K64F: Add support for SERIAL ASYNCH API

Signed-off-by: Mahadevan Mahesh <Mahesh.Mahadevan@nxp.com>
pull/3438/head
Mahadevan Mahesh 2016-12-05 10:15:51 -06:00
parent eb3dc2d2c8
commit ece7b6f05b
4 changed files with 439 additions and 38 deletions

View File

@ -45,4 +45,18 @@
kDmaRequestMux0SPI0Rx, kDmaRequestMux0SPI1, kDmaRequestMux0SPI2 \
}
/* Array for UART DMA TX requests */
#define UART_DMA_TX_REQUEST_NUMBERS \
{ \
kDmaRequestMux0UART0Tx, kDmaRequestMux0UART1Tx, kDmaRequestMux0UART2Tx, \
kDmaRequestMux0UART3Tx, kDmaRequestMux0UART4, kDmaRequestMux0UART5 \
}
/* Array for UART DMA RX requests */
#define UART_DMA_RX_REQUEST_NUMBERS \
{ \
kDmaRequestMux0UART0Rx, kDmaRequestMux0UART1Rx, kDmaRequestMux0UART2Rx, \
kDmaRequestMux0UART3Rx, kDmaRequestMux0UART4, kDmaRequestMux0UART5 \
}
#endif /* _FSL_DMA_REQS_H_ */

View File

@ -28,6 +28,7 @@
#include "fsl_uart.h"
#include "peripheral_clock_defines.h"
#include "PeripheralPins.h"
#include "dma_reqs.h"
#include "fsl_clock_config.h"
static uint32_t serial_irq_ids[FSL_FEATURE_SOC_UART_COUNT] = {0};
@ -37,6 +38,11 @@ static UART_Type *const uart_addrs[] = UART_BASE_PTRS;
/* Array of UART bus clock frequencies */
static clock_name_t const uart_clocks[] = UART_CLOCK_FREQS;
/* UART transfer states */
#define kUART_TxIdle 0
#define kUART_TxBusy 1
#define kUART_RxIdle 2
#define kUART_RxBusy 3
int stdio_uart_inited = 0;
serial_t stdio_uart;
@ -45,8 +51,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
{
uint32_t uart_tx = pinmap_peripheral(tx, PinMap_UART_TX);
uint32_t uart_rx = pinmap_peripheral(rx, PinMap_UART_RX);
obj->index = pinmap_merge(uart_tx, uart_rx);
MBED_ASSERT((int)obj->index != NC);
obj->serial.index = pinmap_merge(uart_tx, uart_rx);
MBED_ASSERT((int)obj->serial.index != NC);
uart_config_t config;
@ -55,40 +61,47 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
config.enableTx = false;
config.enableRx = false;
UART_Init(uart_addrs[obj->index], &config, CLOCK_GetFreq(uart_clocks[obj->index]));
UART_Init(uart_addrs[obj->serial.index], &config, CLOCK_GetFreq(uart_clocks[obj->serial.index]));
pinmap_pinout(tx, PinMap_UART_TX);
pinmap_pinout(rx, PinMap_UART_RX);
if (tx != NC) {
UART_EnableTx(uart_addrs[obj->index], true);
UART_EnableTx(uart_addrs[obj->serial.index], true);
pin_mode(tx, PullUp);
}
if (rx != NC) {
UART_EnableRx(uart_addrs[obj->index], true);
UART_EnableRx(uart_addrs[obj->serial.index], true);
pin_mode(rx, PullUp);
}
if (obj->index == STDIO_UART) {
if (obj->serial.index == STDIO_UART) {
stdio_uart_inited = 1;
memcpy(&stdio_uart, obj, sizeof(serial_t));
}
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;;
obj->serial.txstate = kUART_TxIdle;
obj->serial.rxstate = kUART_RxIdle;
/* Zero the handle. */
memset(&(obj->serial.uart_transfer_handle), 0, sizeof(obj->serial.uart_transfer_handle));
}
void serial_free(serial_t *obj)
{
UART_Deinit(uart_addrs[obj->index]);
serial_irq_ids[obj->index] = 0;
UART_Deinit(uart_addrs[obj->serial.index]);
serial_irq_ids[obj->serial.index] = 0;
}
void serial_baud(serial_t *obj, int baudrate)
{
UART_SetBaudRate(uart_addrs[obj->index], (uint32_t)baudrate, CLOCK_GetFreq(uart_clocks[obj->index]));
UART_SetBaudRate(uart_addrs[obj->serial.index], (uint32_t)baudrate, CLOCK_GetFreq(uart_clocks[obj->serial.index]));
}
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
{
UART_Type *base = uart_addrs[obj->index];
UART_Type *base = uart_addrs[obj->serial.index];
uint8_t temp;
/* Set bit count and parity mode. */
temp = base->C1 & ~(UART_C1_PE_MASK | UART_C1_PT_MASK | UART_C1_M_MASK);
@ -174,7 +187,7 @@ void uart5_irq()
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
{
irq_handler = handler;
serial_irq_ids[obj->index] = id;
serial_irq_ids[obj->serial.index] = id;
}
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
@ -182,7 +195,7 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
IRQn_Type uart_irqs[] = UART_RX_TX_IRQS;
uint32_t vector = 0;
switch (obj->index) {
switch (obj->serial.index) {
case 0:
vector = (uint32_t)&uart0_irq;
break;
@ -208,42 +221,42 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
if (enable) {
switch (irq) {
case RxIrq:
UART_EnableInterrupts(uart_addrs[obj->index], kUART_RxDataRegFullInterruptEnable);
UART_EnableInterrupts(uart_addrs[obj->serial.index], kUART_RxDataRegFullInterruptEnable);
break;
case TxIrq:
UART_EnableInterrupts(uart_addrs[obj->index], kUART_TxDataRegEmptyInterruptEnable);
UART_EnableInterrupts(uart_addrs[obj->serial.index], kUART_TxDataRegEmptyInterruptEnable);
break;
default:
break;
}
NVIC_SetVector(uart_irqs[obj->index], vector);
NVIC_EnableIRQ(uart_irqs[obj->index]);
NVIC_SetVector(uart_irqs[obj->serial.index], vector);
NVIC_EnableIRQ(uart_irqs[obj->serial.index]);
} else { // disable
int all_disabled = 0;
SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq);
switch (irq) {
case RxIrq:
UART_DisableInterrupts(uart_addrs[obj->index], kUART_RxDataRegFullInterruptEnable);
UART_DisableInterrupts(uart_addrs[obj->serial.index], kUART_RxDataRegFullInterruptEnable);
break;
case TxIrq:
UART_DisableInterrupts(uart_addrs[obj->index], kUART_TxDataRegEmptyInterruptEnable);
UART_DisableInterrupts(uart_addrs[obj->serial.index], kUART_TxDataRegEmptyInterruptEnable);
break;
default:
break;
}
switch (other_irq) {
case RxIrq:
all_disabled = ((UART_GetEnabledInterrupts(uart_addrs[obj->index]) & kUART_RxDataRegFullInterruptEnable) == 0);
all_disabled = ((UART_GetEnabledInterrupts(uart_addrs[obj->serial.index]) & kUART_RxDataRegFullInterruptEnable) == 0);
break;
case TxIrq:
all_disabled = ((UART_GetEnabledInterrupts(uart_addrs[obj->index]) & kUART_TxDataRegEmptyInterruptEnable) == 0);
all_disabled = ((UART_GetEnabledInterrupts(uart_addrs[obj->serial.index]) & kUART_TxDataRegEmptyInterruptEnable) == 0);
break;
default:
break;
}
if (all_disabled)
NVIC_DisableIRQ(uart_irqs[obj->index]);
NVIC_DisableIRQ(uart_irqs[obj->serial.index]);
}
}
@ -251,7 +264,7 @@ int serial_getc(serial_t *obj)
{
while (!serial_readable(obj));
uint8_t data;
data = UART_ReadByte(uart_addrs[obj->index]);
data = UART_ReadByte(uart_addrs[obj->serial.index]);
return data;
}
@ -259,22 +272,22 @@ int serial_getc(serial_t *obj)
void serial_putc(serial_t *obj, int c)
{
while (!serial_writable(obj));
UART_WriteByte(uart_addrs[obj->index], (uint8_t)c);
UART_WriteByte(uart_addrs[obj->serial.index], (uint8_t)c);
}
int serial_readable(serial_t *obj)
{
uint32_t status_flags = UART_GetStatusFlags(uart_addrs[obj->index]);
uint32_t status_flags = UART_GetStatusFlags(uart_addrs[obj->serial.index]);
if (status_flags & kUART_RxOverrunFlag)
UART_ClearStatusFlags(uart_addrs[obj->index], kUART_RxOverrunFlag);
UART_ClearStatusFlags(uart_addrs[obj->serial.index], kUART_RxOverrunFlag);
return (status_flags & kUART_RxDataRegFullFlag);
}
int serial_writable(serial_t *obj)
{
uint32_t status_flags = UART_GetStatusFlags(uart_addrs[obj->index]);
uint32_t status_flags = UART_GetStatusFlags(uart_addrs[obj->serial.index]);
if (status_flags & kUART_RxOverrunFlag)
UART_ClearStatusFlags(uart_addrs[obj->index], kUART_RxOverrunFlag);
UART_ClearStatusFlags(uart_addrs[obj->serial.index], kUART_RxOverrunFlag);
return (status_flags & kUART_TxDataRegEmptyFlag);
}
@ -289,12 +302,12 @@ void serial_pinout_tx(PinName tx)
void serial_break_set(serial_t *obj)
{
uart_addrs[obj->index]->C2 |= UART_C2_SBK_MASK;
uart_addrs[obj->serial.index]->C2 |= UART_C2_SBK_MASK;
}
void serial_break_clear(serial_t *obj)
{
uart_addrs[obj->index]->C2 &= ~UART_C2_SBK_MASK;
uart_addrs[obj->serial.index]->C2 &= ~UART_C2_SBK_MASK;
}
#if DEVICE_SERIAL_FC
@ -307,24 +320,24 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
switch(type) {
case FlowControlRTS:
pinmap_pinout(rxflow, PinMap_UART_RTS);
uart_addrs[obj->index]->MODEM &= ~UART_MODEM_TXCTSE_MASK;
uart_addrs[obj->index]->MODEM |= UART_MODEM_RXRTSE_MASK;
uart_addrs[obj->serial.index]->MODEM &= ~UART_MODEM_TXCTSE_MASK;
uart_addrs[obj->serial.index]->MODEM |= UART_MODEM_RXRTSE_MASK;
break;
case FlowControlCTS:
pinmap_pinout(txflow, PinMap_UART_CTS);
uart_addrs[obj->index]->MODEM &= ~UART_MODEM_RXRTSE_MASK;
uart_addrs[obj->index]->MODEM |= UART_MODEM_TXCTSE_MASK;
uart_addrs[obj->serial.index]->MODEM &= ~UART_MODEM_RXRTSE_MASK;
uart_addrs[obj->serial.index]->MODEM |= UART_MODEM_TXCTSE_MASK;
break;
case FlowControlRTSCTS:
pinmap_pinout(rxflow, PinMap_UART_RTS);
pinmap_pinout(txflow, PinMap_UART_CTS);
uart_addrs[obj->index]->MODEM |= UART_MODEM_TXCTSE_MASK | UART_MODEM_RXRTSE_MASK;
uart_addrs[obj->serial.index]->MODEM |= UART_MODEM_TXCTSE_MASK | UART_MODEM_RXRTSE_MASK;
break;
case FlowControlNone:
uart_addrs[obj->index]->MODEM &= ~(UART_MODEM_TXCTSE_MASK | UART_MODEM_RXRTSE_MASK);
uart_addrs[obj->serial.index]->MODEM &= ~(UART_MODEM_TXCTSE_MASK | UART_MODEM_RXRTSE_MASK);
break;
default:
@ -334,4 +347,366 @@ void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, Pi
#endif
static void serial_send_asynch(serial_t *obj)
{
uart_transfer_t sendXfer;
/*Setup send transfer*/
sendXfer.data = obj->tx_buff.buffer;
sendXfer.dataSize = obj->tx_buff.length;
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED ||
obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
UART_SendEDMA(uart_addrs[obj->serial.index], &obj->serial.uart_dma_handle, &sendXfer);
} else {
UART_TransferSendNonBlocking(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, &sendXfer);
}
}
static void serial_receive_asynch(serial_t *obj)
{
uart_transfer_t receiveXfer;
/*Setup send transfer*/
receiveXfer.data = obj->rx_buff.buffer;
receiveXfer.dataSize = obj->rx_buff.length;
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED ||
obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
UART_ReceiveEDMA(uart_addrs[obj->serial.index], &obj->serial.uart_dma_handle, &receiveXfer);
} else {
UART_TransferReceiveNonBlocking(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, &receiveXfer, NULL);
}
}
static bool serial_allocate_dma(serial_t *obj, uint32_t handler)
{
dma_request_source_t dma_rx_requests[] = UART_DMA_RX_REQUEST_NUMBERS;
dma_request_source_t dma_tx_requests[] = UART_DMA_TX_REQUEST_NUMBERS;
edma_config_t userConfig;
/* Allocate the UART RX DMA channel */
obj->serial.uartDmaRx.dmaChannel = dma_channel_allocate(dma_rx_requests[obj->serial.index]);
if (obj->serial.uartDmaRx.dmaChannel == DMA_ERROR_OUT_OF_CHANNELS) {
return false;
}
/* Allocate the UART TX DMA channel */
obj->serial.uartDmaTx.dmaChannel = dma_channel_allocate(dma_tx_requests[obj->serial.index]);
if (obj->serial.uartDmaTx.dmaChannel == DMA_ERROR_OUT_OF_CHANNELS) {
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
return false;
}
/* EDMA init*/
/*
* userConfig.enableRoundRobinArbitration = false;
* userConfig.enableHaltOnError = true;
* userConfig.enableContinuousLinkMode = false;
* userConfig.enableDebugMode = false;
*/
EDMA_GetDefaultConfig(&userConfig);
EDMA_Init(DMA0, &userConfig);
memset(&(obj->serial.uartDmaTx.handle), 0, sizeof(obj->serial.uartDmaTx.handle));
memset(&(obj->serial.uartDmaRx.handle), 0, sizeof(obj->serial.uartDmaRx.handle));
EDMA_CreateHandle(&(obj->serial.uartDmaRx.handle), DMA0, obj->serial.uartDmaRx.dmaChannel);
EDMA_CreateHandle(&(obj->serial.uartDmaTx.handle), DMA0, obj->serial.uartDmaTx.dmaChannel);
UART_TransferCreateHandleEDMA(uart_addrs[obj->serial.index], &obj->serial.uart_dma_handle, (uart_edma_transfer_callback_t)handler,
NULL, &obj->serial.uartDmaTx.handle, &obj->serial.uartDmaRx.handle);
return true;
}
void serial_enable_dma(serial_t *obj, uint32_t handler, DMAUsage state)
{
dma_init();
if (state == DMA_USAGE_ALWAYS && obj->serial.uartDmaRx.dmaUsageState != DMA_USAGE_ALLOCATED) {
/* Try to allocate channels */
if (serial_allocate_dma(obj, handler)) {
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_ALLOCATED;
} else {
obj->serial.uartDmaRx.dmaUsageState = state;
}
} else if (state == DMA_USAGE_OPPORTUNISTIC) {
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED) {
/* Channels have already been allocated previously by an ALWAYS state, so after this transfer, we will release them */
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
} else {
/* Try to allocate channels */
if (serial_allocate_dma(obj, handler)) {
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_TEMPORARY_ALLOCATED;
} else {
obj->serial.uartDmaRx.dmaUsageState = state;
}
}
} else if (state == DMA_USAGE_NEVER) {
/* If channels are allocated, get rid of them */
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED) {
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
}
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_NEVER;
}
}
void serial_enable_event(serial_t *obj, int event, uint8_t enable)
{
// Keep track of the requested events.
if (enable) {
obj->serial.events |= event;
} else {
obj->serial.events &= ~event;
}
}
static void serial_tx_buffer_set(serial_t *obj, void *tx, int tx_length, uint8_t width) {
(void)width;
// Exit if a transmit is already on-going
if (serial_tx_active(obj)) {
return;
}
obj->tx_buff.buffer = tx;
obj->tx_buff.length = tx_length;
obj->tx_buff.pos = 0;
}
int serial_tx_asynch(serial_t *obj, const void *tx, size_t tx_length, uint8_t tx_width, uint32_t handler, uint32_t event, DMAUsage hint)
{
// Check that a buffer has indeed been set up
MBED_ASSERT(tx != (void*)0);
if (tx_length == 0) return 0;
if (serial_tx_active(obj)) {
return 0;
}
// Set up buffer
serial_tx_buffer_set(obj, (void *)tx, tx_length, tx_width);
// Set up events
serial_enable_event(obj, SERIAL_EVENT_TX_ALL, false);
serial_enable_event(obj, event, true);
/* If using DMA, allocate channels only if they have not already been allocated */
if (hint != DMA_USAGE_NEVER) {
/* User requested to transfer using DMA */
serial_enable_dma(obj, handler, hint);
/* Check if DMA setup was successful */
if (obj->serial.uartDmaRx.dmaUsageState != DMA_USAGE_ALLOCATED && obj->serial.uartDmaRx.dmaUsageState != DMA_USAGE_TEMPORARY_ALLOCATED) {
/* Set up an interrupt transfer as DMA is unavailable */
if (obj->serial.uart_transfer_handle.callback == 0) {
UART_TransferCreateHandle(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, (uart_transfer_callback_t)handler, NULL);
}
}
} else {
/* User requested to transfer using interrupts */
/* Disable the DMA */
serial_enable_dma(obj, handler, hint);
/* Set up the interrupt transfer */
if (obj->serial.uart_transfer_handle.callback == 0) {
UART_TransferCreateHandle(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, (uart_transfer_callback_t)handler, NULL);
}
}
/* Start the transfer */
serial_send_asynch(obj);
obj->serial.txstate = kUART_TxBusy;
return 0;
}
void serial_rx_buffer_set(serial_t *obj, void *rx, int rx_length, uint8_t width)
{
// We only support byte buffers for now
MBED_ASSERT(width == 8);
if (serial_rx_active(obj)) return;
obj->rx_buff.buffer = rx;
obj->rx_buff.length = rx_length;
obj->rx_buff.pos = 0;
return;
}
/* Character match is currently not supported */
void serial_rx_asynch(serial_t *obj, void *rx, size_t rx_length, uint8_t rx_width, uint32_t handler, uint32_t event, uint8_t char_match, DMAUsage hint)
{
// Check that a buffer has indeed been set up
MBED_ASSERT(rx != (void*)0);
if (rx_length == 0) return;
if (serial_rx_active(obj)) {
return;
}
// Set up buffer
serial_rx_buffer_set(obj,(void*) rx, rx_length, rx_width);
// Set up events
serial_enable_event(obj, SERIAL_EVENT_RX_ALL, false);
serial_enable_event(obj, event, true);
//obj->char_match = char_match;
/* If using DMA, allocate channels only if they have not already been allocated */
if (hint != DMA_USAGE_NEVER) {
/* User requested to transfer using DMA */
serial_enable_dma(obj, handler, hint);
/* Check if DMA setup was successful */
if (obj->serial.uartDmaRx.dmaUsageState != DMA_USAGE_ALLOCATED && obj->serial.uartDmaRx.dmaUsageState != DMA_USAGE_TEMPORARY_ALLOCATED) {
/* Set up an interrupt transfer as DMA is unavailable */
if (obj->serial.uart_transfer_handle.callback == 0) {
UART_TransferCreateHandle(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, (uart_transfer_callback_t)handler, NULL);
}
}
} else {
/* User requested to transfer using interrupts */
/* Disable the DMA */
serial_enable_dma(obj, handler, hint);
/* Set up the interrupt transfer */
if (obj->serial.uart_transfer_handle.callback == 0) {
UART_TransferCreateHandle(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle, (uart_transfer_callback_t)handler, NULL);
}
}
/* Start the transfer */
serial_receive_asynch(obj);
obj->serial.rxstate = kUART_RxBusy;
}
uint8_t serial_tx_active(serial_t *obj)
{
if (obj->serial.txstate == kUART_TxIdle) {
return 0;
}
return 1;
}
uint8_t serial_rx_active(serial_t *obj)
{
if (obj->serial.rxstate == kUART_RxIdle) {
return 0;
}
return 1;
}
int serial_irq_handler_asynch(serial_t *obj)
{
int status = 0;
//uint8_t *buf = (uint8_t*)obj->rx_buff.buffer;
uint32_t status_flags = UART_GetStatusFlags(uart_addrs[obj->serial.index]);
/* Determine whether the current scenario is DMA or IRQ, and act accordingly */
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED || obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
/* DMA implementation */
if ((obj->serial.txstate != kUART_TxIdle) && (obj->serial.uart_dma_handle.txState == kUART_TxIdle)) {
obj->serial.txstate = kUART_TxIdle;
status |= SERIAL_EVENT_TX_COMPLETE;
}
if ((obj->serial.rxstate != kUART_RxIdle) && (obj->serial.uart_dma_handle.rxState == kUART_RxIdle)) {
obj->serial.rxstate = kUART_RxIdle;
status |= SERIAL_EVENT_RX_COMPLETE;
}
/* Release the dma channels if they were opportunistically allocated */
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
/* Ensure both TX and RX channels are idle before freeing them */
if ((obj->serial.uart_dma_handle.txState == kUART_TxIdle) && (obj->serial.uart_dma_handle.rxState == kUART_RxIdle)) {
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
dma_channel_free(obj->serial.uartDmaTx.dmaChannel);
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
}
}
} else {
/* Interrupt implementation */
if ((obj->serial.txstate != kUART_TxIdle) && (obj->serial.uart_transfer_handle.txState == kUART_TxIdle)) {
obj->serial.txstate = kUART_TxIdle;
status |= SERIAL_EVENT_TX_COMPLETE;
}
if ((obj->serial.rxstate != kUART_RxIdle) && (obj->serial.uart_transfer_handle.rxState == kUART_RxIdle)) {
obj->serial.rxstate = kUART_RxIdle;
status |= SERIAL_EVENT_RX_COMPLETE;
}
}
#if 0
if (obj->char_match != SERIAL_RESERVED_CHAR_MATCH){
/* Check for character match event */
if (buf[obj->rx_buff.length - 1] == obj->char_match) {
status |= SERIAL_EVENT_RX_CHARACTER_MATCH;
}
}
#endif
if (status_flags & kUART_RxOverrunFlag) {
UART_ClearStatusFlags(uart_addrs[obj->serial.index], kUART_RxOverrunFlag);
status |= SERIAL_EVENT_RX_OVERRUN_ERROR;
}
if (status_flags & kUART_FramingErrorFlag) {
UART_ClearStatusFlags(uart_addrs[obj->serial.index], kUART_FramingErrorFlag);
status |= SERIAL_EVENT_RX_FRAMING_ERROR;
}
if (status_flags & kUART_ParityErrorFlag) {
UART_ClearStatusFlags(uart_addrs[obj->serial.index], kUART_ParityErrorFlag);
status |= SERIAL_EVENT_RX_PARITY_ERROR;
}
return status & obj->serial.events;
}
void serial_tx_abort_asynch(serial_t *obj)
{
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED || obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
UART_TransferAbortSendEDMA(uart_addrs[obj->serial.index], &obj->serial.uart_dma_handle);
/* Release the dma channels if they were opportunistically allocated */
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
/* Ensure both TX and RX channels are idle before freeing them */
if ((obj->serial.uart_dma_handle.txState == kUART_TxIdle) && (obj->serial.uart_dma_handle.rxState == kUART_RxIdle)) {
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
dma_channel_free(obj->serial.uartDmaTx.dmaChannel);
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
}
}
} else {
UART_TransferAbortSend(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle);
}
}
void serial_rx_abort_asynch(serial_t *obj)
{
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_ALLOCATED || obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
UART_TransferAbortReceiveEDMA(uart_addrs[obj->serial.index], &obj->serial.uart_dma_handle);
/* Release the dma channels if they were opportunistically allocated */
if (obj->serial.uartDmaRx.dmaUsageState == DMA_USAGE_TEMPORARY_ALLOCATED) {
/* Ensure both TX and RX channels are idle before freeing them */
if ((obj->serial.uart_dma_handle.txState == kUART_TxIdle) && (obj->serial.uart_dma_handle.rxState == kUART_RxIdle)) {
dma_channel_free(obj->serial.uartDmaRx.dmaChannel);
dma_channel_free(obj->serial.uartDmaTx.dmaChannel);
obj->serial.uartDmaRx.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
}
}
} else {
UART_TransferAbortReceive(uart_addrs[obj->serial.index], &obj->serial.uart_transfer_handle);
}
}
#endif

View File

@ -23,6 +23,9 @@
#if DEVICE_SPI_ASYNCH
#include "fsl_dspi_edma.h"
#endif
#if DEVICE_SERIAL_ASYNCH
#include "fsl_uart_edma.h"
#endif
#include "dma_api_hal.h"
#ifdef __cplusplus
@ -46,6 +49,15 @@ struct pwmout_s {
struct serial_s {
int index;
#if DEVICE_SERIAL_ASYNCH
uint8_t txstate;
uint8_t rxstate;
uint32_t events;
uart_handle_t uart_transfer_handle;
uart_edma_handle_t uart_dma_handle;
dma_options_t uartDmaTx;
dma_options_t uartDmaRx;
#endif
};
struct analogin_s {

View File

@ -576,7 +576,7 @@
"macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"],
"inherits": ["Target"],
"detect_code": ["0240"],
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG"],
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "STORAGE", "TRNG"],
"features": ["LWIP", "STORAGE"],
"release_versions": ["2", "5"],
"device_name": "MK64FN1M0xxx12"
@ -588,7 +588,7 @@
"extra_labels": ["Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F"],
"is_disk_virtual": true,
"macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED", "TARGET_K64F"],
"device_has": ["I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES"],
"device_has": ["I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES"],
"device_name": "MK64FN1M0xxx12"
},
"HEXIWEAR": {
@ -600,7 +600,7 @@
"is_disk_virtual": true,
"default_toolchain": "ARM",
"detect_code": ["0214"],
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
"device_has": ["ANALOGIN", "ANALOGOUT", "ERROR_RED", "I2C", "I2CSLAVE", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SERIAL_FC", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE", "STDIO_MESSAGES", "TRNG"],
"default_lib": "std",
"release_versions": ["2", "5"],
"device_name": "MK64FN1M0xxx12"