/************************************************************************************************** * @fn HalUART_DMAIsrSPI * * @brief Handle the Tx done DMA ISR. * * input parameters * * None. * * output parameters * * None. * * @return None. */ void HalUART_DMAIsrSPI(void) { #if defined HAL_SPI_MASTER /* SPI Master must hold CSn active until Tx flushes */ while (UxCSR & CSR_ACTIVE); while(SPI_RDY_IN()) { SPI_CLOCK_RX(1); } #else spiRdyIsr = 0; #endif UxDBUF = 0x00; /* Clear the garbage */ SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */ spiTxLen = 0; }
/************************************************************************************************** * @fn spiParseRx * * @brief Parse all available bytes from the spiRxBuf[]; parse Rx data into the spiRxDat[]. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void spiParseRx(void) { uint8 done = 0; halIntState_t cs; #ifdef HAL_SPI_MASTER uint8 numNotSOF = 0; uint8 count = 0; SPI_SET_CSn_OUT(); #endif //HAL_SPI_MASTER while (!done) { if (!SPI_NEW_RX_BYTE(spiRxIdx)) { #if defined HAL_SPI_MASTER // Clock a byte from slave SPI_CLOCK_RX(1); #else break; #endif } uint8 ch = SPI_GET_RX_BYTE(spiRxIdx); SPI_CLR_RX_BYTE(spiRxIdx); SPI_LEN_T_INCR(spiRxIdx); #ifdef HAL_SPI_MASTER // If searching for a SOF byte limit the number of bytes searched // to SPI_FRM_LEN if ( spiRxPktState == SPIRX_STATE_SOF ) { count++; numNotSOF = ( ch == SPI_SOF ) ? numNotSOF : numNotSOF + 1; // Haven't recieved an SOF. Assume not a packet but only break if there is // no new bytes in the RX buffer to read if ( numNotSOF > SPI_FRM_LEN && numNotSOF == count ) { // Clear all Rx'ed NULL bytes while(SPI_NEW_RX_BYTE(spiRxIdx)) { SPI_CLR_RX_BYTE(spiRxIdx); SPI_LEN_T_INCR(spiRxIdx); } break; } } #endif //HAL_SPI_MASTER switch (spiRxPktState) { case SPIRX_STATE_SOF: if (ch == SPI_SOF) { spiRxPktState = SPIRX_STATE_LEN; /* At this point, the master has effected the protocol for ensuring that the SPI slave is * awake, so set the spiRxLen to non-zero to prevent the slave from re-entering sleep until * the entire packet is received - even if the master interrupts the sending of the packet * by de-asserting/re-asserting MRDY one or more times */ spiRxLen = 1; } break; case SPIRX_STATE_LEN: if ((ch == 0) || (ch > SPI_MAX_DAT_LEN)) { spiRxPktState = SPIRX_STATE_SOF; spiRxLen = 0; } else { spiRxFcs = spiRxLen = ch; spiRxTemp = spiRxTail; spiRxCnt = 0; spiRxPktState = SPIRX_STATE_DATA; #if defined HAL_SPI_MASTER if (!SPI_NEW_RX_BYTE(spiRxIdx)) /* Fix for simultaneous TX/RX to avoid extra clock pulses to SPI Slave */ { halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); SPI_CLOCK_RX(ch + 1); /* Clock out the SPI Frame Data bytes and FCS */ HAL_EXIT_CRITICAL_SECTION(intState); } #endif } break; case SPIRX_STATE_DATA: spiRxFcs ^= ch; spiRxDat[spiRxTemp] = ch; SPI_LEN_T_INCR(spiRxTemp); if (++spiRxCnt == spiRxLen) { spiRxPktState = SPIRX_STATE_FCS; } break; case SPIRX_STATE_FCS: spiRxPktState = SPIRX_STATE_SOF; #ifdef POWER_SAVING pktFound = TRUE; #endif if (ch == spiRxFcs) { spiRxTail = spiRxTemp; } else { dbgFcsByte = ch; #ifdef RBA_UART_TO_SPI badFcsPktCount++; #endif } spiRxCnt = spiRxLen = 0; #ifdef HAL_SPI_MASTER // Clear any trailing empty Rx'ed bytes // Should only receive one frame per MRDY assertion while(SPI_NEW_RX_BYTE(spiRxIdx)) { SPI_CLR_RX_BYTE(spiRxIdx); SPI_LEN_T_INCR(spiRxIdx); } done = 1; #endif //HAL_SPI_MASTER break; default: HAL_ASSERT(0); break; } } spiTxLen = 0; HAL_ENTER_CRITICAL_SECTION(cs); spiRdyIsr = 0; HAL_EXIT_CRITICAL_SECTION(cs); #ifdef HAL_SPI_MASTER SPI_CLR_CSn_OUT(); #ifdef RBA_UART_TO_SPI // Must wait until slave has ended transaction because // the RBA implementation cannot delay writes so this is a // forced delay.... while(SPI_RDY_IN()); #endif #else SPI_CLR_RDY_OUT(); #endif //HAL_SPI_MASTER }
/************************************************************************************************** * @fn HalUARTPollSPI * * @brief SPI Transport Polling Manager. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void HalUARTPollSPI(void) { #ifdef HAL_SPI_MASTER #else #if defined POWER_SAVING pktFound = FALSE; #endif if ( ( spiRdyIsr ) || (SPI_RDY_IN()) ) { CLEAR_SLEEP_MODE(); #if defined HAL_SBL_BOOT_CODE if(!spiTxLen) { UxDBUF = 0x00; /* Zero out garbage from UxDBUF */ HAL_DMA_ARM_CH(HAL_SPI_CH_RX); /* Arm RX DMA */ asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); SPI_SET_RDY_OUT(); /* SPI_RDYOut = 0 */ SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */ HAL_EXIT_CRITICAL_SECTION(intState); } #endif #if defined POWER_SAVING pktFound = TRUE; #endif } #endif #ifdef HAL_SPI_MASTER if ( spiRdyIsr && !writeActive) { spiParseRx(); } #else //SPI Slave if ( spiRdyIsr && !writeActive ) { if ( !(UxCSR & CSR_ACTIVE) ) { // MRDY has gone low to set spiRdyIsr // and has now gone high if SPI_RDY_IN // is false, read RXed bytes spiParseRx(); } else { // MRDY has gone low and is still low // Set SRDY low to signal ready to RX SPI_SET_RDY_OUT(); } } #endif //HAL_SPI_MASTER #if defined HAL_SPI_MASTER if( SPI_RX_RDY()) #else if (SPI_RX_RDY() && !spiTxLen) #endif { if (spiCB != NULL) { spiCB((HAL_UART_SPI - 1), HAL_UART_RX_TIMEOUT); } } #if defined POWER_SAVING if ( SPI_RDY_IN()|| SPI_RX_RDY() || spiRxLen || spiTxLen || spiRdyIsr || pktFound || SPI_RDY_OUT() ) { CLEAR_SLEEP_MODE(); } else if ( (!pktFound) && (!SPI_NEW_RX_BYTE(spiRxIdx)) ) { PxIEN |= SPI_RDYIn_BIT; SPI_CLR_RDY_OUT(); } #endif }
/************************************************************************************************** * @fn HalUARTWriteSPI * * @brief Transmit data bytes as a SPI packet. * * input parameters * * @param buf - pointer to the memory of the data bytes to send. * @param len - the length of the data bytes to send. * * output parameters * * None. * * @return Zero for any error; otherwise, 'len'. */ static spiLen_t HalUARTWriteSPI(uint8 *buf, spiLen_t len) { // Already in Tx or Rx transaction #ifdef RBA_UART_TO_SPI // The RBA Bridge is not written to handle re-writes so we must // just let it write if (spiTxLen != 0) #else //!RBA_UART_TO_SPI if (spiTxLen != 0 || SPI_RDY_OUT()) #endif { return 0; } if (len > SPI_MAX_DAT_LEN) { len = SPI_MAX_DAT_LEN; } spiTxLen = len; writeActive = 1; #if defined HAL_SPI_MASTER spiTxPkt[SPI_LEN_IDX] = len; (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len); spiCalcFcs(spiTxPkt); spiTxPkt[SPI_SOF_IDX] = SPI_SOF; halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX); HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt)); /* DMA TX might need padding */ /* Abort any pending DMA operations */ HAL_DMA_ABORT_CH( HAL_SPI_CH_RX ); spiRxIdx = 0; (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16)); HAL_DMA_ARM_CH(HAL_SPI_CH_RX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); /* Abort any pending DMA operations */ HAL_DMA_ABORT_CH( HAL_SPI_CH_TX ); HAL_DMA_ARM_CH(HAL_SPI_CH_TX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); SPI_SET_CSn_OUT(); while((!SPI_RDY_IN()) && (!spiRdyIsr) ); HAL_DMA_MAN_TRIGGER(HAL_SPI_CH_TX); #elif !defined HAL_SPI_MASTER #ifdef POWER_SAVING /* Disable POWER SAVING when transmission is initiated */ CLEAR_SLEEP_MODE(); #endif HAL_DMA_ARM_CH(HAL_SPI_CH_RX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); spiTxPkt[SPI_LEN_IDX] = len; (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len); spiCalcFcs(spiTxPkt); spiTxPkt[SPI_SOF_IDX] = SPI_SOF; halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX); HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt) + 1); /* slave DMA TX might drop the last byte */ HAL_DMA_ARM_CH(HAL_SPI_CH_TX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); SPI_SET_RDY_OUT(); #endif return len; }
/************************************************************************************************** * @fn spiParseRx * * @brief Parse all available bytes from the spiRxBuf[]; parse Rx data into the spiRxDat[]. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void spiParseRx(void) { while (1) { if (!SPI_NEW_RX_BYTE(spiRxIdx)) { #if defined HAL_SPI_MASTER if (SPI_RDY_IN() && (spiTxLen == 0)) { SPI_CLOCK_RX(1); continue; } #endif break; } uint8 ch = SPI_GET_RX_BYTE(spiRxIdx); SPI_CLR_RX_BYTE(spiRxIdx); SPI_LEN_T_INCR(spiRxIdx); switch (spiRxPktState) { case SPIRX_STATE_SOF: if (ch == SPI_SOF) { spiRxPktState = SPIRX_STATE_LEN; /* At this point, the master has effected the protocol for ensuring that the SPI slave is * awake, so set the spiRxLen to non-zero to prevent the slave from re-entering sleep until * the entire packet is received - even if the master interrupts the sending of the packet * by de-asserting/re-asserting MRDY one or more times */ spiRxLen = 1; } break; case SPIRX_STATE_LEN: if ((ch == 0) || (ch > SPI_MAX_DAT_LEN)) { spiRxPktState = SPIRX_STATE_SOF; spiRxLen = 0; } else { spiRxFcs = spiRxLen = ch; spiRxTemp = spiRxTail; spiRxCnt = 0; spiRxPktState = SPIRX_STATE_DATA; #if defined HAL_SPI_MASTER if (!SPI_NEW_RX_BYTE(spiRxIdx)) /* Fix for simultaneous TX/RX to avoid extra clock pulses to SPI Slave */ { halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); SPI_CLOCK_RX(ch + 1); /* Clock out the SPI Frame Data bytes and FCS */ HAL_EXIT_CRITICAL_SECTION(intState); } #endif } break; case SPIRX_STATE_DATA: spiRxFcs ^= ch; spiRxDat[spiRxTemp] = ch; SPI_LEN_T_INCR(spiRxTemp); if (++spiRxCnt == spiRxLen) { spiRxPktState = SPIRX_STATE_FCS; } break; case SPIRX_STATE_FCS: spiRxPktState = SPIRX_STATE_SOF; #ifdef POWER_SAVING pktFound = TRUE; #endif SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */ if (ch == spiRxFcs) { spiRxTail = spiRxTemp; } else { dbgFcsByte = ch; #ifdef RBA_UART_TO_SPI badFcsPktCount++; #endif } spiRxCnt = spiRxLen = 0; break; default: HAL_ASSERT(0); break; } } }
/************************************************************************************************** * @fn HalUARTPollSPI * * @brief SPI Transport Polling Manager. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void HalUARTPollSPI(void) { #ifdef HAL_SPI_MASTER #else #if defined POWER_SAVING pktFound = FALSE; #endif if ( ( spiRdyIsr ) || (SPI_RDY_IN()) ) { CLEAR_SLEEP_MODE(); #if defined HAL_SBL_BOOT_CODE if(!spiTxLen) { UxDBUF = 0x00; /* Zero out garbage from UxDBUF */ HAL_DMA_ARM_CH(HAL_SPI_CH_RX); /* Arm RX DMA */ asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); SPI_SET_RDY_OUT(); /* SPI_RDYOut = 0 */ SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1 */ HAL_EXIT_CRITICAL_SECTION(intState); } #endif #if defined POWER_SAVING pktFound = TRUE; #endif } #endif #if defined HAL_SPI_MASTER if (!spiTxLen) #else if ((!spiTxLen) && (!SPI_RDY_IN())) #endif { SPI_CLR_RDY_OUT(); /* SPI_RDYOut = 1; */ spiParseRx(); } #if defined HAL_SPI_MASTER if( SPI_RX_RDY()) #else if (SPI_RX_RDY() && !spiTxLen) #endif { if (spiCB != NULL) { spiCB((HAL_UART_SPI - 1), HAL_UART_RX_TIMEOUT); } } if (!spiTxLen) { if ( SPI_RDY_OUT () ) { SPI_CLR_RDY_OUT(); /* Clear the ready-out signal */ } } #if defined POWER_SAVING if ( SPI_RDY_IN()|| SPI_RX_RDY() || spiRxLen || spiTxLen || spiRdyIsr || pktFound || SPI_RDY_OUT() ) { CLEAR_SLEEP_MODE(); } else if ( (!pktFound) && (!SPI_NEW_RX_BYTE(spiRxIdx)) ) { PxIEN |= SPI_RDYIn_BIT; SPI_CLR_RDY_OUT(); } #endif spiRdyIsr = 0; }
/************************************************************************************************** * @fn HalUARTWriteSPI * * @brief Transmit data bytes as a SPI packet. * * input parameters * * @param buf - pointer to the memory of the data bytes to send. * @param len - the length of the data bytes to send. * * output parameters * * None. * * @return Zero for any error; otherwise, 'len'. */ static spiLen_t HalUARTWriteSPI(uint8 *buf, spiLen_t len) { if (spiTxLen != 0) { return 0; } if (len > SPI_MAX_DAT_LEN) { len = SPI_MAX_DAT_LEN; } spiTxLen = len; #if defined HAL_SPI_MASTER spiRdyIsr = 0; spiTxPkt[SPI_LEN_IDX] = len; (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len); spiCalcFcs(spiTxPkt); spiTxPkt[SPI_SOF_IDX] = SPI_SOF; halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX); HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt)); /* DMA TX might need padding */ /* Abort any pending DMA operations */ HAL_DMA_ABORT_CH( HAL_SPI_CH_RX ); spiRxIdx = 0; (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16)); HAL_DMA_ARM_CH(HAL_SPI_CH_RX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); /* Abort any pending DMA operations */ HAL_DMA_ABORT_CH( HAL_SPI_CH_TX ); HAL_DMA_ARM_CH(HAL_SPI_CH_TX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); SPI_SET_CSn_OUT(); while((!SPI_RDY_IN()) && (!spiRdyIsr) ); HAL_DMA_MAN_TRIGGER(HAL_SPI_CH_TX); #elif !defined HAL_SPI_MASTER #ifdef POWER_SAVING /* Disable POWER SAVING when transmission is initiated */ CLEAR_SLEEP_MODE(); #endif SPI_CLR_RDY_OUT(); HAL_DMA_ARM_CH(HAL_SPI_CH_RX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); if ( SPI_RDY_IN() ) { SPI_SET_RDY_OUT(); } spiTxPkt[SPI_LEN_IDX] = len; (void)memcpy(spiTxPkt + SPI_DAT_IDX, buf, len); spiCalcFcs(spiTxPkt); spiTxPkt[SPI_SOF_IDX] = SPI_SOF; halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_SPI_CH_TX); HAL_DMA_SET_LEN(ch, SPI_PKT_LEN(spiTxPkt) + 1); /* slave DMA TX might drop the last byte */ HAL_DMA_ARM_CH(HAL_SPI_CH_TX); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); asm("NOP"); SPI_SET_RDY_OUT(); #endif return len; }