FSL_FAE_ConstYu的个人空间 https://bbs.21ic.com/?1105562 [收藏] [复制] [RSS]

日志

Kinetis UART 驱动分析

已有 2149 次阅读2014-10-4 10:34 |个人分类:Kinetis SDK|系统分类:ARM

       
  1. /*FUNCTION**********************************************************************
  2.  *
  3.  * Function Name : UART_DRV_Init
  4.  * Description   : This function initializes a UART instance for operation.
  5.  * This function will initialize the run-time state structure to keep track of the on-going
  6.  * transfers, ungate the clock to the UART module, initialize the module
  7.  * to user defined settings and default settings, configure the IRQ state structure and enable
  8.  * the module-level interrupt to the core, and enable the UART module transmitter and receiver.
  9.  * The following is an example of how to set up the uart_state_t and the
  10.  * uart_user_config_t parameters and how to call the UART_DRV_Init function by passing
  11.  * in these parameters:
  12.  *    uart_user_config_t uartConfig;
  13.  *    uartConfig.baudRate = 9600;
  14.  *    uartConfig.bitCountPerChar = kUart8BitsPerChar;
  15.  *    uartConfig.parityMode = kUartParityDisabled;
  16.  *    uartConfig.stopBitCount = kUartOneStopBit;
  17.  *    uart_state_t uartState;
  18.  *    UART_DRV_Init(instance, &uartState, &uartConfig);
  19.  *
  20.  *END**************************************************************************/
  21. uart_status_t UART_DRV_Init(uint32_t instance, uart_state_t * uartStatePtr,
  22.                             const uart_user_config_t * uartUserConfig)
  23. {
  24.     assert(uartStatePtr && uartUserConfig);
  25.     assert(instance < HW_UART_INSTANCE_COUNT);

  26.     uint32_t baseAddr = g_uartBaseAddr[instance];
  27.     uint32_t uartSourceClock;

  28.     /* Exit if current instance is already initialized. */
  29.     if (g_uartStatePtr[instance])
  30.     {
  31.         return kStatus_UART_Initialized;
  32.     }

  33.     /* Clear the state structure for this instance. */
  34.     memset(uartStatePtr, 0, sizeof(uart_state_t));

  35.     /* Save runtime structure pointer.*/
  36.     g_uartStatePtr[instance] = uartStatePtr;

  37.     /* Un-gate UART module clock */
  38.     CLOCK_SYS_EnableUartClock(instance);

  39.     /* Initialize UART to a known state. */
  40.     UART_HAL_Init(baseAddr);

  41.     /* Create Semaphore for txIrq and rxIrq. */
  42.     OSA_SemaCreate(&uartStatePtr->txIrqSync, 0);
  43.     OSA_SemaCreate(&uartStatePtr->rxIrqSync, 0);

  44.     /* UART clock source is either system clock or bus clock depending on the instance */
  45.     uartSourceClock = CLOCK_SYS_GetUartFreq(instance);

  46.     /* Initialize UART baud rate, bit count, parity and stop bit. */
  47.     UART_HAL_SetBaudRate(baseAddr, uartSourceClock, uartUserConfig->baudRate);
  48.     UART_HAL_SetBitCountPerChar(baseAddr, uartUserConfig->bitCountPerChar);
  49.     UART_HAL_SetParityMode(baseAddr, uartUserConfig->parityMode);
  50. #if FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT
  51.     UART_HAL_SetStopBitCount(baseAddr, uartUserConfig->stopBitCount);
  52. #endif

  53. #if FSL_FEATURE_UART_HAS_FIFO
  54.     uint8_t fifoSize;
  55.     /* Obtain raw TX FIFO size bit setting */
  56.     fifoSize = UART_HAL_GetTxFifoSize(baseAddr);
  57.     /* Now calculate the number of data words per given FIFO size */
  58.     uartStatePtr->txFifoEntryCount = (fifoSize == 0 ? 1 : 0x1 << (fifoSize + 1));

  59.     /* Configure the TX FIFO watermark to be 1/2 of the total entry or 0 if entry count = 1
  60.      * A watermark setting of 0 for TX FIFO entry count of 1 means that TDRE will only interrupt
  61.      * when the TX buffer (the one entry in the TX FIFO) is empty. Otherwise, if we set the
  62.      * watermark to 1, the TDRE will always be set regardless if the TX buffer was empty or not
  63.      * as the spec says TDRE will set when the FIFO is at or below the configured watermark. */
  64.     if (uartStatePtr->txFifoEntryCount > 1)
  65.     {
  66.         UART_HAL_SetTxFifoWatermark(baseAddr, (uartStatePtr->txFifoEntryCount >> 1U));
  67.     }
  68.     else
  69.     {
  70.         UART_HAL_SetTxFifoWatermark(baseAddr, 0);
  71.     }

  72.     /* Configure the RX FIFO watermark to be 1. 
  73.      * Note about RX FIFO support: There is only one RX data full interrupt that is
  74.      * associated with the RX FIFO Watermark.  The watermark cannot be dynamically changed.
  75.      * This means if the rxSize is less than the programmed watermark the interrupt will 
  76.      * never occur. If we try to change the watermark, this will involve shutting down
  77.      * the receiver first - which is not a desirable operation when the UART is actively
  78.      * receiving data. Hence, the best solution is to set the RX FIFO watermark to 1. */
  79.     UART_HAL_SetRxFifoWatermark(baseAddr, 1);

  80.     /* Enable and flush the FIFO prior to enabling the TX/RX */
  81.     UART_HAL_SetTxFifoCmd(baseAddr, true);
  82.     UART_HAL_SetRxFifoCmd(baseAddr, true);
  83.     UART_HAL_FlushTxFifo(baseAddr);
  84.     UART_HAL_FlushRxFifo(baseAddr);
  85. #else
  86.     /* For modules that do not support a FIFO, they have a data buffer that essentially
  87.      * acts likes a one-entry FIFO, thus to make the code cleaner, we'll
  88.      * equate txFifoEntryCount to 1.  Also note that TDRE flag will set only when the tx
  89.      * buffer is empty. */
  90.     uartStatePtr->txFifoEntryCount = 1;
  91. #endif

  92.     /* Enable UART interrupt on NVIC level. */
  93.     INT_SYS_EnableIRQ(g_uartRxTxIrqId[instance]);

  94.     /* Finally, enable the UART transmitter and receiver*/
  95.     UART_HAL_EnableTransmitter(baseAddr);
  96.     UART_HAL_EnableReceiver(baseAddr);

  97.     return kStatus_UART_Success;
  98. }
复制代码


路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)