/**************************************************************************//** * @file spi.c * @version V3.00 * @brief N9H20 series SPI driver source file * * SPDX-License-Identifier: Apache-2.0 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. *****************************************************************************/ /* Header files */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "wblib.h" #include "N9H20_SPI.h" #ifdef __FreeRTOS__ /* Scheduler include files. */ #include "FreeRTOS.h" #include "semphr.h" // the semaphore used to wake the PDMA task when data transfer is finish INT Spi0CsInit, Spi1CsInit; xSemaphoreHandle xSpi0CsSemaphore, xSpi1CsSemaphore; #ifdef __RAK439__ extern void FLASH_LOCK(); extern void FLASH_UNLOCK(); #endif #endif static PFN_DRVSPI_CALLBACK g_pfnSPI0callback = NULL; static PFN_DRVSPI_CALLBACK g_pfnSPI1callback = NULL; /*-----------------------------------------------------------------------------------*/ int spiActive(int port) { if (port == 0) { outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL)|0x01); while(inpw(REG_SPI0_CNTRL) & 0x01); } else { outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL)|0x01); while(inpw(REG_SPI1_CNTRL) & 0x01); } return 0; } /*-----------------------------------------------------------------------------------*/ VOID spiSetGo(UINT8 u8Port) { UINT32 u32Reg; if (u8Port == 0) { u32Reg = inpw(REG_SPI0_CNTRL); outpw(REG_SPI0_CNTRL, u32Reg | GO_BUSY); } else { u32Reg = inpw(REG_SPI1_CNTRL); outpw(REG_SPI1_CNTRL, u32Reg | GO_BUSY); } } /*-----------------------------------------------------------------------------------*/ BOOL spiIsBusy(UINT8 u8Port) { UINT32 u32reg; if(u8Port == 0) u32reg = inpw(REG_SPI0_CNTRL); else u32reg = inpw(REG_SPI1_CNTRL); return ((u32reg & GO_BUSY)?TRUE:FALSE); } /*-----------------------------------------------------------------------------------*/ int spiTxLen(int port, int count, int bitLen) { unsigned int reg; if (port == 0) reg = inpw(REG_SPI0_CNTRL); else reg = inpw(REG_SPI1_CNTRL); if ((count < 0) || (count > 3)) return -1; if ((bitLen <= 0) || (bitLen > 32)) return -1; if (bitLen == 32) reg = reg & 0xffffff07; else reg = (reg & 0xffffff07) | (bitLen << 3); reg = (reg & 0xfffffcff) | (count << 8); if (port == 0) outpw(REG_SPI0_CNTRL, reg); else outpw(REG_SPI1_CNTRL, reg); return 0; } /*-----------------------------------------------------------------------------------*/ void spiSetClock(int port, int clock_by_MHz, int output_by_kHz) { int volatile divider; divider = (clock_by_MHz * 1000) / (2 * output_by_kHz) - 1; if (port == 0) outpw(REG_SPI0_DIVIDER, divider); else outpw(REG_SPI1_DIVIDER, divider); } /*-----------------------------------------------------------------------------------*/ VOID spiSetByteEndin(UINT8 u8Port, E_DRVSPI_OPERATION eOP) { if (u8Port == 0) { if(eOP == eDRVSPI_ENABLE) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) |BYTE_ENDIN); else outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~BYTE_ENDIN); } else { if(eOP == eDRVSPI_ENABLE) outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) |BYTE_ENDIN); else outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~BYTE_ENDIN); } } /*-----------------------------------------------------------------------------------*/ VOID spiEnableInt(UINT8 u8Port) { if(u8Port == 0) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) |IE); else outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) |IE); } /*-----------------------------------------------------------------------------------*/ VOID spiDisableInt(UINT8 u8Port) { if(u8Port == 0) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~IE); else outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~IE); } /*-----------------------------------------------------------------------------------*/ VOID spi0IRQHandler(void) { outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) |IFG); if(g_pfnSPI0callback != NULL) { g_pfnSPI0callback(); } } /*-----------------------------------------------------------------------------------*/ VOID spi1IRQHandler(void) { outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) |IFG); if(g_pfnSPI1callback != NULL) { g_pfnSPI1callback(); } } /*-----------------------------------------------------------------------------------*/ INT32 spiInstallCallBack( UINT8 u8Port, PFN_DRVSPI_CALLBACK pfncallback, PFN_DRVSPI_CALLBACK *pfnOldcallback ) { if (u8Port == 0) { *pfnOldcallback = g_pfnSPI0callback; g_pfnSPI0callback = pfncallback; sysInstallISR(IRQ_LEVEL_7, IRQ_SPIMS0, (PVOID)spi0IRQHandler); sysSetLocalInterrupt(ENABLE_IRQ); sysEnableInterrupt(IRQ_SPIMS0); } else { *pfnOldcallback = g_pfnSPI1callback; g_pfnSPI1callback = pfncallback; sysInstallISR(IRQ_LEVEL_7, IRQ_SPIMS1, (PVOID)spi1IRQHandler); sysSetLocalInterrupt(ENABLE_IRQ); sysEnableInterrupt(IRQ_SPIMS1); } return Successful; } /*-----------------------------------------------------------------------------------*/ static int _spi_init_flag0 = FALSE, _spi_init_flag1 = FALSE; int spiOpen(SPI_INFO_T *pInfo) { int volatile i; if (pInfo->nPort == 0) { if(_spi_init_flag0) { sysprintf("SPI0 pin is unavailable!!\n"); return -1; } if (!_spi_init_flag0) { outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS0_CKE); // enable the clocks of SPI outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST); outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST); for (i=0; i<200; i++); outpw(REG_GPDFUN, inpw(REG_GPDFUN) | 0xFF000000); // enable spi0 pin function if (pInfo->bIsSlaveMode) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x40000); else // master mode outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x40000); if (pInfo->bIsClockIdleHigh) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x800); else // clock idle low outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x800); if (pInfo->bIsLSBFirst) outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) | 0x400); else // MSB first outpw(REG_SPI0_CNTRL, inpw(REG_SPI0_CNTRL) & ~0x400); if (pInfo->bIsAutoSelect) outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x8); else outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x8); if (pInfo->bIsActiveLow) outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x4); else // active high outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x4); if (pInfo->bIsTxNegative) outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising else outpw(REG_SPI0_CNTRL, (inpw(REG_SPI0_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling if (pInfo->bIsLevelTrigger) outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) |SS_LTRIG); else // edge trigger outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~SS_LTRIG); _spi_init_flag0 = TRUE; } } else { if(_spi_init_flag1) { sysprintf("SPI1 pin is unavailable!!\n"); return -1; } if (!_spi_init_flag1) { outpw(REG_APBCLK, inpw(REG_APBCLK) | SPIMS1_CKE); // enable the clocks of SPI outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST); outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST); for (i=0; i<200; i++); outpw(REG_GPBFUN, (inpw(REG_GPBFUN) & ~0x03FC0000) | 0x01540000); // enable spi1 pin function if (pInfo->bIsSlaveMode) outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x40000); else // master mode outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x40000); if (pInfo->bIsClockIdleHigh) outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x800); else // clock idle low outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x800); if (pInfo->bIsLSBFirst) outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) | 0x400); else // MSB first outpw(REG_SPI1_CNTRL, inpw(REG_SPI1_CNTRL) & ~0x400); if (pInfo->bIsAutoSelect) outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x8); else outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x8); if (pInfo->bIsActiveLow) outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x4); else // active high outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x4); if (pInfo->bIsTxNegative) outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x4); // Tx falling; Rx rising else outpw(REG_SPI1_CNTRL, (inpw(REG_SPI1_CNTRL) & ~0x6)| 0x2); // Tx rising; Rx falling if (pInfo->bIsLevelTrigger) outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) |SS_LTRIG); else // edge trigger outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~SS_LTRIG); _spi_init_flag1 = TRUE; } } return 0; } /*-----------------------------------------------------------------------------------*/ INT32 spiClose(UINT8 u8Port) { INT32 i32TimeOut; i32TimeOut = 0x10000; while(spiIsBusy(u8Port)) { if(i32TimeOut-- <= 0) break; } if(i32TimeOut-- <= 0) return -1; if (u8Port == 0) _spi_init_flag0 = FALSE; else _spi_init_flag1 = FALSE; if (u8Port == 0) { outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI0RST); outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI0RST); sysDisableInterrupt(IRQ_SPIMS0); g_pfnSPI0callback = NULL; outpw(REG_APBCLK, inpw(REG_APBCLK) & ~SPIMS0_CKE); // disable the clocks of SPI } else { outpw(REG_APBIPRST, inpw(REG_APBIPRST) | SPI1RST); outpw(REG_APBIPRST, inpw(REG_APBIPRST) & ~SPI1RST); sysDisableInterrupt(IRQ_SPIMS1); g_pfnSPI1callback = NULL; outpw(REG_APBCLK, inpw(REG_APBCLK) & ~SPIMS1_CKE); // disable the clocks of SPI } return Successful; } /*-----------------------------------------------------------------------------------*/ VOID spiIoctl(INT32 spiPort, INT32 spiFeature, INT32 spiArg0, INT32 spiArg1) { switch(spiFeature) { case SPI_SET_CLOCK: spiSetClock(spiPort, spiArg0, spiArg1); break; } } /*-----------------------------------------------------------------------------------*/ INT spiEnable(INT32 spiPort) { if (spiPort == 0) outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) | 0x01); else outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) | 0x01); return 0; } /*-----------------------------------------------------------------------------------*/ INT spiDisable(INT32 spiPort) { if (spiPort == 0) outpw(REG_SPI0_SSR, inpw(REG_SPI0_SSR) & ~0x01); else outpw(REG_SPI1_SSR, inpw(REG_SPI1_SSR) & ~0x01); return 0; } INT spiRead(INT port, INT RxBitLen, INT len, CHAR *pDst) { switch (RxBitLen) { case SPI_32BIT: if (port == 0) outpw(REG_SPI0_TX0, 0xffffffff); else outpw(REG_SPI1_TX0, 0xffffffff); while (len-- > 0) { spiTxLen(port, 0, SPI_32BIT); spiActive(port); if (port == 0) *((INT32 *)pDst) = inpw(REG_SPI0_RX0) & 0xffffffff; else *((INT32 *)pDst) = inpw(REG_SPI1_RX0) & 0xffffffff; pDst += 4; } break; case SPI_16BIT: if (port == 0) outpw(REG_SPI0_TX0, 0xffff); else outpw(REG_SPI1_TX0, 0xffff); while (len-- > 0) { spiTxLen(port, 0, SPI_16BIT); spiActive(port); if (port == 0) *((INT16 *)pDst) = inpw(REG_SPI0_RX0) & 0xffff; else *((INT16 *)pDst) = inpw(REG_SPI1_RX0) & 0xffff; pDst += 2; } break; case SPI_8BIT: if (port == 0) outpw(REG_SPI0_TX0, 0xff); else outpw(REG_SPI1_TX0, 0xff); while (len-- > 0) { spiTxLen(port, 0, SPI_8BIT); spiActive(port); if (port == 0) *((INT8 *)pDst) = inpw(REG_SPI0_RX0) & 0xff; else *((INT8 *)pDst) = inpw(REG_SPI1_RX0) & 0xff; pDst ++; } break; } return 0; } INT spiWrite(INT port, INT TxBitLen, INT len, CHAR *pSrc) { switch (TxBitLen) { case SPI_32BIT: while (len-- > 0) { if (port == 0) outpw(REG_SPI0_TX0, *((INT32 *)pSrc)); else outpw(REG_SPI1_TX0, *((INT32 *)pSrc)); spiTxLen(port, 0, SPI_32BIT); spiActive(port); pSrc += 4; } break; case SPI_16BIT: while (len-- > 0) { if (port == 0) outpw(REG_SPI0_TX0, *((INT16 *)pSrc)); else outpw(REG_SPI1_TX0, *((INT16 *)pSrc)); spiTxLen(port, 0, SPI_16BIT); spiActive(port); pSrc += 2; } break; case SPI_8BIT: while (len-- > 0) { if (port == 0) outpw(REG_SPI0_TX0, *((INT8 *)pSrc)); else outpw(REG_SPI1_TX0, *((INT8 *)pSrc)); spiTxLen(port, 0, SPI_8BIT); spiActive(port); pSrc ++; } break; } return 0; } /*-----------------------------------------------------------------------------------*/ INT spiSSEnable(UINT32 spiPort, UINT32 SSPin, UINT32 ClockMode) { UINT reg; #ifdef __FreeRTOS__ if(spiPort == 0) #ifdef __RAK439__ // flash wait for RAK439 idle if(SSPin == 0) FLASH_LOCK(); #else // wait the CS is idle while (xSemaphoreTake(xSpi0CsSemaphore, portMAX_DELAY) != pdPASS ) ; else while (xSemaphoreTake(xSpi1CsSemaphore, portMAX_DELAY) != pdPASS ) ; #endif #endif reg = inpw(REG_SPI0_CNTRL+0x400*spiPort) & ~0x806; switch (ClockMode) { case 0: outpw(REG_SPI0_CNTRL+0x400*spiPort, reg | 0x004); break; case 1: outpw(REG_SPI0_CNTRL+0x400*spiPort, reg | 0x002); break; case 2: outpw(REG_SPI0_CNTRL+0x400*spiPort, reg | 0x802); break; case 3: outpw(REG_SPI0_CNTRL+0x400*spiPort, reg | 0x804); } outpw(REG_SPI0_SSR+0x400*spiPort, inpw(REG_SPI0_SSR+0x400*spiPort) | (0x01<<SSPin)); return Successful; } /*-----------------------------------------------------------------------------------*/ INT spiSSDisable(UINT32 spiPort, UINT32 SSPin) { outpw(REG_SPI0_SSR+0x400*spiPort, inpw(REG_SPI0_SSR+0x400*spiPort) & ~(0x01<<SSPin)); #ifdef __FreeRTOS__ if (spiPort == 0) #ifdef __RAK439__ // free the mutext which is shared with RAK439 lib if(SSPin == 0) FLASH_UNLOCK(); #else // free the CS xSemaphoreGive(xSpi0CsSemaphore); else xSemaphoreGive(xSpi1CsSemaphore); #endif #endif return Successful; } /*-----------------------------------------------------------------------------------*/ INT spiTransfer(UINT32 port, UINT32 TxBitLen, UINT32 len, PUINT8 RxBuf , PUINT8 TxBuf) { UINT i, transfer_len, u32TxNum; PUINT pU32Rx, pU32Tx; PUINT16 pU16Rx, pU16Tx; PUINT8 pU8Rx, pU8Tx; //sysprintf("len=%d\n", len); switch (TxBitLen) { case SPI_32BIT: pU32Rx = (PUINT)RxBuf; pU32Tx = (PUINT)TxBuf; transfer_len = len / 4; if ( transfer_len ) { outpw(REG_SPI0_CNTRL+0x400*port, inpw(REG_SPI0_CNTRL+0x400*port) |BYTE_ENDIN); u32TxNum = transfer_len%4; if ( !u32TxNum ) u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |((u32TxNum-1) << 8)); for ( i=0; i<u32TxNum ; i++ ) { if (pU32Tx != NULL) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU32Tx++); //else //outpw((REG_SPI0_TX0+0x400*port) + (i<<2), 0xffffffff); } spiActive(port); if (pU32Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU32Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2)); transfer_len -= u32TxNum; u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |((u32TxNum-1) << 8)); while ( transfer_len > 0 ) { for ( i=0; i<u32TxNum ; i++ ) { if (pU32Tx != NULL) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU32Tx++); //else //outpw((REG_SPI0_TX0+0x400*port) + (i<<2), 0xffffffff); } spiActive(port); if (pU32Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU32Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2)); transfer_len -= u32TxNum; } outpw(REG_SPI0_CNTRL+0x400*port, inpw(REG_SPI0_CNTRL+0x400*port) & ~BYTE_ENDIN); } transfer_len = len % 4; if ( transfer_len ) { pU8Rx = (PUINT8)pU32Rx; pU8Tx = (PUINT8)pU32Tx; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |(0x08 << 3)); for ( i=0; i<transfer_len; i++ ) { if (pU8Tx != NULL) outpw(REG_SPI0_TX0+0x400*port, pU8Tx[i]); //else //outpw(REG_SPI0_TX0+0x400*port, 0xff); spiActive(port); if (pU8Rx != NULL) pU8Rx[i] = inpw(REG_SPI0_RX0+0x400*port)&0xFF ; } } break; case SPI_16BIT: pU16Rx = (PUINT16)RxBuf; pU16Tx = (PUINT16)TxBuf; transfer_len = len / 2; if ( transfer_len ) { outpw(REG_SPI0_CNTRL+0x400*port, inpw(REG_SPI0_CNTRL+0x400*port) |BYTE_ENDIN); u32TxNum = transfer_len%4; if ( !u32TxNum ) u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |(((u32TxNum-1) << 8) |(16<<0x03))); for ( i=0; i<u32TxNum ; i++ ) { if (pU16Tx != NULL) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU16Tx++); //else //outpw((REG_SPI0_TX0+0x400*port) + (i<<2), 0xffff); } spiActive(port); if (pU16Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU16Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2))&0xFFFF; transfer_len -= u32TxNum; u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |(((u32TxNum-1) << 8) |(16<<0x03))); while ( transfer_len > 0 ) { for ( i=0; i<u32TxNum ; i++ ) { if (pU16Tx != NULL) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU16Tx++); //else //outpw((REG_SPI0_TX0+0x400*port) + (i<<2), 0xffff); } spiActive(port); if (pU16Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU16Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2))&0xFFFF; transfer_len -= u32TxNum; } outpw(REG_SPI0_CNTRL+0x400*port, inpw(REG_SPI0_CNTRL+0x400*port) & ~BYTE_ENDIN); } transfer_len = len % 2; if ( transfer_len ) { pU8Rx = (PUINT8)pU16Rx; pU8Tx = (PUINT8)pU16Tx; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |(0x08 << 3)); for ( i=0; i<transfer_len; i++ ) { if (pU8Tx != NULL) outpw(REG_SPI0_TX0+0x400*port, pU8Tx[i]); //else //outpw(REG_SPI0_TX0+0x400*port, 0xff); spiActive(port); if (pU8Rx != NULL) pU8Rx[i] = inpw(REG_SPI0_RX0+0x400*port)&0xFF ; } } break; case SPI_8BIT: pU8Rx = RxBuf; pU8Tx = TxBuf; transfer_len = len; u32TxNum = transfer_len%4; if ( !u32TxNum ) u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM | Tx_BIT_LEN)) |(((u32TxNum-1) << 8) |(8<<0x03))); if (pU8Tx != NULL) for ( i=0; i<u32TxNum ; i++ ) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU8Tx++); spiActive(port); if (pU8Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU8Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2))&0xFF; transfer_len -= u32TxNum; u32TxNum = 4; outpw(REG_SPI0_CNTRL+0x400*port, (inpw(REG_SPI0_CNTRL+0x400*port) & ~(Tx_NUM)) |((u32TxNum-1) << 8)); while ( transfer_len > 0 ) { if (pU8Tx != NULL) for ( i=0; i<u32TxNum ; i++ ) outpw((REG_SPI0_TX0+0x400*port) + (i<<2), *pU8Tx++); spiActive(port); if (pU8Rx != NULL) for ( i=0; i< u32TxNum ; i++ ) *pU8Rx++ = inpw((REG_SPI0_RX0+0x400*port) + (i<<2))&0xFF; transfer_len -= u32TxNum; } break; } return Successful; } /*-----------------------------------------------------------------------------------*/ INT spiRtosInit(INT32 spiPort) { #ifdef __FreeRTOS__ // create the semaphore used for SPI two CS if (spiPort == 0) if (Spi0CsInit == 0) { xSpi0CsSemaphore = xSemaphoreCreateBinary(); xSemaphoreGive(xSpi0CsSemaphore); Spi0CsInit = 1; } else if (Spi1CsInit == 0) { xSpi1CsSemaphore = xSemaphoreCreateBinary(); xSemaphoreGive(xSpi1CsSemaphore); Spi1CsInit = 1; } #endif return Successful; }