基于TI SYSBIOS GIO 接口封装的SPI DMA模式

2024-02-28 16:38

本文主要是介绍基于TI SYSBIOS GIO 接口封装的SPI DMA模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于TI SYSBIOS GIO 接口封装的SPI DMA模式

硬件:TMS320C6748 (创龙开发板)
bsp: bios_6_37_03_30

注意:
DMA模式需要先使能EMDA3 TC/CC 通道。初始化EDMA3,
然后再创建SPi handle,
app.cfg 中要静态创建spi1设备并添加ECM 也就是EventCombiner,
var iomFxns5 = “Spi_IOMFXNS”;
var initFxn5 = “user_spi1_init”;
var deviceParams5 = “spiParams”;
var deviceId5 = 1;
GIO.addDeviceMeta("/spi1", iomFxns5, initFxn5, deviceId5, deviceParams5);
ECM.eventGroupHwiNum[0] = 7;
ECM.eventGroupHwiNum[1] = 8;
ECM.eventGroupHwiNum[2] = 9;
ECM.eventGroupHwiNum[3] = 10;

C6748 SPI 除了chip指定的几个片选功能引脚(SPIx_CSn0~7)外,还支持普通GPIO作为片选引脚,
如果使用SPIx_CSn0~7 只需在初始化接口的第二个参数中指定即可,后面两个参数不生效
如果使用普通GPIO作为cs pin, 第二个参数指定TLFS_HAL_SPI_CS_GPIO, 并在后面两个参数中指定具体的gpio, 具体的bank num和 pinnum (bank中的index)请查询手册,

int tlfs_hal_spi_init(TLFS_HAL_SPI_e spi_port, TLFS_HAL_SPI_CS_e cs, unsigned int gpiobank_num, unsigned int Gpio_Pin);

具体代码如下, 仅供参考,有问题还请指出,

/** tlfs_hal_spi.h**  Created on: 2021-12-3*      Author: Bruce Su*/#ifndef TLFS_HAL_SPI_H_
#define TLFS_HAL_SPI_H_#define TLFS_SPI_TRANSFER_MAX_LEN   (16)typedef enum __tlfs_hal_spi__
{TLFS_HAL_SPI0 = 0,TLFS_HAL_SPI1,TLFS_HAL_SPI_MAX
}TLFS_HAL_SPI_e;typedef enum __tlfs_hal_spi_cs__
{TLFS_HAL_SPI_CS0 = 0,TLFS_HAL_SPI_CS1,TLFS_HAL_SPI_CS2,TLFS_HAL_SPI_CS3,TLFS_HAL_SPI_CS4,TLFS_HAL_SPI_CS5,TLFS_HAL_SPI_CS6,TLFS_HAL_SPI_CS7,TLFS_HAL_SPI_CS_GPIO,TLFS_HAL_SPI_CS_MAX
}TLFS_HAL_SPI_CS_e;/*
* cs  = TLFS_HAL_SPI_CS_GPIO 时,gpiobank_num 和 Gpio_Pin 才有效
* GP3[13]  gpiobank_num = 3    Gpio_Pin = 13   gpio num = 3* 16 + 13 + 1 = 62
*/
int tlfs_hal_spi_init(TLFS_HAL_SPI_e spi_port, TLFS_HAL_SPI_CS_e cs, unsigned int gpiobank_num, unsigned int Gpio_Pin);
int tlfs_hal_spi_write(TLFS_HAL_SPI_e spi_port, unsigned char* data, unsigned int len);
int tlfs_hal_spi_read(TLFS_HAL_SPI_e spi_port, unsigned char* data, unsigned int len);#endif /* TLFS_HAL_SPI_H_ */
/** tlfs_hal_spi.c**  Created on: 2021-12-3*      Author: Bruce Su*/#include <xdc/std.h>
#include <string.h>
#include <stdio.h>
#include <xdc/runtime/Memory.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/log.h>
#include <ti/sysbios/knl/task.h>
#include <ti/sysbios/io/GIO.h>
#include <ti/sysbios/io/iom.h>#include <SPI/include/Spi.h>
#include <GPIO/include/Gpio.h>
#include <PSC/Include/Psc.h>#include <edma3_drv.h>
#include <CSLR/cslr_spi.h>
#include "tlfs_hal_spi.h"
#include "TL6748.h"#define SPI1_HW_NUM   (13)
#define SPI1_SPEED    (12000000)typedef struct _tlfs_spi_handle_ {GIO_Handle spi_Handle;unsigned int cs_gpio_num;TLFS_HAL_SPI_CS_e cs;Bool inited;
}TLFS_SPI_Handle_s;static TLFS_SPI_Handle_s tlfs_spi_handle[TLFS_HAL_SPI_MAX];
extern EDMA3_DRV_Handle hEdma;/* Buffer alignement is required when working in DMA Mode */
/* max command length is 4 (opcode + 3 bytes address) + max trnsfer size )    */
#pragma DATA_ALIGN(spi1loopWrite, 128);
Uint8  spi1loopWrite[TLFS_SPI_TRANSFER_MAX_LEN];/* Buffer alignement is required when working in DMA Mode */
#pragma DATA_ALIGN(spi1loopRead, 128);
Uint8  spi1loopRead[TLFS_SPI_TRANSFER_MAX_LEN];#pragma DATA_ALIGN(spi0loopWrite, 128);
Uint8  spi0loopWrite[TLFS_SPI_TRANSFER_MAX_LEN];/* Buffer alignement is required when working in DMA Mode */
#pragma DATA_ALIGN(spi0loopRead, 128);
Uint8  spi0loopRead[TLFS_SPI_TRANSFER_MAX_LEN];/* Global SPI init config data structure */
Spi_Params       spiParams;
static int spi_init_done = 0;EDMA3_DRV_Handle edma3init(unsigned int edma3Id, EDMA3_DRV_Result *);static unsigned int hal_spi_cs_to_csl_cs(TLFS_HAL_SPI_CS_e cs)
{switch(cs){case TLFS_HAL_SPI_CS0:return CSL_SPI_SPIPC0_SCS0FUN0_MASK;case TLFS_HAL_SPI_CS1:return CSL_SPI_SPIPC0_SCS0FUN1_MASK;case TLFS_HAL_SPI_CS2:return CSL_SPI_SPIPC0_SCS0FUN2_MASK;case TLFS_HAL_SPI_CS3:return CSL_SPI_SPIPC0_SCS0FUN3_MASK;case TLFS_HAL_SPI_CS4:return CSL_SPI_SPIPC0_SCS0FUN4_MASK;case TLFS_HAL_SPI_CS5:return CSL_SPI_SPIPC0_SCS0FUN5_MASK;case TLFS_HAL_SPI_CS6:return CSL_SPI_SPIPC0_SCS0FUN6_MASK;case TLFS_HAL_SPI_CS7:return CSL_SPI_SPIPC0_SCS0FUN7_MASK ;case TLFS_HAL_SPI_CS_GPIO:return 0;default:return CSL_SPI_SPIPC0_SCS0FUN0_MASK;}
}static void spi_early_init(void)
{if(spi_init_done == 0){spi_init_done = 1;Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_CC0, TRUE);Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC0, TRUE);Psc_ModuleClkCtrl(Psc_DevId_0, CSL_PSC_TC1, TRUE);Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_CC1, TRUE);Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_GPIO, TRUE);Spi_init();EDMA3_DRV_Result	edmaResult		= 0;// EDMA3 初始化if(hEdma == NULL)hEdma = edma3init(0, &edmaResult);memset(tlfs_spi_handle, 0, TLFS_HAL_SPI_MAX * sizeof(TLFS_SPI_Handle_s));}
}void user_spi1_init()
{spiParams = Spi_PARAMS;spiParams.hwiNumber = SPI1_HW_NUM;spiParams.opMode = Spi_OpMode_DMAINTERRUPT;spiParams.outputClkFreq     = SPI1_SPEED;spiParams.loopbackEnabled   = FALSE;spiParams.edmaHandle        = NULL;spiParams.spiHWCfgData.configDatafmt[0].charLength   = 8;spiParams.spiHWCfgData.configDatafmt[0].clkHigh      = TRUE ;spiParams.spiHWCfgData.configDatafmt[0].lsbFirst     = FALSE;spiParams.spiHWCfgData.configDatafmt[0].oddParity    = FALSE;spiParams.spiHWCfgData.configDatafmt[0].parityEnable = FALSE ;spiParams.spiHWCfgData.configDatafmt[0].phaseIn      = FALSE ;spiParams.spiHWCfgData.configDatafmt[0].waitEnable   = FALSE;spiParams.spiHWCfgData.intrLevel     = TRUE;Psc_ModuleClkCtrl(Psc_DevId_1, CSL_PSC_SPI1, TRUE);spi_early_init();
}int tlfs_hal_spi_init(TLFS_HAL_SPI_e spi_port, TLFS_HAL_SPI_CS_e cs, unsigned int gpiobank_num, unsigned int Gpio_Pin)
{if(spi_port >= TLFS_HAL_SPI_MAX || spi_port < TLFS_HAL_SPI0) return -1;if(tlfs_spi_handle[spi_port].inited) return 0;SPIPinMuxSetup(spi_port);Error_Block 		eb;Spi_ChanParams      chanParams;GIO_Params 			ioParams;/** Initialize channel attributes.*/GIO_Params_init(&ioParams);Error_init(&eb);if(cs == TLFS_HAL_SPI_CS_GPIO){Gpio_Handle 	gpio0 = NULL;tlfs_spi_handle[spi_port].cs_gpio_num = gpiobank_num * 16 + Gpio_Pin + 1;Gpio_PinCmdArg    pinCmdArg;Gpio_Params     gpioParams = Gpio_PARAMS;gpioParams.instNum = 0;gpioParams.BankParams[gpiobank_num].inUse = Gpio_InUse_No;gpioParams.BankParams[gpiobank_num].hwiNum  = 8u;gpioParams.BankParams[gpiobank_num].PinConfInfo[Gpio_Pin].inUse = Gpio_InUse_No;/* open the GPIO driver to get a handle to it */gpio0 = Gpio_open(&gpioParams);if(gpio0 == NULL) return -1;chanParams.hGpio = gpio0;pinCmdArg.pin   = tlfs_spi_handle[spi_port].cs_gpio_num;pinCmdArg.value = Gpio_Direction_Output;Gpio_setPinDir(gpio0, &pinCmdArg);}else{if(spi_port == TLFS_HAL_SPI1)SPI1CSPinMuxSetup(cs);elseSPI0CSPinMuxSetup(cs);}chanParams.hEdma 	= hEdma;ioParams.chanParams = &chanParams;char spi_name[8] = {'\0'};sprintf(spi_name, "/spi%d", spi_port);/* create SPI channel for transmission */tlfs_spi_handle[spi_port].spi_Handle = GIO_create(spi_name, GIO_INOUT, &ioParams, &eb);if (NULL == tlfs_spi_handle[spi_port].spi_Handle){return -1;}tlfs_spi_handle[spi_port].cs = cs;tlfs_spi_handle[spi_port].inited = TRUE;return 0;
}int tlfs_hal_spi_write(TLFS_HAL_SPI_e spi_port, unsigned char* data, unsigned int len)
{SizeT	 size = 0;Spi_DataParam       dataparam;unsigned char* spi_writebuf = NULL;if((data == NULL) || (tlfs_spi_handle[spi_port].inited == FALSE) || (len > TLFS_SPI_TRANSFER_MAX_LEN)) return -1;if(spi_port == TLFS_HAL_SPI0){spi_writebuf = spi0loopWrite;}else{spi_writebuf = spi1loopWrite;}memset(&dataparam, 0x00, sizeof(Spi_DataParam));memcpy(spi_writebuf, data, len);dataparam.bufLen       = len;dataparam.inBuffer     = NULL;dataparam.outBuffer    = spi_writebuf;dataparam.flags    = Spi_CSHOLD;dataparam.dataFormat   = Spi_DataFormat_0;dataparam.chipSelect = hal_spi_cs_to_csl_cs(tlfs_spi_handle[spi_port].cs);if(tlfs_spi_handle[spi_port].cs == TLFS_HAL_SPI_CS_GPIO){dataparam.flags    |= Spi_GPIO_CS;dataparam.gpioPinNum = tlfs_spi_handle[spi_port].cs_gpio_num;}size = dataparam.bufLen;GIO_submit(tlfs_spi_handle[spi_port].spi_Handle, IOM_WRITE, &dataparam, &size, NULL);return 0;
}int tlfs_hal_spi_read(TLFS_HAL_SPI_e spi_port, unsigned char* data, unsigned int len)
{SizeT	 size = 0;Spi_DataParam       dataparam;unsigned char* spi_readbuf = NULL;if((data == NULL) || (tlfs_spi_handle[spi_port].inited == FALSE) || (len > TLFS_SPI_TRANSFER_MAX_LEN)) return -1;if(spi_port == TLFS_HAL_SPI0){spi_readbuf = spi0loopRead;}else{spi_readbuf = spi1loopRead;}memset(&dataparam, 0x00, sizeof(Spi_DataParam));memset(spi1loopRead, 0 ,TLFS_SPI_TRANSFER_MAX_LEN);dataparam.bufLen       = len;dataparam.inBuffer     = spi_readbuf;dataparam.outBuffer    = NULL;dataparam.flags    = Spi_CSHOLD;dataparam.dataFormat   = Spi_DataFormat_0;dataparam.chipSelect = hal_spi_cs_to_csl_cs(tlfs_spi_handle[spi_port].cs);if(tlfs_spi_handle[spi_port].cs == TLFS_HAL_SPI_CS_GPIO){dataparam.flags    |= Spi_GPIO_CS;dataparam.gpioPinNum = tlfs_spi_handle[spi_port].cs_gpio_num;}size = dataparam.bufLen;GIO_submit(tlfs_spi_handle[spi_port].spi_Handle, IOM_WRITE, &dataparam, &size, NULL);memcpy(data, spi_readbuf, len);return 0;
}

这篇关于基于TI SYSBIOS GIO 接口封装的SPI DMA模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/756023

相关文章

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Idea实现接口的方法上无法添加@Override注解的解决方案

《Idea实现接口的方法上无法添加@Override注解的解决方案》文章介绍了在IDEA中实现接口方法时无法添加@Override注解的问题及其解决方法,主要步骤包括更改项目结构中的Languagel... 目录Idea实现接China编程口的方法上无法添加@javascriptOverride注解错误原因解决方

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

详解Java如何向http/https接口发出请求

《详解Java如何向http/https接口发出请求》这篇文章主要为大家详细介绍了Java如何实现向http/https接口发出请求,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 用Java发送web请求所用到的包都在java.net下,在具体使用时可以用如下代码,你可以把它封装成一

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr