/****************************************************************************** * @fn HalDMAInit * * @brief DMA Interrupt Service Routine * * @param None * * @return None *****************************************************************************/ HAL_ISR_FUNCTION( halDmaIsr, DMA_VECTOR ) { DMAIF = 0; if (ZNP_CFG1_UART == znpCfg1) { if (HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)) { extern void HalUARTIsrDMA(void); HalUARTIsrDMA(); } } else { if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_RX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_RX ); HalSpiRxIsr(); } if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_TX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_TX ); HalSpiTxIsr(); } } }
/****************************************************************************** * @fn AesDmaSetup * * @brief Sets up DMA of 16 byte block using CC2540 HW aes encryption engine * * input parameters * * @param Cstate - Pointer to output data. * @param msg_out_len - message out length * @param msg_in - pointer to input data. * @param msg_in_len - message in length * * output parameters * * @param Cstate - Pointer to encrypted data. * * @return None * */ void AesDmaSetup( uint8 *Cstate, uint16 msg_out_len, uint8 *msg_in, uint16 msg_in_len ) { halDMADesc_t *ch; /* Modify descriptors for channel 1 */ ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_IN ); HAL_DMA_SET_SOURCE( ch, msg_in ); HAL_DMA_SET_LEN( ch, msg_in_len ); /* Modify descriptors for channel 2 */ ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_OUT ); HAL_DMA_SET_DEST( ch, Cstate ); HAL_DMA_SET_LEN( ch, msg_out_len ); /* Arm DMA channels 1 and 2 */ HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_IN ); HAL_DMA_ARM_CH( HAL_DMA_AES_IN ); do { asm("NOP"); } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_IN)); HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_OUT ); HAL_DMA_ARM_CH( HAL_DMA_AES_OUT ); do { asm("NOP"); } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_OUT)); }
/****************************************************************************** * @fn HalDMAInit * * @brief DMA Interrupt Service Routine * * @param None * * @return None *****************************************************************************/ HAL_ISR_FUNCTION( halDmaIsr, DMA_VECTOR ) { extern void HalUARTIsrDMA(void); DMAIF = 0; #if HAL_UART_DMA if (HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)) { HalUARTIsrDMA(); } #endif // HAL_UART_DMA #if (defined HAL_SPI) && (HAL_SPI == TRUE) if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_RX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_RX ); HalSpiRxIsr(); } if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_TX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_TX ); HalSpiTxIsr(); } #endif // (defined HAL_SPI) && (HAL_SPI == TRUE) #if (defined HAL_IRGEN) && (HAL_IRGEN == TRUE) if ( HAL_IRGEN == TRUE && HAL_DMA_CHECK_IRQ( HAL_IRGEN_DMA_CH ) ) { HAL_DMA_CLEAR_IRQ( HAL_IRGEN_DMA_CH ); HalIrGenDmaIsr(); } #endif // (defined HAL_IRGEN) && (HAL_IRGEN == TRUE) }
/****************************************************************************** * @fn HalDMAInit * * @brief DMA Interrupt Service Routine * * @param None * * @return None *****************************************************************************/ HAL_ISR_FUNCTION( halDmaIsr, DMA_VECTOR ) { HAL_ENTER_ISR(); DMAIF = 0; if (ZNP_CFG1_UART == znpCfg1) { if (HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)) { extern void HalUARTIsrDMA(void); HalUARTIsrDMA(); } } #if (defined HAL_SPI) && (HAL_SPI == TRUE) else { if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_RX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_RX ); HalSpiRxIsr(); } if ( HAL_DMA_CHECK_IRQ( HAL_DMA_CH_TX ) ) { HAL_DMA_CLEAR_IRQ( HAL_DMA_CH_TX ); HalSpiTxIsr(); } } #endif // #if (defined HAL_SPI) && (HAL_SPI == TRUE) HAL_EXIT_ISR(); }
/************************************************************************************************** * @fn sblRun * * @brief Serial Boot run code for the SPI transport. * * input parameters * * None. * * output parameters * * None. * * @return None. */ static void sblRun(void) { halUARTCfg_t uartConfig; uartConfig.callBackFunc = sblRxCB; HAL_DMA_SET_ADDR_DESC1234(dmaCh1234); HalUARTInitSPI(); HalUARTOpenSPI(&uartConfig); while (1) { if (PxIFG & SPI_RDYIn_BIT) { spiRdyIn(); } HalUARTPollSPI(); if (HAL_DMA_CHECK_IRQ(HAL_SPI_CH_TX)) { HAL_DMA_CLEAR_IRQ(HAL_SPI_CH_TX); HalUART_DMAIsrSPI(); if (sblReset) { HAL_SYSTEM_RESET(); } } } }
/************************************************************************************************** * @fn HalFlashWrite * * @brief This function writes 'cnt' bytes to the internal flash. * * input parameters * * @param addr - Valid HAL flash write address: actual addr / 4 and quad-aligned. * @param buf - Valid buffer space at least as big as 'cnt' X 4. * @param cnt - Number of 4-byte blocks to write. * * output parameters * * None. * * @return None. ************************************************************************************************** */ void HalFlashWrite(uint16 addr, uint8 *buf, uint16 cnt) { halDMADesc_t *ch = HAL_NV_DMA_GET_DESC(); HAL_DMA_SET_SOURCE(ch, buf); HAL_DMA_SET_DEST(ch, &FWDATA); HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN); HAL_DMA_SET_LEN(ch, (cnt * HAL_FLASH_WORD_SIZE)); HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE); HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE); HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH); HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1); HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0); // The DMA is to be polled and shall not issue an IRQ upon completion. HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE); HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS); HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH); HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH); HAL_DMA_ARM_CH(HAL_NV_DMA_CH); FADDRL = (uint8)addr; FADDRH = (uint8)(addr >> 8); FCTL |= 0x02; // Trigger the DMA writes. while (FCTL & 0x80); // Wait until writing is done. }
/****************************************************************************** * @fn AesLoadKey * * @brief Writes the key into the CC2540 * * input parameters * * @param AesKey - Pointer to AES Key. * * @return None */ void AesLoadKey( uint8 *AesKey ) { #if (defined HAL_AES_DMA) && (HAL_AES_DMA == TRUE) halDMADesc_t *ch = HAL_DMA_GET_DESC1234( HAL_DMA_AES_IN ); /* Modify descriptors for channel 1 */ HAL_DMA_SET_SOURCE( ch, AesKey ); HAL_DMA_SET_LEN( ch, KEY_BLENGTH ); /* Arm DMA channel 1 */ HAL_DMA_CLEAR_IRQ( HAL_DMA_AES_IN ); HAL_DMA_ARM_CH( HAL_DMA_AES_IN ); do { asm("NOP"); } while (!HAL_DMA_CH_ARMED(HAL_DMA_AES_IN)); /* Set AES mode */ AES_SET_ENCR_DECR_KEY_IV( AES_LOAD_KEY ); /* Kick it off, block until AES is ready */ AES_START(); while( !(ENCCS & 0x08) ); #else /* Set AES mode */ AES_SET_ENCR_DECR_KEY_IV( AES_LOAD_KEY ); /* Load the block */ AesLoadBlock( AesKey ); #endif }
/****************************************************************************** * @fn startIrGenNec * * @brief Generate repeat IR signal corresponding to NEC protocol * * input parameters * * @param IrBufSize - Size of the command containing the IR signal * * output parameters * * None. * * @return None. * */ static void startIrGenNec(uint8 IrBufSize) { halIntState_t intState; //check if IR generation timers are already in use if (halIrGenTimerRunning) { // Timer is already running. Cannot generate the signals. return; } halIrGenTimerRunning = TRUE; // Inlcude stop bit ('1') halIrGenCc0Buf[IrBufSize] = HAL_IRGEN_NEC_BIT_1_PER; // Inlcude dummy value as last entry in buffer to make sure stop bit is generated halIrGenCc0Buf[IrBufSize+1] = 0xFFFF; // Set data length. HAL_DMA_SET_LEN(pDmaDescCc0, IrBufSize + 2); HAL_DMA_SET_LEN(pDmaDescCc1, IrBufSize + 2); // ARM both DMA channels HAL_DMA_CLEAR_IRQ(HAL_IRGEN_DMA_CH_CC0); HAL_DMA_ARM_CH(HAL_IRGEN_DMA_CH_CC0); HAL_DMA_CLEAR_IRQ(HAL_IRGEN_DMA_CH_CC1); HAL_DMA_ARM_CH(HAL_IRGEN_DMA_CH_CC1); // program initial state (preamble) // duty cycle if (IrBufSize) // command signal generation { T1CC0L = ((6 * HAL_IRGEN_NEC_BIT_1_PER) & 0xff) - 1; T1CC0H = (6 * HAL_IRGEN_NEC_BIT_1_PER) >> 8; } else // repeat signal generation {
void HalUARTIsrDMA(void) { HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX); // Indicate that the other buffer is free now. dmaCfg.txIdx[(dmaCfg.txSel ^ 1)] = 0; dmaCfg.txMT = TRUE; // Set TX shadow dmaCfg.txShdw = ST0; dmaCfg.txShdwValid = TRUE; // If there is more Tx data ready to go, re-start the DMA immediately on it. if (dmaCfg.txIdx[dmaCfg.txSel]) { // UART TX DMA is expected to be fired dmaCfg.txDMAPending = TRUE; } }
/************************************************************************************************** * @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 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 HalUARTPollDMA * * @brief Poll a USART module implemented by DMA. * * @param none * * @return none *****************************************************************************/ static void HalUARTPollDMA(void) { uint16 cnt = 0; uint8 evt = 0; if (HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead)) { rxIdx_t tail = findTail(); // If the DMA has transferred in more Rx bytes, reset the Rx idle timer. if (dmaCfg.rxTail != tail) { dmaCfg.rxTail = tail; // Re-sync the shadow on any 1st byte(s) received. if (dmaCfg.rxTick == 0) { dmaCfg.rxShdw = ST0; } dmaCfg.rxTick = HAL_UART_DMA_IDLE; } else if (dmaCfg.rxTick) { // Use the LSB of the sleep timer (ST0 must be read first anyway). uint8 decr = ST0 - dmaCfg.rxShdw; if (dmaCfg.rxTick > decr) { dmaCfg.rxTick -= decr; dmaCfg.rxShdw = ST0; } else { dmaCfg.rxTick = 0; } } cnt = HalUARTRxAvailDMA(); } else { dmaCfg.rxTick = 0; } if (cnt >= HAL_UART_DMA_FULL) { evt = HAL_UART_RX_FULL; } else if (cnt >= HAL_UART_DMA_HIGH) { evt = HAL_UART_RX_ABOUT_FULL; PxOUT |= HAL_UART_Px_RTS; // Disable Rx flow. } else if (cnt && !dmaCfg.rxTick) { evt = HAL_UART_RX_TIMEOUT; } if (dmaCfg.txMT) { dmaCfg.txMT = FALSE; evt |= HAL_UART_TX_EMPTY; } if (dmaCfg.txShdwValid) { uint8 decr = ST0; decr -= dmaCfg.txShdw; if (decr > dmaCfg.txTick) { // No protection for txShdwValid is required // because while the shadow was valid, DMA ISR cannot be triggered // to cause concurrent access to this variable. dmaCfg.txShdwValid = FALSE; } } if (dmaCfg.txDMAPending && !dmaCfg.txShdwValid) { // UART TX DMA is expected to be fired and enough time has lapsed since last DMA ISR // to know that DBUF can be overwritten halDMADesc_t *ch = HAL_DMA_GET_DESC1234(HAL_DMA_CH_TX); halIntState_t intState; // Clear the DMA pending flag dmaCfg.txDMAPending = FALSE; HAL_DMA_SET_SOURCE(ch, dmaCfg.txBuf[dmaCfg.txSel]); HAL_DMA_SET_LEN(ch, dmaCfg.txIdx[dmaCfg.txSel]); dmaCfg.txSel ^= 1; HAL_ENTER_CRITICAL_SECTION(intState); HAL_DMA_ARM_CH(HAL_DMA_CH_TX); do { asm("NOP"); } while (!HAL_DMA_CH_ARMED(HAL_DMA_CH_TX)); HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_TX); HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX); HAL_EXIT_CRITICAL_SECTION(intState); } else { halIntState_t his; HAL_ENTER_CRITICAL_SECTION(his); if ((dmaCfg.txIdx[dmaCfg.txSel] != 0) && !HAL_DMA_CH_ARMED(HAL_DMA_CH_TX) && !HAL_DMA_CHECK_IRQ(HAL_DMA_CH_TX)) { HAL_EXIT_CRITICAL_SECTION(his); HalUARTIsrDMA(); } else { HAL_EXIT_CRITICAL_SECTION(his); } } if (evt && (dmaCfg.uartCB != NULL)) { dmaCfg.uartCB(HAL_UART_DMA-1, evt); } }
/****************************************************************************** * @fn HalUARTOpenDMA * * @brief Open a port according tp the configuration specified by parameter. * * @param config - contains configuration information * * @return none *****************************************************************************/ static void HalUARTOpenDMA(halUARTCfg_t *config) { dmaCfg.uartCB = config->callBackFunc; // Only supporting subset of baudrate for code size - other is possible. HAL_UART_ASSERT((config->baudRate == HAL_UART_BR_9600) || (config->baudRate == HAL_UART_BR_19200) || (config->baudRate == HAL_UART_BR_38400) || (config->baudRate == HAL_UART_BR_57600) || (config->baudRate == HAL_UART_BR_115200)); if (config->baudRate == HAL_UART_BR_57600 || config->baudRate == HAL_UART_BR_115200) { UxBAUD = 216; } else { UxBAUD = 59; } switch (config->baudRate) { case HAL_UART_BR_9600: UxGCR = 8; dmaCfg.txTick = 35; // (32768Hz / (9600bps / 10 bits)) // 10 bits include start and stop bits. break; case HAL_UART_BR_19200: UxGCR = 9; dmaCfg.txTick = 18; break; case HAL_UART_BR_38400: UxGCR = 10; dmaCfg.txTick = 9; break; case HAL_UART_BR_57600: UxGCR = 10; dmaCfg.txTick = 6; break; default: // HAL_UART_BR_115200 UxGCR = 11; dmaCfg.txTick = 3; break; } // 8 bits/char; no parity; 1 stop bit; stop bit hi. if (config->flowControl) { UxUCR = UCR_FLOW | UCR_STOP; PxSEL |= HAL_UART_Px_CTS; // DMA Rx is always on (self-resetting). So flow must be controlled by the S/W polling the Rx // buffer level. Start by allowing flow. PxOUT &= ~HAL_UART_Px_RTS; PxDIR |= HAL_UART_Px_RTS; } else { UxUCR = UCR_STOP; } dmaCfg.rxBuf[0] = *(volatile uint8 *)DMA_UDBUF; // Clear the DMA Rx trigger. HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX); HAL_DMA_ARM_CH(HAL_DMA_CH_RX); osal_memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*2); UxCSR |= CSR_RE; // Initialize that TX DMA is not pending dmaCfg.txDMAPending = FALSE; dmaCfg.txShdwValid = FALSE; }