电子说
-
OSR 最小值是 4,因此24Mhz时钟模式下,LPUART最大波特率是 24/5 = 4.8Mbps,手册中硬件的 LPUART最大的波特率是 80Mhz/4=20Mbps。80/13= 6.15Mbps波特率,这样相对于 6Mhz就有 2.5%的误差。
那如果用 FlexIO外设实现 UART波特率可以达到 6Mbps么?
将FlexIO用于UART RX时,RM参考手册的注意事项:“FlexIO数据只在每个位的中间采样一次。可以使用另一个定时器对传入数据进行毛刺过滤”。保持FlexIO时钟与RM参考手册中的波特率的倍数相同。RM参考手册中的UART接收和UART发射配置表将所使用的每个FlexIO定时器的TIMCMP设置为0xF01。这意味着波特率是FlexIO时钟频率的1/4。FlexIO不支持奇偶校验位的自动验证。
使用了SDK中的Flexio_uart示例,并使用了flexio_uart驱动程序,只对这些频率/波特率进行了一些细微的更改。示例使用480MHz的PLL3作为FlexIO的时钟源。将FLEXIO2_CLK_PRED除法器设置为(4+1),将FLEXIO2_CLK_PODF除法器设为(3+1),从而提供 24MHz(480/5/4)的FlexIO时钟。对于驱动程序,将flexio_uart_config_t.baudRate_Bps设置为6000000。然后,驱动程序计算两个定时器的TIMCMP寄存器=0xF01。
它在IMXRT1060-EVKB板上运行,SDK v2.12.1,如下代码简单修改。SDK_2_12_1_MIMXRT1062xxxxBoardsevkbmimxrt1060driver_examplesflexiouartedma_transfer 此应用程序仅在引脚GPIO_B0_05上传输,RX设置在引脚GPIO_B0_06上。
IOMUXC_SetPinMux(IOMUXC_GPIO_B0_05_FLEXIO2_FLEXIO05, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_B0_06_FLEXIO2_FLEXIO06, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_05_FLEXIO2_FLEXIO05, 0x10B0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_06_FLEXIO2_FLEXIO06, 0x10B0U);
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "fsl_flexio_uart_edma.h"
#include "fsl_dmamux.h"
#define BOARD_FLEXIO_BASE FLEXIO2
#define FLEXIO_UART_TX_PIN 5U
#define FLEXIO_UART_RX_PIN 6U
/* Select USB1 PLL (480 MHz) as flexio clock source */
#define FLEXIO_CLOCK_SELECT (3U)
/* Clock pre divider for flexio clock source */
#define FLEXIO_CLOCK_PRE_DIVIDER (4U)
/* Clock divider for flexio clock source */
#define FLEXIO_CLOCK_DIVIDER (3U)
#define FLEXIO_CLOCK_FREQUENCY
(CLOCK_GetFreq(kCLOCK_Usb1PllClk) / (FLEXIO_CLOCK_PRE_DIVIDER + 1U) / (FLEXIO_CLOCK_DIVIDER + 1U))
#define FLEXIO_DMA_REQUEST_BASE kDmaRequestMuxFlexIO2Request0Request1
#define EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR DMAMUX
#define EXAMPLE_FLEXIO_UART_DMA_BASEADDR DMA0
#define FLEXIO_UART_TX_DMA_CHANNEL 0U
#define FLEXIO_UART_RX_DMA_CHANNEL 1U
#define FLEXIO_TX_SHIFTER_INDEX 0U
#define FLEXIO_RX_SHIFTER_INDEX 2U
#define EXAMPLE_TX_DMA_SOURCE kDmaRequestMuxFlexIO2Request0Request1
#define EXAMPLE_RX_DMA_SOURCE kDmaRequestMuxFlexIO2Request2Request3
#define ECHO_BUFFER_LENGTH 8
void FLEXIO_UART_UserCallback(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
status_t status,
void *userData);
flexio_uart_edma_handle_t g_uartHandle;
FLEXIO_UART_Type uartDev;
edma_handle_t g_uartTxEdmaHandle;
edma_handle_t g_uartRxEdmaHandle;
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_tipString[]) =
"Flexio uart edma example Board receives 8 characters then sends them out Now please input: ";
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_txBuffer[ECHO_BUFFER_LENGTH]) = {0};
AT_NONCACHEABLE_SECTION_INIT(uint8_t g_rxBuffer[ECHO_BUFFER_LENGTH]) = {0};
volatile bool rxBufferEmpty = true;
volatile bool txBufferFull = false;
volatile bool txOnGoing = false;
volatile bool rxOnGoing = false;
/* UART 用户回调函数 */
void FLEXIO_UART_UserCallback(FLEXIO_UART_Type *base,
flexio_uart_edma_handle_t *handle,
status_t status,
void *userData)
{
userData = userData;
if (kStatus_FLEXIO_UART_TxIdle == status)
{
txBufferFull = false;
txOnGoing = false;
}
if (kStatus_FLEXIO_UART_RxIdle == status)
{
rxBufferEmpty = false;
rxOnGoing = false;
}
}
int main(void)
{
flexio_uart_config_t userconfig;
flexio_uart_transfer_t xfer;
flexio_uart_transfer_t sendXfer;
status_t result = kStatus_Success;
edma_config_t config;
BOARD_ConfigMPU();
BOARD_InitPins();
BOARD_BootClockRUN();
/* Flexio 时钟设置*/
CLOCK_SetMux(kCLOCK_Flexio2Mux, FLEXIO_CLOCK_SELECT);
CLOCK_SetDiv(kCLOCK_Flexio2PreDiv, FLEXIO_CLOCK_PRE_DIVIDER);
CLOCK_SetDiv(kCLOCK_Flexio2Div, FLEXIO_CLOCK_DIVIDER);
/*
* config.enableUart = true;
* config.enableInDoze = false;
* config.enableInDebug = true;
* config.enableFastAccess = false;
* config.bitCountPerChar = kFLEXIO_UART_8BitsPerChar;
*/
FLEXIO_UART_GetDefaultConfig(&userconfig);
userconfig.baudRate_Bps = BOARD_DEBUG_UART_BAUDRATE;
userconfig.enableUart = true;
uartDev.flexioBase = BOARD_FLEXIO_BASE;
uartDev.TxPinIndex = FLEXIO_UART_TX_PIN;
uartDev.RxPinIndex = FLEXIO_UART_RX_PIN;
uartDev.shifterIndex[0] = FLEXIO_TX_SHIFTER_INDEX;
uartDev.shifterIndex[1] = FLEXIO_RX_SHIFTER_INDEX;
uartDev.timerIndex[0] = 0U;
uartDev.timerIndex[1] = 1U;
result = FLEXIO_UART_Init(&uartDev, &userconfig, FLEXIO_CLOCK_FREQUENCY);
if (result != kStatus_Success)
{
return -1;
}
/*初始化 DMA*/
DMAMUX_Init(EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR);
EDMA_GetDefaultConfig(&config);
EDMA_Init(EXAMPLE_FLEXIO_UART_DMA_BASEADDR, &config);
/* 为 TX&RX 设置 DMA 通道 */
DMAMUX_SetSource(EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR, FLEXIO_UART_TX_DMA_CHANNEL, EXAMPLE_TX_DMA_SOURCE);
DMAMUX_SetSource(EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR, FLEXIO_UART_RX_DMA_CHANNEL, EXAMPLE_RX_DMA_SOURCE);
DMAMUX_EnableChannel(EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR, FLEXIO_UART_TX_DMA_CHANNEL);
DMAMUX_EnableChannel(EXAMPLE_FLEXIO_UART_DMAMUX_BASEADDR, FLEXIO_UART_RX_DMA_CHANNEL);
EDMA_CreateHandle(&g_uartTxEdmaHandle, EXAMPLE_FLEXIO_UART_DMA_BASEADDR, FLEXIO_UART_TX_DMA_CHANNEL);
EDMA_CreateHandle(&g_uartRxEdmaHandle, EXAMPLE_FLEXIO_UART_DMA_BASEADDR, FLEXIO_UART_RX_DMA_CHANNEL);
FLEXIO_UART_TransferCreateHandleEDMA(&uartDev, &g_uartHandle, FLEXIO_UART_UserCallback, NULL, &g_uartTxEdmaHandle, &g_uartRxEdmaHandle);
/* 发送 g_tipString */
xfer.data = g_tipString;
xfer.dataSize = sizeof(g_tipString) - 1;
txOnGoing = true;
FLEXIO_UART_TransferSendEDMA(&uartDev, &g_uartHandle, &xfer);
/* 等待发送完成 */
while (txOnGoing)
{
}
/* 开始应答 */
sendXfer.data = g_txBuffer;
sendXfer.dataSize = ECHO_BUFFER_LENGTH;
while (1)
{
/* If TX is idle and g_txBuffer is full, start to send data. */
if ((!txOnGoing) && txBufferFull)
{
txOnGoing = true;
FLEXIO_UART_TransferSendEDMA(&uartDev, &g_uartHandle, &sendXfer);
}
/* 如果 g_txBuffer为空,加载 g_txBuffer */
if (!txBufferFull)
{
memcpy(g_txBuffer, "UUUUUUUU", ECHO_BUFFER_LENGTH);
txBufferFull = true;
}
}
}
全部0条评论
快来发表一下你的评论吧 !