Initial: MCU_UART hardware UART driver with DMA/ISR TX and ring buffer RX
This commit is contained in:
commit
5313ee98d2
26
cfg/MCU_UART_cfg.c
Normal file
26
cfg/MCU_UART_cfg.c
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* File: MCU_UART_cfg.c
|
||||||
|
* Component: MCU_UART
|
||||||
|
* Description: Configuration array definition for the MCU_UART driver.
|
||||||
|
*
|
||||||
|
* Layer: MCU (hardware abstraction) - configuration
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MCU_UART.h"
|
||||||
|
#include "MCU_UART_cfg.h"
|
||||||
|
|
||||||
|
const MCU_UART_tstrConfig MCU_UART_astrConfig[MCU_UART_NUM_INSTANCES] =
|
||||||
|
{
|
||||||
|
[MCU_UART_INSTANCE_0] =
|
||||||
|
{
|
||||||
|
.u8TxPin = MCU_UART_0_TX_PIN,
|
||||||
|
.u8RxPin = MCU_UART_0_RX_PIN,
|
||||||
|
.u32BaudRate = MCU_UART_0_BAUD_RATE,
|
||||||
|
.enuDataBits = MCU_UART_0_DATA_BITS,
|
||||||
|
.enuStopBits = MCU_UART_0_STOP_BITS,
|
||||||
|
.enuParity = MCU_UART_0_PARITY,
|
||||||
|
.enuTxAsyncMode = MCU_UART_0_TX_ASYNC_MODE,
|
||||||
|
.pfTxCompleteCallback = MCU_UART_0_TX_COMPLETE_CALLBACK,
|
||||||
|
.enuRxAsyncMode = MCU_UART_0_RX_ASYNC_MODE,
|
||||||
|
},
|
||||||
|
};
|
||||||
51
cfg/MCU_UART_cfg.h
Normal file
51
cfg/MCU_UART_cfg.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* File: MCU_UART_cfg.h
|
||||||
|
* Component: MCU_UART
|
||||||
|
* Description: Configuration for the MCU_UART driver. Defines instances,
|
||||||
|
* pin assignments, baud rates, data format, TX/RX async modes,
|
||||||
|
* and RX buffer sizing.
|
||||||
|
*
|
||||||
|
* Layer: MCU (hardware abstraction) - configuration
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MCU_UART_CFG_H
|
||||||
|
#define MCU_UART_CFG_H
|
||||||
|
|
||||||
|
#include "STD_TYPES.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* INSTANCE ENUMERATION */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCU_UART_INSTANCE_0 = 0U,
|
||||||
|
MCU_UART_NUM_INSTANCES
|
||||||
|
} MCU_UART_tenuInstance;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* RX RING BUFFER SIZING */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/** @brief Number of address bits for the RX ring buffer (2^N bytes).
|
||||||
|
* Must be power of 2 for DMA ring wrap.
|
||||||
|
* 5 = 32, 6 = 64, 7 = 128, 8 = 256. */
|
||||||
|
#define MCU_UART_RX_BUFFER_SIZE_BITS 6U
|
||||||
|
#define MCU_UART_RX_BUFFER_SIZE (1U << MCU_UART_RX_BUFFER_SIZE_BITS)
|
||||||
|
#define MCU_UART_RX_BUFFER_MASK (MCU_UART_RX_BUFFER_SIZE - 1U)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* INSTANCE 0 CONFIGURATION */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define MCU_UART_0_TX_PIN 0U
|
||||||
|
#define MCU_UART_0_RX_PIN 1U
|
||||||
|
#define MCU_UART_0_BAUD_RATE 115200U
|
||||||
|
#define MCU_UART_0_DATA_BITS MCU_UART_DATA_BITS_8
|
||||||
|
#define MCU_UART_0_STOP_BITS MCU_UART_STOP_BITS_1
|
||||||
|
#define MCU_UART_0_PARITY MCU_UART_PARITY_NONE
|
||||||
|
#define MCU_UART_0_TX_ASYNC_MODE MCU_UART_ASYNC_DMA
|
||||||
|
#define MCU_UART_0_TX_COMPLETE_CALLBACK STD_NULL
|
||||||
|
#define MCU_UART_0_RX_ASYNC_MODE MCU_UART_ASYNC_ISR
|
||||||
|
|
||||||
|
#endif /* MCU_UART_CFG_H */
|
||||||
124
inc/MCU_UART.h
Normal file
124
inc/MCU_UART.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* File: MCU_UART.h
|
||||||
|
* Component: MCU_UART
|
||||||
|
* Description: Public interface for the MCU UART driver component.
|
||||||
|
*
|
||||||
|
* TX: SendByte (blocking), SendBuffer (non-blocking DMA/ISR),
|
||||||
|
* SendBufferBlocking.
|
||||||
|
* RX: background ring buffer filled by ISR or DMA.
|
||||||
|
* ReadByte / ReadBuffer read from the buffer (non-blocking).
|
||||||
|
*
|
||||||
|
* Layer: MCU (hardware abstraction)
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MCU_UART_H
|
||||||
|
#define MCU_UART_H
|
||||||
|
|
||||||
|
#include "STD_TYPES.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* CONFIGURATION VALUE TYPES */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCU_UART_PARITY_NONE = 0U,
|
||||||
|
MCU_UART_PARITY_EVEN,
|
||||||
|
MCU_UART_PARITY_ODD
|
||||||
|
} MCU_UART_tenuParity;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCU_UART_DATA_BITS_5 = 5U,
|
||||||
|
MCU_UART_DATA_BITS_6 = 6U,
|
||||||
|
MCU_UART_DATA_BITS_7 = 7U,
|
||||||
|
MCU_UART_DATA_BITS_8 = 8U
|
||||||
|
} MCU_UART_tenuDataBits;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCU_UART_STOP_BITS_1 = 1U,
|
||||||
|
MCU_UART_STOP_BITS_2 = 2U
|
||||||
|
} MCU_UART_tenuStopBits;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MCU_UART_ASYNC_DMA = 0U,
|
||||||
|
MCU_UART_ASYNC_ISR
|
||||||
|
} MCU_UART_tenuAsyncMode;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* CONFIGURATION STRUCTURE */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
u8 u8TxPin;
|
||||||
|
u8 u8RxPin;
|
||||||
|
u32 u32BaudRate;
|
||||||
|
MCU_UART_tenuDataBits enuDataBits;
|
||||||
|
MCU_UART_tenuStopBits enuStopBits;
|
||||||
|
MCU_UART_tenuParity enuParity;
|
||||||
|
MCU_UART_tenuAsyncMode enuTxAsyncMode;
|
||||||
|
STD_tpfCallbackFunc pfTxCompleteCallback;
|
||||||
|
MCU_UART_tenuAsyncMode enuRxAsyncMode;
|
||||||
|
} MCU_UART_tstrConfig;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* TX PUBLIC API */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuInit(void);
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendByte(u8 u8Instance, u8 u8Byte);
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendBuffer(u8 u8Instance, const u8 *pu8Data, u16 u16Length);
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendBufferBlocking(u8 u8Instance, const u8 *pu8Data, u16 u16Length);
|
||||||
|
|
||||||
|
STD_tBool MCU_UART_bIsTxBusy(u8 u8Instance);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* RX PUBLIC API */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read one byte from the RX ring buffer (non-blocking).
|
||||||
|
*
|
||||||
|
* The ring buffer is filled in the background by ISR or DMA.
|
||||||
|
* Returns immediately — STD_OK with the byte, or STD_NOK if empty.
|
||||||
|
*
|
||||||
|
* @param u8Instance UART instance index.
|
||||||
|
* @param pu8Byte Pointer to store the received byte.
|
||||||
|
* @return STD_OK byte read,
|
||||||
|
* STD_NULL_POINTER_ERROR if pu8Byte is NULL,
|
||||||
|
* STD_NOK if ring buffer is empty.
|
||||||
|
*/
|
||||||
|
STD_tenuResult MCU_UART_enuReadByte(u8 u8Instance, u8 *pu8Byte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read up to u16MaxLength bytes from the RX ring buffer (non-blocking).
|
||||||
|
*
|
||||||
|
* Copies as many bytes as are currently available (up to u16MaxLength)
|
||||||
|
* into pu8Data. Reports the actual number of bytes read via pu16Read.
|
||||||
|
* Returns immediately even if fewer than u16MaxLength bytes are available.
|
||||||
|
*
|
||||||
|
* @param u8Instance UART instance index.
|
||||||
|
* @param pu8Data Pointer to output buffer.
|
||||||
|
* @param u16MaxLength Maximum bytes to read.
|
||||||
|
* @param pu16Read Pointer to store actual bytes read. Must not be NULL.
|
||||||
|
* @return STD_OK at least one byte read,
|
||||||
|
* STD_NULL_POINTER_ERROR if pu8Data or pu16Read is NULL,
|
||||||
|
* STD_NOK if ring buffer is empty (zero bytes read).
|
||||||
|
*/
|
||||||
|
STD_tenuResult MCU_UART_enuReadBuffer(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if the RX ring buffer has data.
|
||||||
|
*
|
||||||
|
* @param u8Instance UART instance index.
|
||||||
|
* @return STD_TRUE if at least one byte available, STD_FALSE if empty.
|
||||||
|
*/
|
||||||
|
STD_tBool MCU_UART_bIsRxDataAvailable(u8 u8Instance);
|
||||||
|
|
||||||
|
#endif /* MCU_UART_H */
|
||||||
421
prg/MCU_UART_prg.c
Normal file
421
prg/MCU_UART_prg.c
Normal file
@ -0,0 +1,421 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* File: MCU_UART_prg.c
|
||||||
|
* Component: MCU_UART
|
||||||
|
* Description: TX: blocking + non-blocking (DMA or ISR) with callback.
|
||||||
|
* RX: ISR or DMA fills ring buffer in background. ReadByte
|
||||||
|
* and ReadBuffer read from the buffer non-blocking.
|
||||||
|
*
|
||||||
|
* Layer: MCU (hardware abstraction)
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MCU_UART.h"
|
||||||
|
#include "MCU_UART_priv.h"
|
||||||
|
#include "MCU_UART_cfg.h"
|
||||||
|
|
||||||
|
#include "hardware/uart.h"
|
||||||
|
#include "hardware/gpio.h"
|
||||||
|
#include "hardware/dma.h"
|
||||||
|
#include "hardware/irq.h"
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* INSTANCE LOOKUP TABLE */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static uart_inst_t * const apstrInstances[] = { uart0, uart1 };
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* RUNTIME STATE */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static MCU_UART_tstrControl strControl;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* INTERNAL HELPERS */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void vCallTxCallback(u8 u8Instance)
|
||||||
|
{
|
||||||
|
STD_tpfCallbackFunc pfCbLoc = MCU_UART_astrConfig[u8Instance].pfTxCompleteCallback;
|
||||||
|
|
||||||
|
if (pfCbLoc != STD_NULL)
|
||||||
|
{
|
||||||
|
pfCbLoc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get current RX head. DMA mode derives from hw write pointer. */
|
||||||
|
static u16 u16GetRxHead(u8 u8Instance)
|
||||||
|
{
|
||||||
|
u16 u16HeadLoc;
|
||||||
|
|
||||||
|
if (MCU_UART_astrConfig[u8Instance].enuRxAsyncMode == MCU_UART_ASYNC_DMA)
|
||||||
|
{
|
||||||
|
s8 s8ChLoc = strControl.as8RxDmaChannel[u8Instance];
|
||||||
|
u32 u32WrLoc = (u32)dma_channel_hw_addr((u32)s8ChLoc)->write_addr;
|
||||||
|
u32 u32BaseLoc = (u32)(&strControl.aau8RxBuffer[u8Instance][0]);
|
||||||
|
u16HeadLoc = (u16)((u32WrLoc - u32BaseLoc) & MCU_UART_RX_BUFFER_MASK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u16HeadLoc = strControl.au16RxHead[u8Instance];
|
||||||
|
}
|
||||||
|
|
||||||
|
return u16HeadLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* TX DMA IRQ HANDLER (INSTANCE 0) */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void vTxDmaIrqHandler0(void)
|
||||||
|
{
|
||||||
|
s8 s8ChLoc = strControl.as8TxDmaChannel[MCU_UART_INSTANCE_0];
|
||||||
|
u32 u32StatusLoc = dma_channel_get_irq0_status((u32)s8ChLoc);
|
||||||
|
|
||||||
|
if (u32StatusLoc != 0U)
|
||||||
|
{
|
||||||
|
dma_irqn_acknowledge_channel(0, (u32)s8ChLoc);
|
||||||
|
strControl.abTxBusy[MCU_UART_INSTANCE_0] = STD_FALSE;
|
||||||
|
vCallTxCallback((u8)MCU_UART_INSTANCE_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
/* UART ISR HANDLER (RX + TX) */
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static void vUartIsrHandler(u8 u8Instance)
|
||||||
|
{
|
||||||
|
uart_inst_t *pstrUartLoc = apstrInstances[u8Instance];
|
||||||
|
|
||||||
|
/* --- RX: drain FIFO into ring buffer --- */
|
||||||
|
STD_tBool bReadableLoc = (uart_is_readable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
|
||||||
|
while (bReadableLoc == STD_TRUE)
|
||||||
|
{
|
||||||
|
u8 u8ByteLoc = (u8)uart_getc(pstrUartLoc);
|
||||||
|
u16 u16HeadLoc = strControl.au16RxHead[u8Instance];
|
||||||
|
|
||||||
|
strControl.aau8RxBuffer[u8Instance][u16HeadLoc] = u8ByteLoc;
|
||||||
|
strControl.au16RxHead[u8Instance] = (u16HeadLoc + 1U) & MCU_UART_RX_BUFFER_MASK;
|
||||||
|
|
||||||
|
bReadableLoc = (uart_is_readable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- TX: fill FIFO from buffer (if TX ISR active) --- */
|
||||||
|
STD_tBool bTxBusyLoc = strControl.abTxBusy[u8Instance];
|
||||||
|
|
||||||
|
if (bTxBusyLoc == STD_TRUE)
|
||||||
|
{
|
||||||
|
STD_tBool bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
STD_tBool bDataLeft = (strControl.au16TxIndex[u8Instance] < strControl.au16TxLength[u8Instance]) ? STD_TRUE : STD_FALSE;
|
||||||
|
|
||||||
|
while ((bFifoReady == STD_TRUE) && (bDataLeft == STD_TRUE))
|
||||||
|
{
|
||||||
|
uart_putc_raw(pstrUartLoc,
|
||||||
|
strControl.apu8TxBuffer[u8Instance][strControl.au16TxIndex[u8Instance]]);
|
||||||
|
strControl.au16TxIndex[u8Instance]++;
|
||||||
|
|
||||||
|
bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
bDataLeft = (strControl.au16TxIndex[u8Instance] < strControl.au16TxLength[u8Instance]) ? STD_TRUE : STD_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bDataLeft == STD_FALSE)
|
||||||
|
{
|
||||||
|
uart_set_irqs_enabled(pstrUartLoc, false, true);
|
||||||
|
strControl.abTxBusy[u8Instance] = STD_FALSE;
|
||||||
|
vCallTxCallback(u8Instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vUart0IrqHandler(void)
|
||||||
|
{
|
||||||
|
vUartIsrHandler((u8)MCU_UART_INSTANCE_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* INIT */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuInit(void)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
u8 u8IndexLoc;
|
||||||
|
|
||||||
|
for (u8IndexLoc = 0U; u8IndexLoc < (u8)MCU_UART_NUM_INSTANCES; u8IndexLoc++)
|
||||||
|
{
|
||||||
|
strControl.apu8TxBuffer[u8IndexLoc] = STD_NULL;
|
||||||
|
strControl.au16TxLength[u8IndexLoc] = 0U;
|
||||||
|
strControl.au16TxIndex[u8IndexLoc] = 0U;
|
||||||
|
strControl.abTxBusy[u8IndexLoc] = STD_FALSE;
|
||||||
|
strControl.as8TxDmaChannel[u8IndexLoc] = -1;
|
||||||
|
strControl.au16RxHead[u8IndexLoc] = 0U;
|
||||||
|
strControl.au16RxTail[u8IndexLoc] = 0U;
|
||||||
|
strControl.as8RxDmaChannel[u8IndexLoc] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u8IndexLoc = 0U; u8IndexLoc < (u8)MCU_UART_NUM_INSTANCES; u8IndexLoc++)
|
||||||
|
{
|
||||||
|
const MCU_UART_tstrConfig *pstrCfgLoc = &MCU_UART_astrConfig[u8IndexLoc];
|
||||||
|
uart_inst_t *pstrUartLoc = apstrInstances[u8IndexLoc];
|
||||||
|
|
||||||
|
uart_init(pstrUartLoc, pstrCfgLoc->u32BaudRate);
|
||||||
|
gpio_set_function(pstrCfgLoc->u8TxPin, GPIO_FUNC_UART);
|
||||||
|
gpio_set_function(pstrCfgLoc->u8RxPin, GPIO_FUNC_UART);
|
||||||
|
uart_set_format(pstrUartLoc,
|
||||||
|
pstrCfgLoc->enuDataBits,
|
||||||
|
pstrCfgLoc->enuStopBits,
|
||||||
|
pstrCfgLoc->enuParity);
|
||||||
|
|
||||||
|
/* TX async setup */
|
||||||
|
if (pstrCfgLoc->enuTxAsyncMode == MCU_UART_ASYNC_DMA)
|
||||||
|
{
|
||||||
|
s8 s8ChLoc = (s8)dma_claim_unused_channel(true);
|
||||||
|
strControl.as8TxDmaChannel[u8IndexLoc] = s8ChLoc;
|
||||||
|
dma_channel_set_irq0_enabled((u32)s8ChLoc, true);
|
||||||
|
|
||||||
|
if (u8IndexLoc == (u8)MCU_UART_INSTANCE_0)
|
||||||
|
{
|
||||||
|
irq_set_exclusive_handler(DMA_IRQ_0, vTxDmaIrqHandler0);
|
||||||
|
irq_set_enabled(DMA_IRQ_0, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RX async setup */
|
||||||
|
if (pstrCfgLoc->enuRxAsyncMode == MCU_UART_ASYNC_DMA)
|
||||||
|
{
|
||||||
|
s8 s8RxChLoc = (s8)dma_claim_unused_channel(true);
|
||||||
|
strControl.as8RxDmaChannel[u8IndexLoc] = s8RxChLoc;
|
||||||
|
|
||||||
|
dma_channel_config strRxCfgLoc = dma_channel_get_default_config((u32)s8RxChLoc);
|
||||||
|
channel_config_set_transfer_data_size(&strRxCfgLoc, DMA_SIZE_8);
|
||||||
|
channel_config_set_read_increment(&strRxCfgLoc, false);
|
||||||
|
channel_config_set_write_increment(&strRxCfgLoc, true);
|
||||||
|
channel_config_set_dreq(&strRxCfgLoc, uart_get_dreq(pstrUartLoc, false));
|
||||||
|
channel_config_set_ring(&strRxCfgLoc, true, MCU_UART_RX_BUFFER_SIZE_BITS);
|
||||||
|
|
||||||
|
dma_channel_configure(
|
||||||
|
(u32)s8RxChLoc,
|
||||||
|
&strRxCfgLoc,
|
||||||
|
&strControl.aau8RxBuffer[u8IndexLoc][0],
|
||||||
|
&uart_get_hw(pstrUartLoc)->dr,
|
||||||
|
0xFFFFFFFFU,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (u8IndexLoc == (u8)MCU_UART_INSTANCE_0)
|
||||||
|
{
|
||||||
|
irq_set_exclusive_handler(UART0_IRQ, vUart0IrqHandler);
|
||||||
|
irq_set_enabled(UART0_IRQ, true);
|
||||||
|
}
|
||||||
|
uart_set_irqs_enabled(pstrUartLoc, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* SEND BYTE (BLOCKING) */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendByte(u8 u8Instance, u8 u8Byte)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
|
||||||
|
uart_putc_raw(apstrInstances[u8Instance], u8Byte);
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* SEND BUFFER (NON-BLOCKING) */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendBuffer(u8 u8Instance, const u8 *pu8Data, u16 u16Length)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
STD_tBool bBusyLoc = strControl.abTxBusy[u8Instance];
|
||||||
|
MCU_UART_tenuAsyncMode enuModeLoc = MCU_UART_astrConfig[u8Instance].enuTxAsyncMode;
|
||||||
|
|
||||||
|
if (pu8Data == STD_NULL)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NULL_POINTER_ERROR;
|
||||||
|
}
|
||||||
|
else if (bBusyLoc == STD_TRUE)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NOK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strControl.apu8TxBuffer[u8Instance] = pu8Data;
|
||||||
|
strControl.au16TxLength[u8Instance] = u16Length;
|
||||||
|
strControl.au16TxIndex[u8Instance] = 0U;
|
||||||
|
strControl.abTxBusy[u8Instance] = STD_TRUE;
|
||||||
|
|
||||||
|
if (enuModeLoc == MCU_UART_ASYNC_DMA)
|
||||||
|
{
|
||||||
|
s8 s8ChLoc = strControl.as8TxDmaChannel[u8Instance];
|
||||||
|
uart_inst_t *pstrUartLoc = apstrInstances[u8Instance];
|
||||||
|
|
||||||
|
dma_channel_config strCfgLoc = dma_channel_get_default_config((u32)s8ChLoc);
|
||||||
|
channel_config_set_transfer_data_size(&strCfgLoc, DMA_SIZE_8);
|
||||||
|
channel_config_set_read_increment(&strCfgLoc, true);
|
||||||
|
channel_config_set_write_increment(&strCfgLoc, false);
|
||||||
|
channel_config_set_dreq(&strCfgLoc, uart_get_dreq(pstrUartLoc, true));
|
||||||
|
|
||||||
|
dma_channel_configure(
|
||||||
|
(u32)s8ChLoc, &strCfgLoc,
|
||||||
|
&uart_get_hw(pstrUartLoc)->dr, pu8Data, u16Length, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uart_inst_t *pstrUartLoc = apstrInstances[u8Instance];
|
||||||
|
STD_tBool bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
STD_tBool bDataLeft = (strControl.au16TxIndex[u8Instance] < u16Length) ? STD_TRUE : STD_FALSE;
|
||||||
|
|
||||||
|
while ((bFifoReady == STD_TRUE) && (bDataLeft == STD_TRUE))
|
||||||
|
{
|
||||||
|
uart_putc_raw(pstrUartLoc, pu8Data[strControl.au16TxIndex[u8Instance]]);
|
||||||
|
strControl.au16TxIndex[u8Instance]++;
|
||||||
|
bFifoReady = (uart_is_writable(pstrUartLoc) != 0) ? STD_TRUE : STD_FALSE;
|
||||||
|
bDataLeft = (strControl.au16TxIndex[u8Instance] < u16Length) ? STD_TRUE : STD_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bDataLeft == STD_FALSE)
|
||||||
|
{
|
||||||
|
strControl.abTxBusy[u8Instance] = STD_FALSE;
|
||||||
|
vCallTxCallback(u8Instance);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uart_set_irqs_enabled(pstrUartLoc, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* SEND BUFFER (BLOCKING) */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuSendBufferBlocking(u8 u8Instance, const u8 *pu8Data, u16 u16Length)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
u16 u16IndexLoc;
|
||||||
|
|
||||||
|
if (pu8Data == STD_NULL)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NULL_POINTER_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (u16IndexLoc = 0U; u16IndexLoc < u16Length; u16IndexLoc++)
|
||||||
|
{
|
||||||
|
uart_putc_raw(apstrInstances[u8Instance], pu8Data[u16IndexLoc]);
|
||||||
|
}
|
||||||
|
vCallTxCallback(u8Instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* TX BUSY CHECK */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tBool MCU_UART_bIsTxBusy(u8 u8Instance)
|
||||||
|
{
|
||||||
|
return strControl.abTxBusy[u8Instance];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* READ BYTE (NON-BLOCKING) */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuReadByte(u8 u8Instance, u8 *pu8Byte)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
|
||||||
|
if (pu8Byte == STD_NULL)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NULL_POINTER_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u16 u16HeadLoc = u16GetRxHead(u8Instance);
|
||||||
|
u16 u16TailLoc = strControl.au16RxTail[u8Instance];
|
||||||
|
|
||||||
|
if (u16HeadLoc == u16TailLoc)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NOK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pu8Byte = strControl.aau8RxBuffer[u8Instance][u16TailLoc];
|
||||||
|
strControl.au16RxTail[u8Instance] = (u16TailLoc + 1U) & MCU_UART_RX_BUFFER_MASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* READ BUFFER (NON-BLOCKING) */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tenuResult MCU_UART_enuReadBuffer(u8 u8Instance, u8 *pu8Data, u16 u16MaxLength, u16 *pu16Read)
|
||||||
|
{
|
||||||
|
STD_tenuResult enuResultLoc = STD_OK;
|
||||||
|
|
||||||
|
if ((pu8Data == STD_NULL) || (pu16Read == STD_NULL))
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NULL_POINTER_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u16 u16HeadLoc = u16GetRxHead(u8Instance);
|
||||||
|
u16 u16TailLoc = strControl.au16RxTail[u8Instance];
|
||||||
|
u16 u16CountLoc = 0U;
|
||||||
|
|
||||||
|
while ((u16HeadLoc != u16TailLoc) && (u16CountLoc < u16MaxLength))
|
||||||
|
{
|
||||||
|
pu8Data[u16CountLoc] = strControl.aau8RxBuffer[u8Instance][u16TailLoc];
|
||||||
|
u16TailLoc = (u16TailLoc + 1U) & MCU_UART_RX_BUFFER_MASK;
|
||||||
|
u16CountLoc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strControl.au16RxTail[u8Instance] = u16TailLoc;
|
||||||
|
*pu16Read = u16CountLoc;
|
||||||
|
|
||||||
|
if (u16CountLoc == 0U)
|
||||||
|
{
|
||||||
|
enuResultLoc = STD_NOK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return enuResultLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
/* RX DATA AVAILABLE CHECK */
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
STD_tBool MCU_UART_bIsRxDataAvailable(u8 u8Instance)
|
||||||
|
{
|
||||||
|
STD_tBool bResultLoc = STD_FALSE;
|
||||||
|
u16 u16HeadLoc = u16GetRxHead(u8Instance);
|
||||||
|
u16 u16TailLoc = strControl.au16RxTail[u8Instance];
|
||||||
|
|
||||||
|
if (u16HeadLoc != u16TailLoc)
|
||||||
|
{
|
||||||
|
bResultLoc = STD_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bResultLoc;
|
||||||
|
}
|
||||||
34
prg/MCU_UART_priv.h
Normal file
34
prg/MCU_UART_priv.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* File: MCU_UART_priv.h
|
||||||
|
* Component: MCU_UART
|
||||||
|
* Description: Private header — control struct and extern config array.
|
||||||
|
*
|
||||||
|
* Layer: MCU (hardware abstraction) - internal use only
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MCU_UART_PRIV_H
|
||||||
|
#define MCU_UART_PRIV_H
|
||||||
|
|
||||||
|
#include "MCU_UART.h"
|
||||||
|
#include "MCU_UART_cfg.h"
|
||||||
|
|
||||||
|
extern const MCU_UART_tstrConfig MCU_UART_astrConfig[MCU_UART_NUM_INSTANCES];
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* TX state */
|
||||||
|
const u8 *apu8TxBuffer[MCU_UART_NUM_INSTANCES];
|
||||||
|
u16 au16TxLength[MCU_UART_NUM_INSTANCES];
|
||||||
|
u16 au16TxIndex[MCU_UART_NUM_INSTANCES];
|
||||||
|
STD_tBool abTxBusy[MCU_UART_NUM_INSTANCES];
|
||||||
|
s8 as8TxDmaChannel[MCU_UART_NUM_INSTANCES];
|
||||||
|
|
||||||
|
/* RX ring buffer — filled by ISR or DMA in the background */
|
||||||
|
u8 aau8RxBuffer[MCU_UART_NUM_INSTANCES][MCU_UART_RX_BUFFER_SIZE]
|
||||||
|
__attribute__((aligned(MCU_UART_RX_BUFFER_SIZE)));
|
||||||
|
u16 au16RxHead[MCU_UART_NUM_INSTANCES];
|
||||||
|
u16 au16RxTail[MCU_UART_NUM_INSTANCES];
|
||||||
|
s8 as8RxDmaChannel[MCU_UART_NUM_INSTANCES];
|
||||||
|
} MCU_UART_tstrControl;
|
||||||
|
|
||||||
|
#endif /* MCU_UART_PRIV_H */
|
||||||
Loading…
x
Reference in New Issue
Block a user