开发板:AM335X
编译环境:css
qq:956465349
gdut15级本科
最近在移植rtos的spi-loopback的测试程序到am335x开发板上 顺便把相关的操作函数源码给分析了下
移植的是pdk_am335x_1_0_5\packages\ti\drv\spi\example\mcspiLoopbackApp的测试程序
spi的基础知识可以看我觉得不错的博客
http://blog.csdn.net/skyflying2012/article/details/11710801
一开始跑的肯定是main函数
一开始程序先跑Main程序
int main(void)
{
/* Call board init functions */
Board_initCfg boardCfg;
/* 我们的开发板是am335x 所以这里会执行 */
#if defined(SOC_AM335x) || defined (SOC_AM437x)
Task_Handle task;
Error_Block eb;
Error_init(&eb);
/* 创建spi任务 main函数最终会执行spi_test函数 */
task = Task_create(spi_test, NULL, &eb);
/* 判断Task_create是否成功 这里是成功 */
if (task == NULL) {
System_printf("Task_create() failed!\n");
BIOS_exit(0);
}
#endif
boardCfg = BOARD_INIT_PINMUX_CONFIG |
BOARD_INIT_MODULE_CLOCK |
BOARD_INIT_UART_STDIO;
/* 根据boardCfg的参数判断 执行相关的初始化函数 */
Board_init(boardCfg);
SPI_log("Board_init succeed. \n");
#if defined(SOC_AM572x) || defined (SOC_AM571x)
MCSPI_Board_crossbarInit();
#endif
/* Start BIOS */
BIOS_start();
return (0);
}
main函数主要就创建了一个任务 名字叫做spi_test也就是我们的主要程序处理
并且设置boardCfg的参数调用Board_init进行相关的初始化
进行
Board_STATUS Board_init(Board_initCfg cfg)
{
/*定义int型变量ret来当函数返回值判断 */
Board_STATUS ret = BOARD_SOK;
/* DDR3的PLL时钟设置 */
if (cfg & BOARD_INIT_PLL)
ret = Board_PLLInit();
if (ret != BOARD_SOK)
return ret;
/* 单板模块时钟的初始化 */
if (cfg & BOARD_INIT_MODULE_CLOCK)
ret = Board_moduleClockInit();
if (ret != BOARD_SOK)
return ret;
/* DDR初始化 */
if (cfg & BOARD_INIT_DDR)
ret = Board_DDR3Init();
if (ret != BOARD_SOK)
return ret;
/* ICSS管脚初始化 */
if (cfg & BOARD_INIT_ICSS_PINMUX)
{
/* 设置flags 判断是否是icssPinmux */
icssPinMuxFlag = 1U;
ret = Board_pinmuxConfig();
}
/* 管脚配置初始化 */
else if (cfg & BOARD_INIT_PINMUX_CONFIG)
{
ret = Board_pinmuxConfig();
}
if (ret != BOARD_SOK)
return ret;
/* 标准输入输出串口初始化 */
if (cfg & BOARD_INIT_UART_STDIO)
ret = Board_uartStdioInit();
if (ret != BOARD_SOK)
return ret;
return ret;
}
根据main函数中cfg参数色设置这里只执行三个函数
Board_moduleClockInit();
Board_pinmuxConfig();
Board_uartStdioInit();
分别分析三个初始化函数
这里主要关注的是串口和MCSPI时钟的初始化
Board_STATUS Board_moduleClockInit()
{
int32_t status;
/* UART时钟 */
/* UART0 UART1 UART3 UART4 */
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 0U, 0U);
if(S_PASS == status)
{
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 1U, 0U);
}
if(S_PASS == status)
{
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 3U, 0U);
}
if(S_PASS == status)
{
status = PRCMModuleEnable(CHIPDB_MOD_ID_UART, 4U, 0U);
}
....
/* MCSPI */
if(S_PASS == status)
{/* SPI0 SPI1 */
status = PRCMModuleEnable(CHIPDB_MOD_ID_MCSPI, 0U, 0U);
}
if(S_PASS == status)
{
status = PRCMModuleEnable(CHIPDB_MOD_ID_MCSPI, 1U, 0U);
}
...
}
这里其实就是根据前面的时钟判断来决定后面时钟的配置
如果有一个模块没使能成功 那么后面的都不能执行 所以这里得判断是否前面的没有使能成功 而影响后面的mcspi的使能
大致的分析下有关的模块使能 第一个是模块ID每个模块都有自己独立的ID 第二个是某个模块的号码 比如UART1 UART0这些
#ifndef BUILDCFG_MOD_MCSPI
#define BUILDCFG_MOD_MCSPI
#endif /* BUILDCFG_MOD_MCSPI */
/** Peripheral Pin Configurations */
#ifndef BUILDCFG_MOD_UART
#define BUILDCFG_MOD_UART
#endif /* BUILDCFG_MOD_UART */
int32_t PRCMModuleEnable(chipdbModuleID_t moduleId, uint32_t instNum,
uint32_t isBlockingCall)
{
int32_t status = S_PASS;
switch(moduleId)
{
...
#if defined(BUILDCFG_MOD_UART)
case CHIPDB_MOD_ID_UART:
{
switch(instNum)
{
case 0:
enableModule(SOC_CM_WKUP_REGS, CM_WKUP_UART0_CLKCTRL,
CM_WKUP_CLKSTCTRL,
CM_WKUP_CLKSTCTRL_CLKACTIVITY_UART0_GFCLK);
break;
case 1:
enableModule(SOC_CM_PER_REGS, CM_PER_UART1_CLKCTRL,
CM_PER_L4LS_CLKSTCTRL,
CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK);
break;
case 2:
enableModule(SOC_CM_PER_REGS, CM_PER_UART2_CLKCTRL,
CM_PER_L4LS_CLKSTCTRL,
CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK);
break;
case 3:
enableModule(SOC_CM_PER_REGS, CM_PER_UART3_CLKCTRL,
CM_PER_L4LS_CLKSTCTRL,
CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK);
break;
case 4:
enableModule(SOC_CM_PER_REGS, CM_PER_UART4_CLKCTRL,
CM_PER_L4LS_CLKSTCTRL,
CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK);
break;
case 5:
enableModule(SOC_CM_PER_REGS, CM_PER_UART5_CLKCTRL,
CM_PER_L4LS_CLKSTCTRL,
CM_PER_L4LS_CLKSTCTRL_CLKACTIVITY_UART_GFCLK);
break;
}
}
break;
#endif /* if defined(BUILDCFG_MOD_UART) */
...
#if defined(BUILDCFG_MOD_MCSPI)
case CHIPDB_MOD_ID_MCSPI:
{
/* 两次调用 所以SPI0和SPI1都能使能时钟 */
switch(instNum)
{
case 0:
enableModule(SOC_CM_PER_REGS, CM_PER_SPI0_CLKCTRL,
CM_PER_L3_CLKSTCTRL, CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK);
break;
case 1:
enableModule(SOC_CM_PER_REGS, CM_PER_SPI1_CLKCTRL,
CM_PER_L3_CLKSTCTRL, CM_PER_L3_CLKSTCTRL_CLKACTIVITY_L3_GCLK);
break;
}
}
break;
#endif /* if defined(BUILDCFG_MOD_MCSPI) */
...
return status;
}
可以分析下enableModule参数是什么使能模块的时钟的 其实只是往寄存器里写进入相关位 使能时钟并且判断
void enableModule(uint32_t domainOffset, uint32_t clkCtrlReg,
uint32_t clkStCtrlReg, uint32_t clkActMask)
{
/* Enable the module */
/* */
HW_WR_REG32(domainOffset + clkCtrlReg, PRCM_MODULEMODE_ENABLE);
/* Check for module enable status */
while(PRCM_MODULEMODE_ENABLE !=
(HW_RD_REG32(domainOffset + clkCtrlReg) & PRCM_MODULEMODE_MASK));
/* Check clock activity - ungated */
while(clkActMask != (HW_RD_REG32(domainOffset + clkStCtrlReg) & clkActMask));
/* Check idle status value - should be in functional state */
while((PRCM_MODULE_IDLEST_FUNC << PRCM_IDLE_ST_SHIFT) !=
(HW_RD_REG32(domainOffset + clkCtrlReg) & PRCM_IDLE_ST_MASK));
}
如果没设置成功的话就会死循环在这 所以要么没有运行enableModule要么就执行
把SPI1的初始化时钟代入可得
enableModule(0x44E00000, 0x50,
0xc, 0x00000010u);
void enableModule(uint32_t domainOffset, uint32_t clkCtrlReg,
uint32_t clkStCtrlReg, uint32_t clkActMask)
{
/* Enable the module */
/* */
HW_WR_REG32(0x44E00000 + 0x50, 2);
/* Check for module enable status */
while(2 != (HW_RD_REG32(0x44E00000 + 0x50) & 3));
/* Check clock activity - ungated */
while(0x00000010u != (HW_RD_REG32(0x44E00000 + 0x50) & 0x00000010u));
/* Check idle status value - should be in functional state */
while((PRCM_MODULE_IDLEST_FUNC << PRCM_IDLE_ST_SHIFT) !=
(HW_RD_REG32(domainOffset + clkCtrlReg) & PRCM_IDLE_ST_MASK));
}
查询手册0x44E00050寄存器 就是CM_PER_SPI1_CLKCTRL [1:0]设置为0x2就是初始化了使能了模块的时钟
下面的是
Board_pinmuxConfig();这个函数对pinmux配置
Board_STATUS Board_pinmuxConfig (void)
{
int32_t status;
/* UART */
status = PINMUXModuleConfig(CHIPDB_MOD_ID_UART, 0U, NULL);
if(S_PASS == status)
{
status = PINMUXModuleConfig(CHIPDB_MOD_ID_UART, 1U, NULL);
}
if(S_PASS == status)
{
status = PINMUXModuleConfig(CHIPDB_MOD_ID_UART, 3U, NULL);
}
if(S_PASS == status)
{
status = PINMUXModuleConfig(CHIPDB_MOD_ID_UART, 4U, NULL);
}
....
/* MCSPI */
/* */
if(S_PASS == status)
{
status = PINMUXModuleConfig(CHIPDB_MOD_ID_MCSPI, 0U, NULL);
}
if(S_PASS == status)
{
status = PINMUXModuleConfig(CHIPDB_MOD_ID_MCSPI, 1U, NULL);
}
...
return BOARD_SOK;
}
这里的写法也是跟模块时钟使能函数的写法类似 都是判断前面一个函数执行成功与否来决定后面的执行与否 只要有一个错误 所以这里调试也要加判断 万一前面的出错 那么后面的都执行不了
int32_t PINMUXModuleConfig(chipdbModuleID_t moduleId, uint32_t instNum,
void* pParam1)
{
pinmuxModuleCfg_t* pModuleData = NULL;
pinmuxPerCfg_t* pInstanceData = NULL;
volatile const pinmuxBoardCfg_t* pPinmuxData = NULL;
uint32_t ctrlModBase = CHIPDBBaseAddress(CHIPDB_MOD_ID_CONTROL_MODULE, 0);
int32_t status = E_FAIL;
uint32_t index = 0;
/* Get module Data */
// pPinmuxData = gGpevmPinmuxData;
/* 设置pPinmuxData为icv2pinux gIceV2PinmuxData有相关单板的引脚设置等 这里非常重要 */
pPinmuxData = gIceV2PinmuxData;
ASSERT(NULL != pPinmuxData);
status = E_INVALID_MODULE_ID;
for(index = 0; ((S_PASS != status) &&
(CHIPDB_MOD_ID_INVALID != pPinmuxData[index].moduleId)); index++)
{
if(pPinmuxData[index].moduleId == moduleId)
{
pModuleData = pPinmuxData[index].modulePinCfg;
ASSERT(NULL != pModuleData);
status = S_PASS;
}
}
/* Get instance Data */
if(S_PASS == status)
{
status = E_INST_NOT_SUPP;
for(index = 0; ((S_PASS != status) &&
(CHIPDB_INVALID_INSTANCE_NUM != pModuleData[index].modInstNum)); index++)
{
if(pModuleData[index].modInstNum == instNum)
{
pInstanceData = pModuleData[index].instPins;
ASSERT(NULL != pInstanceData)
status = S_PASS;
}
}
}
/* Configure Pinmux */
if(S_PASS == status)
{
for(index = 0; ((uint16_t)PINMUX_INVALID_PIN !=
pInstanceData[index].pinOffset); index++)
{
if(NULL != pParam1)
{
if(pInstanceData[index].optParam == *(uint16_t*)pParam1)
{
HW_WR_REG32((ctrlModBase + pInstanceData[index].pinOffset),
pInstanceData[index].pinSettings);
status = S_PASS;
break;
}
}
else
{
HW_WR_REG32((ctrlModBase + pInstanceData[index].pinOffset),
pInstanceData[index].pinSettings);
}
}
if((NULL != pParam1) && ((uint16_t)PINMUX_INVALID_PIN == pInstanceData[index].pinOffset))
{
status = E_FAIL;
}
}
/* 将相关的引脚复用 */
HW_WR_REG32(1155598688,49);
HW_WR_REG32(1155598692,17);
/* */
HW_WR_REG32(1155598736,19); //44E10990 10011
HW_WR_REG32(1155598740,51);
HW_WR_REG32(1155598744,51);
HW_WR_REG32(1155598748,19);
return status;
}
所以boart_init()主要做了Clock Module Peripheral Registers 外部模块的时钟 相关引脚的设置初始化 还要串口的设置初始化之类的工作
然后开始执行spi_test这个函数 这个函数是我们主要做的事情
/*
* ======== test function ========
*/
void spi_test(UArg arg0, UArg arg1)
{
//SPI_Params spiParams; /* SPI params structure */
//SPI_Handle handle; /* SPI handle */
SPI_Transaction transaction; /* SPI transaction */
int32_t retVal; /* return value */
SPI_log("\n McSPI Internal Loopback test app started \n");
SPI_log("\n The Mode of transfer is Interrupt Mode \n");
/* Modify the default SPI configurations if necessary */
/* 修改SPI配置 */
spi_initConfig();
/* SPI驱动的初始化 */
/* Init SPI driver */
SPI_init();
/* Open MCSPI instance 1 driver */
/* 打开SPI驱动 */
gSpiHandle = SPI_open(MCSPI_INSTANCE, &gSpiParams);
if(gSpiHandle == NULL)
{
printf("\nError opening MCSPI driver\n");
}
/* SPI_RX 和SPI_TX的缓冲区初始化 */
McSPIInitializeBuffers();
/* 设置transaction结构体 也就是数据传输三要素 源 目的 长度 */
transaction.count = McSPI_DATA_COUNT;
transaction.txBuf = gTxBuffer;
transaction.rxBuf = gRxBuffer;
SPI_transfer(gSpiHandle, &transaction);
/* 对SPI_RX接受到的数据和SPI_TX发送的数据 比对 如果一致说明spi读写成功 */
retVal = McSPIVerifyData();
if(retVal != 0)
{
SPI_log("\n McSPI Data Transmission is Failed \n");
}
else
{
SPI_log("\n McSPI Data Transmission is successful \n");
}
/* 关闭SPI驱动 */
SPI_close(gSpiHandle);
while(1);
}
先是spi_initConfig();执行这个函数
void spi_initConfig(void)
{
SPI_v1_HWAttrs spi_cfg;
/* 获取默认的spi配置 保存在spi_cfg中 */
/* Get the default UART init configurations */
SPI_socGetInitCfg(MCSPI_INSTANCE, &spi_cfg);
/* Modify the default SPI configurations if necessary */
/* 修改spi_cfg的内容 */
spi_cfg.dataLineCommMode = MCSPI_DATA_LINE_COMM_MODE_4;
/* Set the default UART init configurations */
/* 修改后再写进去设置 */
SPI_socSetInitCfg(MCSPI_INSTANCE, &spi_cfg);
}
具体的实现分析 也可以看看
int32_t SPI_socGetInitCfg(uint32_t index, SPI_v1_HWAttrs *cfg)
{
int32_t ret = 0;
if (index < CSL_MCSPI_PER_CNT)
{
*cfg = spiInitCfg[index];
}
else
{
ret = -1;
}
return ret;
}
/* SPI configuration structure */
SPI_v1_HWAttrs spiInitCfg[CSL_MCSPI_PER_CNT] =
{
{
SOC_SPI_0_REGS,
65,
91,
SPI_PINMODE_4_PIN,
MCSPI_DATA_LINE_COMM_MODE_1,
MCSPI_CHANNEL_1,
MCSPI_SINGLE_CH,
MCSPI_CS_POL_LOW,
true,
48000000U,
},
{
SOC_SPI_1_REGS,
125,
92,
SPI_PINMODE_4_PIN,
MCSPI_DATA_LINE_COMM_MODE_1,
MCSPI_CHANNEL_0,
MCSPI_SINGLE_CH,
MCSPI_CS_POL_LOW,
true,
48000000U,
},
};
所以SPI_socGetInitCfg就是将spiInitCfg[CSL_MCSPI_PER_CNT]内容赋值给spi_cfg中 相反SPI_socSetInitCfg就是将spi_cfg赋值给spiInitCfg[CSL_MCSPI_PER_CNT]中
我们使用的是spi1所以MCSPI_INSTANCE就要设置为1 这个变量决定了使用spi0还是spi1 我们设置为1说明使用的是spiInitCfg[1] 看下这个参数的设置
/*!
* @brief SPI_v1 Hardware attributes
*/
typedef struct SPI_v1_HWAttrs_s {
/*! SPI_v1 Peripheral base address */
uint32_t baseAddr;
/*! SPI_v1 Peripheral interrupt vector */
uint32_t intNum;
/*! SPI_v1 Peripheral interrupt vector */
uint32_t eventId;
/*! pin mode 3 or 4 pin mode */
uint32_t pinMode;
/*! data lines mode : which lines are used for tx */
uint32_t dataLineCommMode;
/*! Channel number */
uint32_t chNum;
/*! Channel mode: Single channel or multi channel */
uint32_t chMode;
/*! Polarity of the chip select signal */
uint32_t csPolarity;
/*! Polarity of the chip select signal */
bool enableIntr;
/*! Module input clock frequency */
uint32_t inputClkFreq;
} SPI_v1_HWAttrs;
{
SOC_SPI_1_REGS,
125,
92,
SPI_PINMODE_4_PIN,
MCSPI_DATA_LINE_COMM_MODE_1,
MCSPI_CHANNEL_0,
MCSPI_SINGLE_CH,
MCSPI_CS_POL_LOW,
true,
48000000U,
},
替换也就是
{
/*! SPI_v1 Peripheral base address */
0x481A0000,
/*! SPI_v1 Peripheral interrupt vector */
125,
/*! SPI_v1 Peripheral interrupt vector */
92,
/*! pin mode 3 or 4 pin mode */
SPI_PINMODE_4_PIN,
uint32_t dataLineCommMode;
MCSPI_DATA_LINE_COMM_MODE_1,
/*! Channel mode: Single channel or multi channel */
MCSPI_CHANNEL_0,
/*! Polarity of the chip select signal */
MCSPI_SINGLE_CH,
/*! Module input clock frequency */
/**
* \brief Chip select is held low during active state
*/
MCSPI_CS_POL_LOW,
true,
/*! Module input clock frequency */
48000000U,
},
/**
* \brief Communication on Data line pins is configured as :
* Data line 0 (SPIDAT[0]) selected for reception
* Data line 1 (SPIDAT[1]) selected for transmission
* No transmission on Data Line 0 (SPIDAT[0])
*/
#define MCSPI_DATA_LINE_COMM_MODE_1 (((uint32_t) MCSPI_CH0CONF_IS_LINE0 << \
MCSPI_CH0CONF_IS_SHIFT) | \
((uint32_t) MCSPI_CH0CONF_DPE1_ENABLED << \
MCSPI_CH0CONF_DPE1_SHIFT) | \
((uint32_t) MCSPI_CH0CONF_DPE0_DISABLED \
<< MCSPI_CH0CONF_DPE0_SHIFT))
也就是SPIDAT[0]作为RX 而SPIDAT[1]作为TX
/**
* \brief Communication on Data line pins is configured as :
* Data line 1 (SPIDAT[1]) selected for reception
* Data line 1 (SPIDAT[1]) selected for transmission
* Data Line 0 (SPIDAT[0]) selected for transmission
*/
#define MCSPI_DATA_LINE_COMM_MODE_4 (((uint32_t) MCSPI_CH0CONF_IS_LINE1 << \
MCSPI_CH0CONF_IS_SHIFT) | \
((uint32_t) MCSPI_CH0CONF_DPE1_ENABLED << \
MCSPI_CH0CONF_DPE1_SHIFT) | \
((uint32_t) MCSPI_CH0CONF_DPE0_ENABLED << \
MCSPI_CH0CONF_DPE0_SHIFT))
从上面的配置可以得知MCSPI被设置一下模式
寄存器正确 McSPI1 Registers:0x481A0000
寄存器地址为0x481A0000
中断号为125
eventId为92
4引脚模式 CLK SPIDAT[0] SPIDAT[1] CS
数据线引脚模式设置为MCSPI_DATA_LINE_COMM_MODE_1 但是后面会设置为MCSPI_DATA_LINE_COMM_MODE_4也就是
SPIDAT[0] SPIDAT[1]可以用来发送 但是SPIDAT[1]可以用来接收
MCSPI_CHANNEL_0被选通
单CHANNEL模式 也就是只使用一个通道 MCSPI_CHANNEL_0
片选CS低电平有效
时钟频率为48000000U
然后就执行SPI_init(void)函数初始化SPI驱动
void SPI_init(void)
{
if (SPI_count == -1) {
/* Call each driver's init function */
for (SPI_count = 0; SPI_config[SPI_count].fxnTablePtr != NULL; SPI_count++) {
SPI_config[SPI_count].fxnTablePtr->initFxn((SPI_Handle)&(SPI_config[SPI_count]));
}
}
}
依次调用SPI_config中SPI_FxnTable_v1的SPI_init_v1函数执行初始化
static void SPI_init_v1(SPI_Handle handle)
{
/* Input parameter validation */
OSAL_Assert(handle == NULL);
/* Mark the object as available */
((SPI_v1_Object *)(handle->object))->isOpen = (bool)false;
SPI_log("\n SPI_init_v1 succeed \n");
}
设置handle->object的isOpen是false 保证SPI在spi_open前未被打开
/* SPI configuration structure */
const SPI_config_list SPI_config = {
{
&SPI_FxnTable_v1,
&SpiObjects[0],
&spiInitCfg[0]
},
{
&SPI_FxnTable_v1,
&SpiObjects[1],
&spiInitCfg[1]
},
{
&QSPI_FxnTable_v1,
&QspiObjects[0],
&qspiInitCfg[0]
},
/* "pad to full predefined length of array" */
{NULL, NULL, NULL},
{NULL, NULL, NULL},
{NULL, NULL, NULL},
{NULL, NULL, NULL}
};
所以这里就会依次调用这里三个的初始化函数
然后下面的结构体根据“`
/* SPI parameters structure Master mode*/
SPI_Params gSpiParams = {
SPI_MODE_BLOCKING, /* transferMode */
SemaphoreP_WAIT_FOREVER,/* transferTimeout */
NULL, /* transferCallbackFxn */
SPI_MASTER, /* mode */
1000000, /* bitRate */
8, /* dataSize */
SPI_POL0_PHA0, /* frameFormat */
NULL /* custom */
};
就调用SPI_open()
gSpiHandle = SPI_open(MCSPI_INSTANCE, &gSpiParams);
static SPI_Handle SPI_open_v1(SPI_Handle handle, const SPI_Params *params)
{
SemaphoreP_Params semParams;
uint32_t key;
SPI_v1_Object *object = NULL;
SPI_v1_HWAttrs const *hwAttrs = NULL;
HwiP_Params hwiInputParams;
uint8_t ret_flag = 0u;
/* 检查handle是否为空 为空就挂起 也就是死循环 */
/* Input parameter validation */
OSAL_Assert(handle == NULL);
/* Get the pointer to the object and hwAttrs */
/* 获得spi_open函数传进来的handle里的object和hwAttrs */
/* object就是前面SPI_config里的&SpiObjects[1] 在之前的spi_init中设置了isopen = false */
/* hwAttrs就是SPI_v1_HWAttrs */
object = handle->object;
hwAttrs = handle->hwAttrs;
/* 空函数 ti未编写此函数 所以什么都不执行 */
SPI_osalHwiParamsInit(&hwiInputParams);
/* Determine if the device index was already opened */
/* 空函数 ti未编写此函数 所以什么都不执行 */
key = SPI_osalHardwareIntDisable();
/* 判断object->isOpen参数是true or false 前面我们spi_init里设置里false 所以这里执行else部分 */
if(object->isOpen == true) {
/* 说明已经open过 就不做任何处理 把handle设置为NULL */
SPI_osalHardwareIntRestore(key);
handle = NULL;
}
else
{
/* Mark the handle as being used */
/* 把flag设置为true 代表已经被open 防止被再次open */
object->isOpen = (bool)true;
/* 空函数 ti未编写此函数 所以什么都不执行 */
SPI_osalHardwareIntRestore(key);
/* Store the SPI parameters */
/* 判断params是否为空 如果为空就是用默认的params 如果自行设置了 就把object->spiParams赋值为我们设置的spiParams */
/* 这里我们只是把transferTimeout 修改为了SemaphoreP_WAIT_FOREVER 也就是无限等待 默认是0 */
if (params == NULL) {
/* No params passed in, so use the defaults */
SPI_Params_init(&(object->spiParams));
params = &(object->spiParams);
}
else {
object->spiParams = *params;
}
/* 判断params->dataSize是否在4~32内 如果不在就挂起死循环 我们设置的8所以不受这里影响 */
OSAL_Assert(!((params->dataSize >= 4) && (params->dataSize <= 32)));
/* Determine if we need to use an 8-bit or 16-bit framesize for the DMA */
/* 为DMA设置frameSize为SPI_v1_8bit或者SPI_v1_16bit 这里我们是8 所以frameSize设置SPI_v1_8bit */
object->frameSize = (params->dataSize < 9) ? SPI_v1_8bit : SPI_v1_16bit;
/* Store the current mode. Extract operating mode from hwAttrs and params */
/* 判断是否是SPI_MODE_BLOCKING或者SPI_MODE_CALLBACK 我们这里是SPI_MODE_BLOCKING模式 */
if(SPI_MODE_BLOCKING == params->transferMode)
{
/* 设置的true 执行这里object->operMode保存SPI_OPER_MODE_BLOCKING */
if(true == hwAttrs->enableIntr)
{
object->operMode = SPI_OPER_MODE_BLOCKING;
}
else
{
object->operMode = SPI_OPER_MODE_POLLING;
}
}
else
{
object->operMode = SPI_OPER_MODE_CALLBACK;
}
/* Extract actual mode */
/* 设置object->spiMode为MCSPI_TX_RX_MODE 为下面FIFO设置 */
if(SPI_MASTER == params->mode)
{
object->spiMode = MCSPI_TX_RX_MODE;
}
else
{
object->spiMode = MCSPI_TX_RX_MODE;
}
/* 前面设置了object->operMode为SPI_OPER_MODE_BLOCKING 所以这里执行if */
if(object->operMode != SPI_OPER_MODE_POLLING)
{
/* 设置hwiInputParams结构体的相关值并且调用SPI_osalRegisterInterrupt注册中断 */
/* 不过在am335x这里 SPI_osalRegisterInterrupt直接返回了-1的指针 不做任何处理 */
hwiInputParams.name = NULL;
hwiInputParams.arg = (uintptr_t)handle;
hwiInputParams.priority = 0x20;
hwiInputParams.evtId = hwAttrs->eventId;
object->hwi = SPI_osalRegisterInterrupt(hwAttrs->intNum,
SPI_v1_hwiFxn, &hwiInputParams);
/* 不执行 */
if(object->hwi == NULL) {
SPI_close_v1(handle);
ret_flag = 1u;
handle = NULL;
}
}
/* 执行这里 ret_flag = 0 */
if(ret_flag == 0u)
{
/*
* Construct thread safe handles for this SPI peripheral
* Semaphore to provide exclusive access to the QSPI peripheral
*/
/* am335x对osal不做任何处理 */
SPI_osalSemParamsInit(&semParams);
semParams.mode = SemaphoreP_Mode_BINARY;
object->mutex = SPI_osalCreateBlockingLock(1U, &semParams);
if (object->operMode == SPI_OPER_MODE_BLOCKING) {
/*
* Construct a semaphore to block task execution for the duration of the
* SPI transfer
*/
object->transferComplete = SPI_osalCreateBlockingLock(0U, &semParams);
/* Store internal callback function */
object->transferCallbackFxn = &SPI_transferCallback_v1;
}
if (object->operMode == SPI_OPER_MODE_CALLBACK){
/* Check to see if a callback function was defined for async mode */
OSAL_Assert(params->transferCallbackFxn == NULL);
/* Save the callback function pointer */
object->transferCallbackFxn = params->transferCallbackFxn;
}
object->transaction = NULL;
/* Extract clock mode from the frame format */
/* 我们选择的是SPI_POL0_PHA0 也就是时钟相位和时钟极性为00 */
switch(params->frameFormat)
{
case SPI_POL0_PHA0:
object->clockMode = MCSPI_CLK_MODE_0;
break;
case SPI_POL0_PHA1:
object->clockMode = MCSPI_CLK_MODE_1;
break;
case SPI_POL1_PHA0:
object->clockMode = MCSPI_CLK_MODE_2;
break;
case SPI_POL1_PHA1:
object->clockMode = MCSPI_CLK_MODE_3;
break;
default:
object->clockMode = MCSPI_CLK_MODE_2;
break;
}
/* Reset SPI Peripheral */
/* 重新设置SPI周围 这里都是设置MCSPI_SYSCONFIG的某些位 这里MCSPI_SYSCONFIG寄存器地址正确110H偏移量 */
McSPIReset(hwAttrs->baseAddr);
/* 设置MCSPI_SYSCONFIG寄存器的一些值 */
MCSPISysConfigSetup(hwAttrs->baseAddr, MCSPI_CLOCKS_OCP_ON_FUNC_ON,
MCSPI_SIDLEMODE_NO, MCSPI_WAKEUP_DISABLE,
MCSPI_AUTOIDLE_OFF);
/* Configure 3 pin or 4 pin mode */
/* 我们这里设置的是SPI_PINMODE_4_PIN 也就是SCLK D0 D1 CS四个pin */
if(SPI_PINMODE_3_PIN == hwAttrs->pinMode)
{
/* Disable chip select pin.*/
McSPICSDisable(hwAttrs->baseAddr);
}
else
{
/* Enable chip select pin.*/
/* 设置MCSPI_MODULCTRL寄存器的PIN34为0 也就是SPIEN is used as a chip select. */
McSPICSEnable(hwAttrs->baseAddr);
}
/* 我们设置的是SPI_MASTER 执行if里 */
if(SPI_MASTER == params->mode)
{
/* Enable SPI Master */
/* 设置MCSPI_MODULCTRL寄存器的MS为0 也就是设置为Master 设置*/
McSPIMasterModeEnable(hwAttrs->baseAddr);
/* Configure the peripheral as single channel SPI Master */
/* 设置寄存器设置single channel mode4之类的 设置MCSPI_CH0CONF的IS, DPE0, DPE1为100 */
McSPIMasterModeConfig(hwAttrs->baseAddr,
hwAttrs->chMode,
object->spiMode,
hwAttrs->dataLineCommMode,
hwAttrs->chNum);
/* Clock configuration */
/* 时钟配置*/
McSPIClkConfig(hwAttrs->baseAddr,
hwAttrs->inputClkFreq,
params->bitRate,
hwAttrs->chNum,
object->clockMode);
}
else
{
/* Enable SPI Slave */
McSPISlaveModeEnable(hwAttrs->baseAddr);
/* Configure the peripheral as single channel SPI Master */
McSPIMasterModeConfig(hwAttrs->baseAddr,
hwAttrs->chMode,
object->spiMode,
hwAttrs->dataLineCommMode,
hwAttrs->chNum);
}
/* Set word length for corresponding channel */
/* 设置MCSPI_CH0CONF的WL为00111 8bits */
McSPIWordLengthSet(hwAttrs->baseAddr, MCSPI_WORD_LENGTH(params->dataSize),
hwAttrs->chNum);
/* TBC: Below function added for DIAG. Need to check if this needs in any
special case or generic function. */
/* Set polarity of SPIEN to low.*/
/* 设置MCSPI_CH0CONF的EPOL为1 也即是Set polarity of SPIEN to low */
McSPICSPolarityConfig(hwAttrs->baseAddr,hwAttrs->csPolarity,
hwAttrs->chNum);
/* Enable FIFO's dependent on which mode of operation is chosen */
/* 前面设置object->spiMode == MCSPI_TX_RX_MODE为MCSPI_TX_RX_MODE */
if(object->spiMode == MCSPI_TX_RX_MODE) {
object->fifoSize = RX_TX_FIFO_SIZE;
/* 写入寄存器MCSPI_CH0CONF的27位为1 也就是The buffer is used to transmit data 设置为发送 */
McSPITxFIFOConfig(hwAttrs->baseAddr, MCSPI_TX_FIFO_ENABLE,
hwAttrs->chNum);
/* 写入寄存器MCSPI_CH0CONF的28位为1 也就是The buffer is used to receive data 设置为接收 */
McSPIRxFIFOConfig(hwAttrs->baseAddr, MCSPI_RX_FIFO_ENABLE,
hwAttrs->chNum);
}
else if (object->spiMode == MCSPI_TX_ONLY_MODE) {
object->fifoSize = 60;
McSPITxFIFOConfig(hwAttrs->baseAddr, MCSPI_TX_FIFO_ENABLE,
hwAttrs->chNum);
McSPIRxFIFOConfig(hwAttrs->baseAddr, MCSPI_RX_FIFO_DISABLE,
hwAttrs->chNum);
}
else {
/* RX_ONLY Mode */
object->fifoSize = 60;
McSPITxFIFOConfig(hwAttrs->baseAddr, MCSPI_TX_FIFO_DISABLE,
hwAttrs->chNum);
McSPIRxFIFOConfig(hwAttrs->baseAddr, MCSPI_RX_FIFO_ENABLE,
hwAttrs->chNum);
}
}
}
SPI_log("\n SPI_open_v1 succeed \n");
return (handle);
}
可见被设置为BLOCKING 模式
传送模式是BLOCKING 还有一种是Callback
主模式SPI_MASTER
时序中的时钟相位和时钟极性为SPI_POL0_PHA0 也就是00模式
传输数据大小为8位
然后就是初始化gTxBuffer和gRxBuf```
static void McSPIInitializeBuffers(void)
{
uint32_t index = 0;
for (index = 0; index < McSPI_DATA_COUNT; index++)
{
/* Initialize the gTxBuffer McSPI1 with a known pattern of data */
gTxBuffer[index] = index;
/* Initialize the gRxBuffer McSPI1 with 0 */
gRxBuffer[index] = (uint32_t) 0;
/*gRxBuffer被设置为0 gTxBuffer被设置为0,1,2....29*/
}
}
transaction.count = McSPI_DATA_COUNT;
transaction.txBuf = gTxBuffer;
transaction.rxBuf = gRxBuffer;
static bool SPI_transfer_v1(SPI_Handle handle, SPI_Transaction *transaction)
{
uint32_t key;
SPI_v1_Object *object = NULL;
bool ret_val = false;
/* Input parameter validation */
/* 检查handle和transaction是否为空 之前我们设置了 所以这里不为空 */
OSAL_Assert(!((handle != NULL) && (transaction != NULL)));
/* 设置标志位为SPI_TRANSFER_STARTED 说明传输开始 */
transaction->status=SPI_TRANSFER_STARTED;
/* transaction->count = 50 */
if (transaction->count != 0)
{
/* Get the pointer to the object */
object = handle->object;
/* Check if a transfer is in progress */
key = SPI_osalHardwareIntDisable();
if (object->transaction)
{
SPI_osalHardwareIntRestore(key);
transaction->status=SPI_TRANSFER_CANCELED;
/* Transfer is in progress */
ret_val = (bool)false;
}
else
{
/* 保存transaction到object->transaction */
/* Save the pointer to the transaction */
object->transaction = transaction;
/* Acquire the lock for this particular I2C handle */
SPI_osalPendLock(object->mutex, SemaphoreP_WAIT_FOREVER);
/* 调用这个传输函数 前面都是判断 这个函数才是真正传输数据的功能函数 */
SPI_primeTransfer_v1(handle, transaction);
SPI_osalHardwareIntRestore(key);
if (object->operMode == SPI_OPER_MODE_BLOCKING)
{
SPI_osalPendLock(object->transferComplete, SemaphoreP_WAIT_FOREVER);
}
/* Release the lock for this particular I2C handle */
SPI_osalPostLock(object->mutex);
/* 发送成功 */
transaction->status=SPI_TRANSFER_COMPLETED;
SPI_log("\n SPI_transfer_v1 succeed \n");
ret_val = (bool)true;
}
}
else
{
transaction->status=SPI_TRANSFER_CANCELED;
}
return (ret_val);
}是真正的发送数据功能
static void SPI_primeTransfer_v1(SPI_Handle handle, SPI_Transaction *transaction)
{
SPI_v1_Object *object = NULL;
SPI_v1_HWAttrs const *hwAttrs = NULL;
uint32_t channelStatus = 0;
uint32_t countIndex;
/* Input parameter validation */
OSAL_Assert(!((handle != NULL) && (transaction != NULL)));
/* Get the pointer to the object and hwAttrs */
hwAttrs = handle->hwAttrs;
object = handle->object;
/* 赋值 */
object->writeBufIdx = transaction->txBuf;
object->writeCountIdx = transaction->count;
object->readBufIdx = transaction->rxBuf;
object->readCountIdx = transaction->count;
/* Set FIFO XFER levels */
/* object->fifoSize = 32 设置bject->rxTrgLevel和object->txTrgLevel 的大小 */
if (transaction->count <= object->fifoSize) {
/* Transaction fits entirely in FIFO */
object->rxTrgLevel = transaction->count;
object->txTrgLevel = transaction->count;
}
else {
/*
* Transaction count is more than FIFO size, set TX trigger level
* to FIFO size, set RX trigger level to (FIFO size - 2) to prevent
* TX FIFO under run
*/
object->rxTrgLevel = object->fifoSize - 2;
object->txTrgLevel = object->fifoSize;
}
/* MCSPI_XFERLEVEL的AFL和AEL 应该是29 */
McSPIFIFOTrigLvlSet(hwAttrs->baseAddr, object->rxTrgLevel,
object->txTrgLevel, object->spiMode);
/* Set number of words to be transmitted */
/* 设置MCSPI_XFERLEVEL的WCNT为30 传输的大小 MCSPI_XFERLEVEL的WCNT应该是30 */
McSPIWordCountSet(hwAttrs->baseAddr, transaction->count);
if(SPI_SLAVE == object->spiParams.mode)
{
for (countIndex = 0; countIndex < (object->txTrgLevel); countIndex++)
{
McSPITransmitData(hwAttrs->baseAddr,
(uint32_t) (*object->writeBufIdx), hwAttrs->chNum);
object->writeBufIdx++;
object->writeCountIdx--;
}
}
/* Enable the McSPI channel for communication */
/* 设置MCSPI_CHCTRL的EN为1 也正确 使能Channel0 使能后就开始数据的传输 */
McSPIChannelEnable(hwAttrs->baseAddr, hwAttrs->chNum);
/* Interrupt Mode */
if(object->operMode != SPI_OPER_MODE_POLLING)
{
/* 设置MCSPI_SYST的SSB为0 设置MCSPI_IRQSTATUS的第0 2 17位为1 */
McSPIIntStatusClear(hwAttrs->baseAddr,
MCSPI_INT_TX_EMPTY(hwAttrs->chNum) |
MCSPI_INT_RX_FULL(hwAttrs->chNum) |
MCSPI_INT_EOWKE);
if(SPI_MASTER == object->spiParams.mode)
{
/* 将上面设置寄存器的相关位数清0 */
McSPIIntEnable(hwAttrs->baseAddr,
MCSPI_INT_TX_EMPTY(hwAttrs->chNum) |
MCSPI_INT_RX_FULL(hwAttrs->chNum) |
MCSPI_INT_EOWKE);
/* Assert un-used chip select (Force SPIEN) */
McSPICSAssert(hwAttrs->baseAddr, hwAttrs->chNum);
}
else
{
/* 不执行 */
/* 设置MCSPI_CHCONF的FORCE为1 */
McSPIIntEnable(hwAttrs->baseAddr, MCSPI_INT_RX_FULL(hwAttrs->chNum));
}
}
/* Polling mode */
else
{
if(SPI_MASTER == object->spiParams.mode)
{
/* SPIEN line is forced to low state.*/
McSPICSAssert(hwAttrs->baseAddr, hwAttrs->chNum);
}
/* Polling mode transfer */
while (0 != object->readCountIdx)
{
channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr,
hwAttrs->chNum);
if(SPI_MASTER == object->spiParams.mode)
{
while (0U == (channelStatus & CSL_MCSPI_CH0STAT_TXS_MASK))
{
channelStatus = 0;
channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr,
hwAttrs->chNum);
}
McSPITransmitData(hwAttrs->baseAddr,
(uint32_t) (*object->writeBufIdx), hwAttrs->chNum);
object->writeBufIdx++;
object->writeCountIdx--;
}
while (0U == (channelStatus & CSL_MCSPI_CH0STAT_RXS_MASK))
{
channelStatus = 0;
channelStatus = McSPIChannelStatusGet(hwAttrs->baseAddr,
hwAttrs->chNum);
}
*object->readBufIdx = (uint8_t)McSPIReceiveData(hwAttrs->baseAddr,
hwAttrs->chNum);
(object->readBufIdx)++;
object->readCountIdx--;
if(SPI_SLAVE == object->spiParams.mode)
{
if (0 != object->writeCountIdx)
{
McSPITransmitData(hwAttrs->baseAddr,
(uint32_t) (*object->writeBufIdx), hwAttrs->chNum);
(object->writeBufIdx)++;
object->writeCountIdx--;
}
}
}
if(SPI_MASTER == object->spiParams.mode)
{
/* Force SPIEN line to the inactive state.*/
McSPICSDeAssert(hwAttrs->baseAddr, hwAttrs->chNum);
}
/* Disable the McSPI channel.*/
McSPIChannelDisable(hwAttrs->baseAddr, hwAttrs->chNum);
object->transaction = NULL;
}
}
“`