/***************************************************************************//** * @brief * Init LEUART. * * @details * This function will configure basic settings in order to operate in normal * asynchronous mode. Consider using LEUART_Reset() prior to this function if * state of configuration is not known, since only configuration settings * specified by @p init are set. * * Special control setup not covered by this function may be done either * before or after using this function (but normally before enabling) * by direct modification of the CTRL register. * * Notice that pins used by the LEUART module must be properly configured * by the user explicitly, in order for the LEUART to work as intended. * (When configuring pins, one should remember to consider the sequence of * configuration, in order to avoid unintended pulses/glitches on output * pins.) * * @note * Initializing requires synchronization into the low frequency domain. * If the same register is modified before a previous update has completed, * this function will stall until the previous synchronization has completed. * * @param[in] leuart * Pointer to LEUART peripheral register block. * * @param[in] init * Pointer to initialization structure used to configure basic async setup. ******************************************************************************/ void LEUART_Init(LEUART_TypeDef *leuart, LEUART_Init_TypeDef const *init) { /* Make sure the module exists on the selected chip */ EFM_ASSERT(LEUART_REF_VALID(leuart)); /* LF register about to be modified require sync. busy check */ LEUART_Sync(leuart, LEUART_SYNCBUSY_CMD); /* Ensure disabled while doing config */ leuart->CMD = LEUART_CMD_RXDIS | LEUART_CMD_TXDIS; /* Freeze registers to avoid stalling for LF synchronization */ LEUART_FreezeEnable(leuart, true); /* Configure databits and stopbits */ leuart->CTRL = (leuart->CTRL & ~(_LEUART_CTRL_PARITY_MASK | _LEUART_CTRL_STOPBITS_MASK)) | (uint32_t)(init->databits) | (uint32_t)(init->parity) | (uint32_t)(init->stopbits); /* Configure baudrate */ LEUART_BaudrateSet(leuart, init->refFreq, init->baudrate); /* Finally enable (as specified) */ leuart->CMD = (uint32_t)(init->enable); /* Unfreeze registers, pass new settings on to LEUART */ LEUART_FreezeEnable(leuart, false); }
/************************************************************************************//** ** \brief Initializes the UART communication interface. ** \return none. ** ****************************************************************************************/ static void BootComUartInit(void) { LEUART_Init_TypeDef init = LEUART_INIT_DEFAULT; /* configure GPIO pins */ CMU_ClockEnable(cmuClock_GPIO, true); /* to avoid false start, configure output as high */ GPIO_PinModeSet(gpioPortC, 6, gpioModePushPull, 1); GPIO_PinModeSet(gpioPortC, 7, gpioModeInput, 0); /* enable CORE LE clock in order to access LE modules */ CMU_ClockEnable(cmuClock_CORELE, true); /* select LFXO for LEUARTs (and wait for it to stabilize) */ CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); /* do not prescale clock */ CMU_ClockDivSet(cmuClock_LEUART1, cmuClkDiv_1); /* enable LEUART1 clock */ CMU_ClockEnable(cmuClock_LEUART1, true); /* configure LEUART */ init.enable = leuartDisable; LEUART_Init(LEUART1, &init); LEUART_BaudrateSet(LEUART1, 0, BOOT_COM_UART_BAUDRATE); /* enable pins at default location */ LEUART1->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN; /* clear previous RX interrupts */ LEUART_IntClear(LEUART1, LEUART_IF_RXDATAV); /* finally enable it */ LEUART_Enable(LEUART1, leuartEnable); } /*** end of BootUartComInit ***/
static int leuart_configure (sBSPACMperiphUARTstate * usp, const sBSPACMperiphUARTconfiguration * cfgp) { LEUART_TypeDef * leuart; const sBSPACMdeviceEFM32periphLEUARTdevcfg * devcfgp; if (! (usp && usp->uart)) { return -1; } leuart = (LEUART_TypeDef *)usp->uart; devcfgp = (const sBSPACMdeviceEFM32periphLEUARTdevcfg *)usp->devcfg.ptr; /* Configure LFB's source, enable the low-energy peripheral clock, and the clock for the * leuart itself */ if (cfgp) { /* LFB is required for LEUART. Power-up is LFRCO which doesn't * work so good; if we were told a source to use, override * whatever was there. */ if (devcfgp->lfbsel) { CMU_ClockSelectSet(cmuClock_LFB, devcfgp->lfbsel); } CMU_ClockEnable(cmuClock_CORELE, true); CMU_ClockEnable(devcfgp->common.clock, true); } else { NVIC_DisableIRQ(devcfgp->irqn); NVIC_ClearPendingIRQ(devcfgp->irqn); } LEUART_Reset(leuart); leuart->FREEZE = LEUART_FREEZE_REGFREEZE; leuart->CMD = LEUART_CMD_RXDIS | LEUART_CMD_TXDIS; if (usp->rx_fifo_ni_) { fifo_reset(usp->rx_fifo_ni_); } if (usp->tx_fifo_ni_) { fifo_reset(usp->tx_fifo_ni_); } usp->tx_state_ = 0; if (cfgp) { unsigned int speed_baud = cfgp->speed_baud; if (0 == speed_baud) { speed_baud = 9600; } /* Configure the LEUART for rate at 8N1. */ leuart->CTRL = LEUART_CTRL_DATABITS_EIGHT | LEUART_CTRL_PARITY_NONE | LEUART_CTRL_STOPBITS_ONE; LEUART_BaudrateSet(leuart, 0, speed_baud); CMU_ClockEnable(cmuClock_GPIO, true); } /* Enable or disable UART pins. To avoid false start, when enabling * configure TX as high. This relies on a comment in the EMLIB code * that manipulating registers of disabled modules has no effect * (unlike TM4C where it causes a HardFault). We'll see. */ vBSPACMdeviceEFM32pinmuxConfigure(&devcfgp->common.rx_pinmux, !!cfgp, 1); vBSPACMdeviceEFM32pinmuxConfigure(&devcfgp->common.tx_pinmux, !!cfgp, 0); if (cfgp) { leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | devcfgp->common.location; /* Clear and enable RX interrupts at the device. Device TX * interrupts are enabled at the peripheral when there's something * to transmit. Clear then enable interrupts at the NVIC. */ leuart->IFC = _LEUART_IF_MASK; leuart->IEN = LEUART_IF_RXDATAV; NVIC_ClearPendingIRQ(devcfgp->irqn); NVIC_EnableIRQ(devcfgp->irqn); /* Configuration complete; enable the LEUART, and release the * registers to synchronize. */ leuart->CMD = LEUART_CMD_RXEN | LEUART_CMD_TXEN; leuart->FREEZE = 0; } else { CMU_ClockEnable(devcfgp->common.clock, false); } return 0; }