S3C2416 SPI中断方式实现

来源:互联网 发布:子曰法语之言能无从乎 编辑:程序博客网 时间:2024/06/07 02:15

samsung S3C2416支持HS_SPI(高速串行外设接口),是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为PCB的布局上节省空间,提供方便,正是出于这种简单易用的特性,如今越来越多的芯片集成了这种通信协议。

将2416作为SPI主站与MCP2515通讯,s3c2416采用SPI中断方式处理发送和接收。

考虑到MCP2515spi协议,采用一问一答方式,中断处理中需严格遵循一条完整指令中的发送和接收,即发送完应马上处理需要的接收。

spi中断处理流程:

1.初始化SPI和中断

void SpiRegInit(PCAN_INFO pCan_info)
{
rCH_CFG |= (1<<5);//软件复位
rCH_CFG &= ~(1<<5);


rCH_CFG = (0<<4) | (0<<3) | (0<<2) | (0<<1) | (0<<0);


rCLK_CFG = PCLK/((2*SPICLK)+1);//时钟配置
rCLK_CFG |= (0<<9) | (1<<8);


rMODE_CFG = (rMODE_CFG & ~0x1fffffff) | TRAIL_CNT(0x3FF) | MODE_BUS_SZ_BYTE | TX_TRIG_LVL(0x1);//配置模式寄存器
//RX_TRIG_LVL(1);// | TX_TRIG_LVL(0x4);
//rSPI_INT_EN = 0;
rPACKET_CNT = 1<<16;//启用接收包数量控制
rSWAP_REG = 0;
rFB_Clk_sel = 0x3;//Feedback clock selecting register. 


#if 1
SPIINT_Init();
DebugPrint("[*CH_CFG %08X]\n", rCH_CFG);
#endif


nSSHigh(); //片选寄存器inactive
}

2.发送数据申请和接收数据申请

   发送数据申请 

    rSPI_INT_EN |= INT_TX_FIFORDY;//开启准备发送中断

   接收申请

   这里可以按需设置触发等级来触发接收fifo准备中断,触发等级为0~64字节

    rMODE_CFG |= RX_TRIG_LVL(1); //设置接收中断触发等级

    rSPI_INT_EN |= INT_TX_FIFORDY; //开启接收中断

3.中断处理发送接收

   VOID __irq MCP2515_SPIINTHandler(void)
{
PMCP2515_SPIINFO pSpiInfo = &Mcp2515_spi;
DWORD pspi_data;
DWORD  status, modecfg;
BYTE  OperTotal;
INT   i = 0;
ULONG TotalTimeOut, Count=0;


rINTMSK |= (((DWORD)0x1)<<(pSpiInfo->dwSPIINTNo-0x20));//屏蔽SPI0中断
ClearPending(1 << (pSpiInfo->dwSPIINTNo-0x20));//清除悬而未决中断源

status = rSPI_STATUS;//获取SPI状态

rPENDING_CLR |= (1<<4) | (1<<3) | (1<<2) | (1<<1);//清楚SPI中断

if (status & STUS_TX_FIFORDY)//判断发送中断
{
if(!g_bCSValid) {
MCP2515_CS_VALID;//拉低CS片选引脚
nSSLow(); //设置slave_selection_reg寄存器nssout active
g_bCSValid = TRUE;
}
OperTotal = 64 - ((status>>6) & 0x7f);
rPENDING_CLR = 0x1f;

while (i<OperTotal && GetQueToRead(&pSpiInfo->TxQue.Que, &pspi_data, (DWORD)1, FALSE))
{
rSPI_TX_DATA = *((BYTE *)pspi_data);
ChangeQueOut(&pSpiInfo->TxQue.Que, 1, FALSE);
i++;
}

TotalTimeOut = WRITE_TIME_OUT_CONSTANT*50 + (WRITE_TIME_OUT_MULTIPLIER)*(i-1);
TXDone(TotalTimeOut);//等待发送完成
rCH_CFG &= ~CH_TXCH_ON;

if (g_byReadReg)
{
rCH_CFG |= CH_RXCH_ON; 
rSPI_INT_EN |= INT_RX_FIFORDY;
}
}
else if (status & STUS_RX_FIFORDY /*|| status & STUS_TRAILCNT_ZERO*/)//接收中断
{
BYTE rrtmp[5] = {0};
i = 0;
OperTotal = (status>>13) & 0x7f;//data level in RX fifo
TotalTimeOut = READ_TIME_OUT_CONSTANT*50 + (READ_TIME_OUT_MULTIPLIER)*OperTotal;

while(i<OperTotal && GetQueToWrite(&pSpiInfo->RxQue.Que, &pspi_data, 1, FALSE))
{
*((BYTE *)pspi_data) = rSPI_RX_DATA;
ChangeQueIn(&pSpiInfo->RxQue.Que, 1, FALSE);
i++;
}

rCH_CFG &= ~CH_RXCH_ON;
g_byReadReg = 0;
}

if (!g_byReadReg)
{
nSSHigh();
MCP2515_CS_INVALID;

rPACKET_CNT = 0;
rCH_CFG |= CH_SW_RST;
rCH_CFG &= ~CH_SW_RST;
//CAN_Delay(100);
DebugPrint("[<<<CS Invalid>>>]\n");
g_bCSValid = FALSE;
}


ClearPending(1 << (pSpiInfo->dwSPIINTNo-0x20));
rINTMSK &= ~(((DWORD)0x1)<<(pSpiInfo->dwSPIINTNo-0x20));//取消屏蔽
}

4.调试过程

  a.当Packet_Count_reg(Ch0)= 1<<16 | (1)时,发送数据时只能发送1个字节的数据,其余数据在FIFO中发布出去。这个问题比较奇怪,不知道是我的SPI配置有问题还是S3C2416的bug?还望有知道的童鞋解释解释。

    

原创粉丝点击