📄 ssp.c
字号:
** Descriptions: SSP发送中断调用子函数,内部使用.将软FIFO中的数据写入SSP硬件FIFO中.
** input parameters: psspInfo: 指向SSP设备信息结构体指针.
**
** Returned value: 无返回值.
** Notice: 每次最多发送8个帧.
*********************************************************************************************************/
static void __sspWriteIsrSub (__PSSP_INFO psspInfo)
{
uint8 ucSendData;
uint16 usSendData;
volatile uint16 usQueueByteNum;
const uint16 usSspFrameLen = psspInfo->usSspFrameNum; /* 限制变量参数不可修改,只读 */
uint16 usSendByteNum;
uint32 uiOffsetBase;
volatile uint32 *puiBaseAddr;
__PDATA_QUEUE SspSendQueAddr;
if (psspInfo == NULL) {
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] &= (~(0x01 << 3)); /* 关TxFIFO至少半空中断,防重入 */
return;
}
IRQDisable(); /* 关IRQ中断 */
psspInfo->ucSendIntEn = __SSP_W_INT_ENABLE; /* 标志当前已进入写中断 */
psspInfo->ucSSPState = __SSP_SEND;
uiOffsetBase = psspInfo->uiOffsetBase;
puiBaseAddr = psspInfo->puiAddrBase;
SspSendQueAddr = psspInfo->SspSendQueAddr;
IRQEnable(); /* 开IRQ中断 */
/*
* 状态判断
*/
if (psspInfo->uiSQueueState == __SSP_QUEUE_EMPTY) { /* 判断发送队列是否为空 */
if ((puiBaseAddr[__B_SSP_SSPSR << uiOffsetBase] & (0x01 << 0)) == 1) {
psspInfo->ucSendIntEn = __SSP_W_INT_DISABLE; /* 标志硬写FIFO为空,可软件启动 */
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] &= (~(0x01 << 3)); /* 关TxFIFO至少半空中断,防重入 */
}
return;
}
/*
* 数据写中断处理.
*/
if (SspSendQueAddr->NData == 0) {
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] &= (~(0x01 << 3)); /* 关TxFIFO至少半空中断,防重入 */
return;
}
usQueueByteNum = SspSendQueAddr->NData;
usSendByteNum = (uint16)((usQueueByteNum > (usSspFrameLen)) ? \
((usSspFrameLen) - 1) : (usQueueByteNum - 1));
if (usSendByteNum == 0) {
usSendByteNum = 1;
}
do {
switch (psspInfo->ucDataLen) { /* 根据要发送的数据帧调整数据 */
case 4:
if (QueueRead(&ucSendData,psspInfo->SspSendQueAddr) == QUEUE_OK) {
usSendData = (uint16)(ucSendData & 0xF0); /* 先发高4位 (当帧格式为4位) */
}
break;
case 8:
if (QueueRead(&ucSendData,psspInfo->SspSendQueAddr) == QUEUE_OK) {
usSendData = (uint16)(ucSendData & 0xFF);
}
break;
case 16:
if (QueueRead(&ucSendData,psspInfo->SspSendQueAddr) == QUEUE_OK) {
usSendData = (uint16)(ucSendData << 8);
if (QueueRead(&ucSendData,psspInfo->SspSendQueAddr) == QUEUE_OK) {
usSendData = (uint16)(ucSendData | usSendData);
}
}
break;
default:
break; /* 队列写入错误,退出循环 */
}
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_ENABLE(SSP_CS_Pin);
}
#endif
puiBaseAddr[__B_SSP_SSPDR << uiOffsetBase] = usSendData;
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_DISABLE(SSP_CS_Pin);
}
#endif
if (psspInfo->ucDataLen == 4) {
usSendData = (uint16)(ucSendData & 0x0F); /* 再发低4位 (当帧格式为4位) */
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_ENABLE(SSP_CS_Pin);
}
#endif
puiBaseAddr[__B_SSP_SSPDR << uiOffsetBase] = usSendData;
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_DISABLE(SSP_CS_Pin);
}
#endif
}
} while (--usSendByteNum != 0); /* 当发送未完 */
/*
* 状态标志处理.
*/
IRQDisable(); /* 关IRQ中断 */
if ((puiBaseAddr[__B_SSP_SSPSR << uiOffsetBase] & (0x01 << 0)) == 1) {
psspInfo->ucSendIntEn = __SSP_W_INT_DISABLE; /* 标志硬写FIFO为空,可软件启动 */
if ((SspSendQueAddr->NData - usSendByteNum) == 0) {
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] &= (~(0x01 << 3));
/* 关TxFIFO至少半空中断,防重入 */
}
}
psspInfo->ucSSPState = __SSP_IDLE;
psspInfo->uiSQueueState = (SspSendQueAddr->NData == 0) ? (__SSP_QUEUE_EMPTY) : (__SSP_QUEUE_NO_FULL);
psspInfo->uiHardSFIFOState = ((puiBaseAddr[__B_SSP_SSPSR << uiOffsetBase] & (0x01 << 1)) == 0) ? \
(__SSP_FIFO_FULL) : (__SSP_FIFO_NO_FULL);
IRQEnable(); /* 开IRQ中断 */
}
/*********************************************************************************************************
** Function name: __sspReadIsrSub
**
** Descriptions: SSP接收中断调用子函数,内部使用.
** input parameters: psspInfo: 指向SSP设备信息结构体指针.
**
** Returned value: 无返回值.
** Notice: 无论是4, 8, 16位 / 帧,都作为一次8位入队处理.读取SSP硬件FIFO数据,缓存入软FIFO中.
*********************************************************************************************************/
static void __sspReadIsrSub (__PSSP_INFO psspInfo)
{
uint8 ucRecvData;
uint16 usRecvData;
uint16 usReadByteNum;
const uint16 usSspFrameLen = (uint32)psspInfo->usSspFrameNum; /* 限制变量参数不可修改,只读 */
uint32 uiOffsetBase;
volatile uint32 *puiBaseAddr;
__PDATA_QUEUE SspRecvQueAddr;
if (psspInfo == NULL) {
return;
}
IRQDisable();
psspInfo->ucSSPState = __SSP_RECIEVE;
if (psspInfo->uiRQueueState == __SSP_QUEUE_FULL) { /* 判断是否收队列为满 */
return;
}
IRQEnable(); /* 开IRQ中断 */
uiOffsetBase = psspInfo->uiOffsetBase;
puiBaseAddr = psspInfo->puiAddrBase;
SspRecvQueAddr = psspInfo->SspRecvQueAddr;
usReadByteNum = usSspFrameLen;
do {
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_ENABLE(SSP_CS_Pin);
}
#endif
usRecvData = (uint16)puiBaseAddr[__B_SSP_SSPDR << uiOffsetBase];
#if SSP_CS_GPIO > 0
if (psspInfo->ucMasterSlave == 0) {
__SSP_CS_DISABLE(SSP_CS_Pin);
}
#endif
if (psspInfo->ucDataLen == 16) {
ucRecvData = (uint8)(usRecvData >> 8); /* 高8位入队 */
if (QueueWrite(SspRecvQueAddr,ucRecvData) != QUEUE_OK) {
break;
}
}
ucRecvData = (uint8)(usRecvData & 0xFF); /* 低8位入队 */
if (QueueWrite(SspRecvQueAddr,ucRecvData) != QUEUE_OK) {
break;
}
}while (((puiBaseAddr[__B_SSP_SSPSR << uiOffsetBase] & 0x01 << 2) != 0) &&
(--usReadByteNum != 0)); /* 当硬FIFO未空,未发完8帧,继续 */
/*
* 状态标志处理.
*/
IRQDisable(); /* 关IRQ中断 */
psspInfo->ucSSPState = __SSP_IDLE;
psspInfo->uiHardRFIFOState = ((puiBaseAddr[__B_SSP_SSPSR << uiOffsetBase] & 0x01 << 3) == 1) ? \
(__SSP_FIFO_FULL) : (__SSP_FIFO_NO_FULL);
if ((SspRecvQueAddr->NData) >= (SspRecvQueAddr->MaxData)) { /* 软FIFO已满 */
psspInfo->uiRQueueState = __SSP_QUEUE_FULL;
} else {
psspInfo->uiRQueueState = __SSP_QUEUE_NO_FULL;
}
IRQEnable(); /* 开IRQ中断 */
}
/*********************************************************************************************************
** Function name: __sspIsrNone
**
** Descriptions: SSP中断空处理调用子函数,内部使用.
** input parameters: psspInfo: 指向SSP设备信息结构体指针.
**
** Returned value: 无返回值.
*********************************************************************************************************/
static void __sspIsrNone (__PSSP_INFO psspInfo)
{
uint32 uiOffsetBase;
volatile uint32 *puiBaseAddr;
volatile uint32 uiTmp = 0;
psspInfo = psspInfo;
uiOffsetBase = __GpSSPInfoData[__SSP0]->uiOffsetBase;
puiBaseAddr = __GpSSPInfoData[__SSP0]->puiAddrBase;
/*
* 清空所有的中断
*/
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] &= (~(0x01 << 3)); /* 关TxFIFO至少半空中断,防重入 */
uiTmp = puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase]; /* 清读一半中断 */
puiBaseAddr[__B_SSP_SSPIMSC << uiOffsetBase] = uiTmp; /* 清写一半中断 */
puiBaseAddr[__B_SSP_SSPICR << uiOffsetBase] |= 0x03; /* 清除接收中断标志 */
return;
}
/*********************************************************************************************************
** Defination: 函数指针数组来调用各个中断状态处理函数.
**
** Descriptions: 安装SSP中断调用子函数,内部使用.
** Notice: 只对至少一半空/满状态进行读写中断处理.
**********************************************************************************************************/
static void (* const __sspIsrFun[16]) (__PSSP_INFO psspInfo) = {
__sspIsrNone, __sspIsrNone, __sspReadIsrSub, __sspIsrNone,
__sspReadIsrSub, __sspIsrNone, __sspReadIsrSub, __sspIsrNone,
__sspWriteIsrSub, __sspIsrNone, __sspReadIsrSub, __sspIsrNone,
__sspReadIsrSub, __sspIsrNone, __sspReadIsrSub, __sspIsrNone
};
/*********************************************************************************************************
** Function name: ssp0Isr
** Descriptions: SSP0中断服务函数
** Transfer Functions: __sspIsrFunInstall(); 中断处理函数指针安装函数.
** ssp0Hook(); 钩子函数,存放用户处理中断代码.
** input parameters: 无
** Returned value: 无
*********************************************************************************************************/
void ssp0Isr (void)
{
uint32 uiOffsetBase;
volatile uint32 *puiBaseAddr;
uint32 uiStateNum;
uint32 uiSspIntState;
uiOffsetBase = __GpSSPInfoData[__SSP0]->uiOffsetBase;
puiBaseAddr = __GpSSPInfoData[__SSP0]->puiAddrBase;
uiSspIntState = puiBaseAddr[__B_SSP_SSPMIS << uiOffsetBase]; /* 获取中断状态号 */
uiStateNum = uiSspIntState & 0x0F;
puiBaseAddr[__B_SSP_SSPICR << uiOffsetBase] |= 0x03; /* 清除接收中断标志 */
(*__sspIsrFun[uiStateNum ])(__GpSSPInfoData[__SSP0]); /* 调用对应状态中断处理函数 */
ssp0Hook(); /* 调用钩子函数 */
VICVectAddr = 0x00; /* 清除内核中断逻辑 */
}
#endif /* SSP_FUN_LIB */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -