基于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);
else
SPI0CSPinMuxSetup(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;
}