/************************************************************************************************** * @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 HalUARTInitDMA * * @brief Initialize the UART * * @param none * * @return none *****************************************************************************/ static void HalUARTInitDMA(void) { halDMADesc_t *ch; #if (HAL_UART_DMA == 1) PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0. #else PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1. #endif PxSEL |= HAL_UART_Px_SEL; // Enable Peripheral control of Rx/Tx on Px. p0.2 P0.3 set peripheral //i0 setting UxCSR = CSR_MODE; // Mode is UART Mode. UxUCR = UCR_FLUSH; // Flush it. P2DIR &= ~P2DIR_PRIPO; //ÓÅÏȼ¶ P2DIR |= HAL_UART_PRIPO; if (DMA_PM) { // Setup GPIO for interrupts by falling edge on DMA_RDY_IN. PxIEN |= DMA_RDYIn_BIT; PICTL |= PICTL_BIT; HAL_UART_DMA_CLR_RDY_OUT(); PxDIR |= DMA_RDYOut_BIT; } #if !HAL_UART_TX_BY_ISR // Setup Tx by DMA. ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX ); // Abort any pending DMA operations (in case of a soft reset). HAL_DMA_ABORT_CH( HAL_DMA_CH_TX ); // The start address of the destination. HAL_DMA_SET_DEST( ch, DMA_UxDBUF ); // Using the length field to determine how many bytes to transfer. HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); // One byte is transferred each time. HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE ); // The bytes are transferred 1-by-1 on Tx Complete trigger. HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE ); HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX ); // The source address is incremented by 1 byte after each transfer. HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 ); // The destination address is constant - the Tx Data Buffer. HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 ); // The DMA Tx done is serviced by ISR in order to maintain full thruput. HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE ); // Xfer all 8 bits of a byte xfer. HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); // DMA has highest priority for memory access. HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH); #endif // Setup Rx by DMA. ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX ); // Abort any pending DMA operations (in case of a soft reset). HAL_DMA_ABORT_CH( HAL_DMA_CH_RX ); // The start address of the source. HAL_DMA_SET_SOURCE( ch, DMA_UxDBUF ); // Using the length field to determine how many bytes to transfer. HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx. * The byte after the Rx Data Buffer is the Baud Cfg Register, * which always has a known value. So init Rx buffer to inverse of that * known value. DMA word xfer will flip the bytes, so every valid Rx byte * in the Rx buffer will be preceded by a DMA_PAD char equal to the * Baud Cfg Register value. */ HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD ); // The bytes are transferred 1-by-1 on Rx Complete trigger. HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED ); HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX ); // The source address is constant - the Rx Data Buffer. HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 ); // The destination address is incremented by 1 word after each transfer. HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 ); HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf ); HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX ); // The DMA is to be polled and shall not issue an IRQ upon completion. HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE ); // Xfer all 8 bits of a byte xfer. HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); // DMA has highest priority for memory access. HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH); volatile uint8 dummy = *(volatile uint8 *)DMA_UxDBUF; // Clear the DMA Rx trigger. HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX); HAL_DMA_ARM_CH(HAL_DMA_CH_RX); (void)memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX * sizeof(uint16)); }
/************************************************************************************************** * @fn HalUARTInitSPI * * @brief Initialize the SPI UART Transport. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void HalUARTInitSPI(void) { #if (HAL_UART_SPI == 1) PERCFG &= ~HAL_UART_PERCFG_BIT; /* Set UART0 I/O to Alt. 1 location on P0 */ #else PERCFG |= HAL_UART_PERCFG_BIT; /* Set UART1 I/O to Alt. 2 location on P1 */ #endif #if defined HAL_SPI_MASTER PxSEL |= HAL_UART_Px_SEL_M; /* SPI-Master peripheral select */ UxCSR = 0; /* Mode is SPI-Master Mode */ UxGCR = 15; /* Cfg for the max Rx/Tx baud of 2-MHz */ UxBAUD = 255; #elif !defined HAL_SPI_MASTER PxSEL |= HAL_UART_Px_SEL_S; /* SPI-Slave peripheral select */ UxCSR = CSR_SLAVE; /* Mode is SPI-Slave Mode */ #endif UxUCR = UCR_FLUSH; /* Flush it */ UxGCR |= BV(5); /* Set bit order to MSB */ P2DIR &= ~P2DIR_PRIPO; P2DIR |= HAL_UART_PRIPO; /* Setup GPIO for interrupts by falling edge on SPI_RDY_IN */ PxIEN |= SPI_RDYIn_BIT; PICTL |= PICTL_BIT; SPI_CLR_RDY_OUT(); PxDIR |= SPI_RDYOut_BIT; /* Setup Tx by DMA */ halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_SPI_CH_TX ); /* Abort any pending DMA operations (in case of a soft reset) */ HAL_DMA_ABORT_CH( HAL_SPI_CH_TX ); /* The start address of the destination */ HAL_DMA_SET_DEST( ch, DMA_UxDBUF ); /* Using the length field to determine how many bytes to transfer */ HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); /* One byte is transferred each time */ HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE ); /* The bytes are transferred 1-by-1 on Tx Complete trigger */ HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE ); HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX ); /* The source address is incremented by 1 byte after each transfer */ HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 ); HAL_DMA_SET_SOURCE( ch, spiTxPkt ); /* The destination address is constant - the Tx Data Buffer */ HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 ); /* The DMA Tx done is serviced by ISR */ HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE ); /* Xfer all 8 bits of a byte xfer */ HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); /* DMA has highest priority for memory access */ HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH ); /* Setup Rx by DMA */ ch = HAL_DMA_GET_DESC1234( HAL_SPI_CH_RX ); /* Abort any pending DMA operations (in case of a soft reset) */ HAL_DMA_ABORT_CH( HAL_SPI_CH_RX ); /* The start address of the source */ HAL_DMA_SET_SOURCE( ch, DMA_UxDBUF ); /* Using the length field to determine how many bytes to transfer */ HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx. * The byte after the Rx Data Buffer is the Baud Cfg Register, * which always has a known value. So init Rx buffer to inverse of that * known value. DMA word xfer will flip the bytes, so every valid Rx byte * in the Rx buffer will be preceded by a DMA_PAD char equal to the * Baud Cfg Register value. */ HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD ); /* The bytes are transferred 1-by-1 on Rx Complete trigger */ HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED ); HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX ); /* The source address is constant - the Rx Data Buffer */ HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 ); /* The destination address is incremented by 1 word after each transfer */ HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 ); HAL_DMA_SET_DEST( ch, spiRxBuf ); HAL_DMA_SET_LEN( ch, SPI_MAX_PKT_LEN ); /* The DMA is to be polled and shall not issue an IRQ upon completion */ HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE ); /* Xfer all 8 bits of a byte xfer */ HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); /* DMA has highest priority for memory access */ HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH ); volatile uint8 dummy = *(volatile uint8 *)DMA_UxDBUF; /* Clear the DMA Rx trigger */ HAL_DMA_CLEAR_IRQ(HAL_SPI_CH_RX); HAL_DMA_ARM_CH(HAL_SPI_CH_RX); (void)memset(spiRxBuf, (DMA_PAD ^ 0xFF), SPI_MAX_PKT_LEN * sizeof(uint16)); }
/************************************************************************************************** * @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; }