/****************************************************************************** * @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 HalUARTPollTxTrigDMA * * @brief Ascertain whether a manual trigger is required for the DMA Tx channel. * * @param None * * @return None *****************************************************************************/ static void HalUARTPollTxTrigDMA(void) { if ((UxCSR & CSR_TX_BYTE) == 0) // If no TXBUF to shift register transfer, then TXBUF may be MT. { if ((dmaCfg.txTick == 0) || ((uint8)(ST0 - dmaCfg.txTick) > HAL_UART_TX_TICK_MIN)) { dmaCfg.txTick = 0; if (dmaCfg.txTrig && HAL_DMA_CH_ARMED(HAL_DMA_CH_TX)) { HAL_DMA_MAN_TRIGGER(HAL_DMA_CH_TX); } dmaCfg.txTrig = 0; } } else { UxCSR = (CSR_MODE | CSR_RE); // Clear the CSR_TX_BYTE flag. dmaCfg.txTick = ST0; if (dmaCfg.txTick == 0) // Reserve zero to signify that the minimum delay has been met. { dmaCfg.txTick = 0xFF; } } }
/****************************************************************************** * @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 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); } }