Kinetis UART 驱动分析
已有 2149 次阅读2014-10-4 10:34
|个人分类:Kinetis SDK|系统分类:ARM
- /*FUNCTION**********************************************************************
- *
- * Function Name : UART_DRV_Init
- * Description : This function initializes a UART instance for operation.
- * This function will initialize the run-time state structure to keep track of the on-going
- * transfers, ungate the clock to the UART module, initialize the module
- * to user defined settings and default settings, configure the IRQ state structure and enable
- * the module-level interrupt to the core, and enable the UART module transmitter and receiver.
- * The following is an example of how to set up the uart_state_t and the
- * uart_user_config_t parameters and how to call the UART_DRV_Init function by passing
- * in these parameters:
- * uart_user_config_t uartConfig;
- * uartConfig.baudRate = 9600;
- * uartConfig.bitCountPerChar = kUart8BitsPerChar;
- * uartConfig.parityMode = kUartParityDisabled;
- * uartConfig.stopBitCount = kUartOneStopBit;
- * uart_state_t uartState;
- * UART_DRV_Init(instance, &uartState, &uartConfig);
- *
- *END**************************************************************************/
- uart_status_t UART_DRV_Init(uint32_t instance, uart_state_t * uartStatePtr,
- const uart_user_config_t * uartUserConfig)
- {
- assert(uartStatePtr && uartUserConfig);
- assert(instance < HW_UART_INSTANCE_COUNT);
- uint32_t baseAddr = g_uartBaseAddr[instance];
- uint32_t uartSourceClock;
- /* Exit if current instance is already initialized. */
- if (g_uartStatePtr[instance])
- {
- return kStatus_UART_Initialized;
- }
- /* Clear the state structure for this instance. */
- memset(uartStatePtr, 0, sizeof(uart_state_t));
- /* Save runtime structure pointer.*/
- g_uartStatePtr[instance] = uartStatePtr;
- /* Un-gate UART module clock */
- CLOCK_SYS_EnableUartClock(instance);
- /* Initialize UART to a known state. */
- UART_HAL_Init(baseAddr);
- /* Create Semaphore for txIrq and rxIrq. */
- OSA_SemaCreate(&uartStatePtr->txIrqSync, 0);
- OSA_SemaCreate(&uartStatePtr->rxIrqSync, 0);
- /* UART clock source is either system clock or bus clock depending on the instance */
- uartSourceClock = CLOCK_SYS_GetUartFreq(instance);
- /* Initialize UART baud rate, bit count, parity and stop bit. */
- UART_HAL_SetBaudRate(baseAddr, uartSourceClock, uartUserConfig->baudRate);
- UART_HAL_SetBitCountPerChar(baseAddr, uartUserConfig->bitCountPerChar);
- UART_HAL_SetParityMode(baseAddr, uartUserConfig->parityMode);
- #if FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT
- UART_HAL_SetStopBitCount(baseAddr, uartUserConfig->stopBitCount);
- #endif
- #if FSL_FEATURE_UART_HAS_FIFO
- uint8_t fifoSize;
- /* Obtain raw TX FIFO size bit setting */
- fifoSize = UART_HAL_GetTxFifoSize(baseAddr);
- /* Now calculate the number of data words per given FIFO size */
- uartStatePtr->txFifoEntryCount = (fifoSize == 0 ? 1 : 0x1 << (fifoSize + 1));
- /* Configure the TX FIFO watermark to be 1/2 of the total entry or 0 if entry count = 1
- * A watermark setting of 0 for TX FIFO entry count of 1 means that TDRE will only interrupt
- * when the TX buffer (the one entry in the TX FIFO) is empty. Otherwise, if we set the
- * watermark to 1, the TDRE will always be set regardless if the TX buffer was empty or not
- * as the spec says TDRE will set when the FIFO is at or below the configured watermark. */
- if (uartStatePtr->txFifoEntryCount > 1)
- {
- UART_HAL_SetTxFifoWatermark(baseAddr, (uartStatePtr->txFifoEntryCount >> 1U));
- }
- else
- {
- UART_HAL_SetTxFifoWatermark(baseAddr, 0);
- }
- /* Configure the RX FIFO watermark to be 1.
- * Note about RX FIFO support: There is only one RX data full interrupt that is
- * associated with the RX FIFO Watermark. The watermark cannot be dynamically changed.
- * This means if the rxSize is less than the programmed watermark the interrupt will
- * never occur. If we try to change the watermark, this will involve shutting down
- * the receiver first - which is not a desirable operation when the UART is actively
- * receiving data. Hence, the best solution is to set the RX FIFO watermark to 1. */
- UART_HAL_SetRxFifoWatermark(baseAddr, 1);
- /* Enable and flush the FIFO prior to enabling the TX/RX */
- UART_HAL_SetTxFifoCmd(baseAddr, true);
- UART_HAL_SetRxFifoCmd(baseAddr, true);
- UART_HAL_FlushTxFifo(baseAddr);
- UART_HAL_FlushRxFifo(baseAddr);
- #else
- /* For modules that do not support a FIFO, they have a data buffer that essentially
- * acts likes a one-entry FIFO, thus to make the code cleaner, we'll
- * equate txFifoEntryCount to 1. Also note that TDRE flag will set only when the tx
- * buffer is empty. */
- uartStatePtr->txFifoEntryCount = 1;
- #endif
- /* Enable UART interrupt on NVIC level. */
- INT_SYS_EnableIRQ(g_uartRxTxIrqId[instance]);
- /* Finally, enable the UART transmitter and receiver*/
- UART_HAL_EnableTransmitter(baseAddr);
- UART_HAL_EnableReceiver(baseAddr);
- return kStatus_UART_Success;
- }
复制代码