mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-17 15:38:14 +08:00
821 lines
22 KiB
C
821 lines
22 KiB
C
/*
|
|
* Copyright 2016, MXCHIP.
|
|
* All Rights Reserved.
|
|
*/
|
|
|
|
/*
|
|
* uart.c: mxchip driver for UART
|
|
*/
|
|
|
|
#include <board.h>
|
|
#include <wmtypes.h>
|
|
#include <wmstdio.h>
|
|
#include <mdev_uart.h>
|
|
//#include <wm_os.h>
|
|
#include <pwrmgr.h>
|
|
#include <mdev_dma.h>
|
|
#include <wmassert.h>
|
|
#include <system-work-queue.h>
|
|
#include "common.h"
|
|
#include "mico_platform.h"
|
|
|
|
#define DISABLE_DMA
|
|
#ifdef DISABLE_DMA
|
|
#define NUM_UART_PORTS 3
|
|
#define UART_IRQn_BASE UART0_IRQn
|
|
#define UART_INT_BASE INT_UART0
|
|
|
|
#ifdef NO_MICO_RTOS
|
|
#define os_thread_relinquish()
|
|
#endif
|
|
|
|
|
|
static void (*uart_8bit_cb_p[NUM_UART_PORTS]) ();
|
|
static void (*uart_9bit_cb_p[NUM_UART_PORTS]) ();
|
|
|
|
#define SET_RX_BUF_SIZE(uart_data_p, size) \
|
|
uart_data_p->rx_ringbuf.buf_size = size
|
|
#define GET_RX_BUF_SIZE(uart_data_p) (uart_data_p->rx_ringbuf.buf_size)
|
|
|
|
#define SET_DMA_BLK_SIZE(uart_data_p, size) \
|
|
uart_data_p->rx_ringbuf.dma_block_size = size
|
|
#define GET_DMA_BLK_SIZE(uart_data_p) (uart_data_p->rx_ringbuf.dma_block_size)
|
|
|
|
#define DEFINE_UART_CB(id, mode) \
|
|
static void \
|
|
uart ## id ## _ ## mode ## bit_cb() {\
|
|
uart_ ## mode ## bit_cb(id); }
|
|
#define GET_UART_CB(id, mode) uart ## id ## _ ## mode ## bit_cb
|
|
|
|
extern platform_uart_t platform_uart_peripherals[];
|
|
extern platform_uart_driver_t platform_uart_drivers[];
|
|
|
|
/* UART callback functions */
|
|
static void uart_8bit_cb(int port_num)
|
|
{
|
|
uint8_t recv_byte, i;
|
|
platform_uart_driver_t* driver = NULL;
|
|
|
|
for ( i = 0; i < MICO_UART_MAX; i++ ) {
|
|
if ( platform_uart_peripherals[i].port_id == port_num ) {
|
|
driver = &platform_uart_drivers[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( driver == NULL ) return;
|
|
/* Receive new data */
|
|
while (UART_GetLineStatus(port_num, UART_LINESTATUS_DR) == SET) {
|
|
if (ring_buffer_is_full(driver->rx_ring_buffer) == 0) {
|
|
recv_byte = UART_ReceiveData(port_num);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
if ( ( driver->rx_size > 0 ) &&
|
|
( ring_buffer_used_space( driver->rx_ring_buffer) >= driver->rx_size ) ) {
|
|
mico_rtos_set_semaphore( &driver->rx_complete );
|
|
|
|
driver->rx_size = 0;
|
|
|
|
}
|
|
} else {
|
|
/* Rx Buffer is full, discard received data */
|
|
if (driver->flow_control != FLOW_CONTROL_DISABLED_DRV) {
|
|
/* We need to mask the interrupt till the data
|
|
is read; otherwise we keep getting
|
|
data-ready interrupt infinitely */
|
|
UART_IntMask(port_num, UART_INT_RDA, MASK);
|
|
return;
|
|
} else {
|
|
UART_ReceiveData(port_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void uart_9bit_cb(int port_num)
|
|
{
|
|
uint16_t data;
|
|
platform_uart_driver_t* driver = &platform_uart_drivers[port_num];
|
|
uint8_t recv_byte;
|
|
/* Receive new data */
|
|
while (UART_GetLineStatus(port_num, UART_LINESTATUS_DR) == SET) {
|
|
if (ring_buffer_free_space(driver->rx_ring_buffer) > 1) {
|
|
data = UART_Receive9bits(port_num);
|
|
recv_byte = (uint8_t) ((data >> 8) & 0x01);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
recv_byte = (uint8_t) (data & 0xFF);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
|
|
if ( ( driver->rx_size > 0 ) &&
|
|
( ring_buffer_used_space( driver->rx_ring_buffer ) >= driver->rx_size ) ) {
|
|
mico_rtos_set_semaphore( &driver->rx_complete );
|
|
driver->rx_size = 0;
|
|
}
|
|
} else {
|
|
/* Rx Buffer is full, discard received data */
|
|
if (driver->flow_control != FLOW_CONTROL_DISABLED_DRV) {
|
|
/* We need to mask the interrupt till the data
|
|
is read; otherwise we keep getting
|
|
data-ready interrupt infinitely */
|
|
UART_IntMask(port_num, UART_INT_RDA, MASK);
|
|
return;
|
|
} else {
|
|
UART_Receive9bits(port_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DEFINE_UART_CB(0, 8)
|
|
DEFINE_UART_CB(1, 8)
|
|
DEFINE_UART_CB(0, 9)
|
|
DEFINE_UART_CB(1, 9)
|
|
#if (NUM_UART_PORTS > 2)
|
|
DEFINE_UART_CB(2, 8)
|
|
DEFINE_UART_CB(2, 9)
|
|
#if (NUM_UART_PORTS > 3)
|
|
DEFINE_UART_CB(3, 8)
|
|
DEFINE_UART_CB(3, 9)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static void fill_cb_array()
|
|
{
|
|
uart_8bit_cb_p[0] = GET_UART_CB(0, 8);
|
|
uart_8bit_cb_p[1] = GET_UART_CB(1, 8);
|
|
uart_9bit_cb_p[0] = GET_UART_CB(0, 9);
|
|
uart_9bit_cb_p[1] = GET_UART_CB(1, 9);
|
|
#if (NUM_UART_PORTS > 2)
|
|
uart_8bit_cb_p[2] = GET_UART_CB(2, 8);
|
|
uart_9bit_cb_p[2] = GET_UART_CB(2, 9);
|
|
#if (NUM_UART_PORTS > 3)
|
|
uart_8bit_cb_p[3] = GET_UART_CB(3, 8);
|
|
uart_9bit_cb_p[3] = GET_UART_CB(3, 9);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
OSStatus platform_uart_init( platform_uart_driver_t* driver, const platform_uart_t* peripheral, const platform_uart_config_t* config, ring_buffer_t* optional_ring_buffer )
|
|
//int platform_uart_init(int port_id, const platform_uart_config_t* config, ring_buffer_t* optional_ring_buffer)
|
|
{
|
|
UART_CFG_Type uartcfg;
|
|
UART_FifoCfg_Type fifocfg;
|
|
uint32_t port_id = peripheral->port_id;
|
|
//platform_uart_driver_t* driver;
|
|
|
|
//sys_work_queue_init();
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return -1;
|
|
}
|
|
fill_cb_array();
|
|
|
|
//driver = &uart_drivers[port_id];
|
|
driver->id = port_id;
|
|
|
|
switch (driver->id) {
|
|
case UART0_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_0, CLK_UART_FAST);
|
|
CLK_ModuleClkEnable(CLK_UART0);
|
|
break;
|
|
case UART1_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_1, CLK_UART_SLOW);
|
|
CLK_ModuleClkEnable(CLK_UART1);
|
|
break;
|
|
case UART2_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_2, CLK_UART_SLOW);
|
|
CLK_ModuleClkEnable(CLK_UART2);
|
|
break;
|
|
}
|
|
if (optional_ring_buffer != NULL){
|
|
/* Note that the ring_buffer should've been initialised first */
|
|
driver->rx_ring_buffer = optional_ring_buffer;
|
|
|
|
} else {
|
|
uint8_t *pbuf;
|
|
pbuf = malloc(512);
|
|
ring_buffer_init(driver->rx_ring_buffer, pbuf, 512);
|
|
}
|
|
|
|
/* Initialize the UART port's mdev structure */
|
|
driver->rx_size = 0;
|
|
driver->tx_size = 0;
|
|
driver->last_transmit_result = kNoErr;
|
|
driver->last_receive_result = kNoErr;
|
|
|
|
uartcfg.baudRate = config->baud_rate;
|
|
uartcfg.stickyParity = DISABLE;
|
|
fifocfg.fifoEnable = ENABLE;
|
|
|
|
switch (config->data_width) {
|
|
case DATA_WIDTH_5BIT:
|
|
uartcfg.dataBits = UART_DATABITS_5;
|
|
break;
|
|
case DATA_WIDTH_6BIT:
|
|
uartcfg.dataBits = UART_DATABITS_6;
|
|
break;
|
|
case DATA_WIDTH_7BIT:
|
|
uartcfg.dataBits = UART_DATABITS_7;
|
|
break;
|
|
case DATA_WIDTH_8BIT:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
break;
|
|
case DATA_WIDTH_9BIT:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
uartcfg.parity = UART_PARITY_EVEN;
|
|
uartcfg.stickyParity = DISABLE;
|
|
fifocfg.fifoEnable = DISABLE;
|
|
break;
|
|
default:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
break;
|
|
}
|
|
switch ( config->parity )
|
|
{
|
|
case NO_PARITY:
|
|
uartcfg.parity = UART_PARITY_NONE;
|
|
break;
|
|
|
|
case EVEN_PARITY:
|
|
uartcfg.parity = UART_PARITY_EVEN;
|
|
break;
|
|
|
|
case ODD_PARITY:
|
|
uartcfg.parity = UART_PARITY_ODD;
|
|
break;
|
|
|
|
default:
|
|
uartcfg.parity = UART_PARITY_NONE;
|
|
break;
|
|
}
|
|
if (config->flow_control != FLOW_CONTROL_DISABLED) {
|
|
fifocfg.autoFlowControl = ENABLE;
|
|
} else {
|
|
fifocfg.autoFlowControl = DISABLE;
|
|
}
|
|
|
|
if ( config->stop_bits == STOP_BITS_1 )
|
|
UART_SetStopBits(port_id, UART_STOPBITS_1);
|
|
else
|
|
UART_SetStopBits(port_id, UART_STOPBITS_2);
|
|
|
|
fifocfg.rxFifoLevel = UART_RXFIFO_BYTE_1;
|
|
fifocfg.txFifoLevel = UART_TXFIFO_HALF_EMPTY;
|
|
fifocfg.peripheralBusType = UART_PERIPHERAL_BITS_8;
|
|
fifocfg.fifoDmaEnable = DISABLE;
|
|
|
|
UART_Disable(driver->id);
|
|
UART_Enable(driver->id);
|
|
UART_Init(driver->id, &uartcfg);
|
|
UART_FifoConfig(driver->id, &fifocfg);
|
|
|
|
install_int_callback(UART_INT_BASE + driver->id,
|
|
UART_INT_RDA,
|
|
(config->data_width == DATA_WIDTH_9BIT) ?
|
|
uart_9bit_cb_p[driver->id] :
|
|
uart_8bit_cb_p[driver->id]);
|
|
|
|
NVIC_EnableIRQ(UART_IRQn_BASE + driver->id);
|
|
NVIC_SetPriority(UART_IRQn_BASE + driver->id, 0xf);
|
|
UART_IntMask(driver->id, UART_INT_RDA, UNMASK);
|
|
|
|
/* Configure the pinmux for uart pins */
|
|
board_uart_pin_config(driver->id);
|
|
|
|
mico_rtos_init_semaphore( &driver->tx_complete, 1 );
|
|
mico_rtos_init_semaphore( &driver->rx_complete, 1 );
|
|
mico_rtos_init_semaphore( &driver->sem_wakeup, 1 );
|
|
mico_rtos_init_mutex ( &driver->tx_mutex );
|
|
return WM_SUCCESS;
|
|
}
|
|
|
|
//uint32_t mico_get_time_no_os(void)
|
|
//{
|
|
// return os_total_ticks_get();
|
|
//}
|
|
|
|
OSStatus platform_uart_receive_bytes( platform_uart_driver_t* driver, uint8_t* data_in, uint32_t expected_data_size, uint32_t timeout_ms )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
|
|
if (( data_in == NULL ) || ( expected_data_size == 0 )) {
|
|
err = kParamErr;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
while (expected_data_size != 0)
|
|
{
|
|
uint32_t transfer_size = MIN( driver->rx_ring_buffer->size/2, expected_data_size );
|
|
|
|
/* Check if ring buffer already contains the required amount of data. */
|
|
if ( transfer_size > ring_buffer_used_space( driver->rx_ring_buffer ) )
|
|
{
|
|
/* Set rx_size and wait in rx_complete semaphore until data reaches rx_size or timeout occurs */
|
|
driver->rx_size = transfer_size;
|
|
|
|
if ( mico_rtos_get_semaphore( &driver->rx_complete, timeout_ms) != kNoErr )
|
|
{
|
|
driver->rx_size = 0;
|
|
return kTimeoutErr;
|
|
}
|
|
|
|
/* Reset rx_size to prevent semaphore being set while nothing waits for the data */
|
|
driver->rx_size = 0;
|
|
}
|
|
|
|
expected_data_size -= transfer_size;
|
|
|
|
// Grab data from the buffer
|
|
do
|
|
{
|
|
uint8_t* available_data;
|
|
uint32_t bytes_available;
|
|
|
|
ring_buffer_get_data( driver->rx_ring_buffer, &available_data, &bytes_available );
|
|
bytes_available = MIN( bytes_available, transfer_size );
|
|
memcpy( data_in, available_data, bytes_available );
|
|
transfer_size -= bytes_available;
|
|
data_in = ( (uint8_t*) data_in + bytes_available );
|
|
ring_buffer_consume( driver->rx_ring_buffer, bytes_available );
|
|
} while ( transfer_size != 0 );
|
|
}
|
|
|
|
if ( expected_data_size != 0 )
|
|
{
|
|
return kGeneralErr;
|
|
}
|
|
else
|
|
{
|
|
return kNoErr;
|
|
}
|
|
|
|
|
|
exit:
|
|
//platform_mcu_powersave_enable();
|
|
return err;
|
|
}
|
|
|
|
OSStatus platform_uart_transmit_bytes( platform_uart_driver_t* driver, const uint8_t* data_out, uint32_t size )
|
|
//OSStatus platform_uart_transmit_bytes( int port_id, const uint8_t* data_out, uint32_t size )
|
|
{
|
|
int i;
|
|
|
|
if (driver->tx_mutex)
|
|
mico_rtos_lock_mutex( &driver->tx_mutex );
|
|
for(i=0; i<size; i++) {
|
|
while (UART_GetLineStatus(driver->id,
|
|
UART_LINESTATUS_TDRQ) != SET) {
|
|
os_thread_relinquish();
|
|
}
|
|
|
|
UART_SendData(driver->id, data_out[i]);
|
|
}
|
|
if (driver->tx_mutex)
|
|
mico_rtos_unlock_mutex( &driver->tx_mutex );
|
|
return kNoErr;
|
|
}
|
|
|
|
|
|
uint32_t platform_uart_get_length_in_buffer( platform_uart_driver_t* driver )
|
|
{
|
|
return ring_buffer_used_space( driver->rx_ring_buffer );
|
|
}
|
|
|
|
|
|
OSStatus platform_uart_deinit( platform_uart_driver_t* driver )
|
|
{
|
|
|
|
mico_rtos_deinit_semaphore( &driver->rx_complete );
|
|
mico_rtos_deinit_semaphore( &driver->tx_complete );
|
|
mico_rtos_deinit_semaphore( &driver->sem_wakeup );
|
|
mico_rtos_deinit_mutex( &driver->tx_mutex );
|
|
driver->rx_size = 0;
|
|
driver->tx_size = 0;
|
|
driver->last_transmit_result = kNoErr;
|
|
driver->last_receive_result = kNoErr;
|
|
|
|
while (UART_GetLineStatus(driver->id, UART_LINESTATUS_TEMT)!= SET)
|
|
;
|
|
|
|
UART_Disable(driver->id);
|
|
|
|
/* de-register interrupt callbacks */
|
|
NVIC_DisableIRQ(UART_IRQn_BASE + driver->id);
|
|
install_int_callback(UART_INT_BASE + driver->id, UART_INT_RDA, 0);
|
|
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
#define NUM_UART_PORTS 3
|
|
#define UART_IRQn_BASE UART0_IRQn
|
|
#define UART_INT_BASE INT_UART0
|
|
|
|
static platform_uart_driver_t uart_drivers[NUM_UART_PORTS];
|
|
static void (*uart_8bit_cb_p[NUM_UART_PORTS]) ();
|
|
static void (*uart_9bit_cb_p[NUM_UART_PORTS]) ();
|
|
|
|
#define SET_RX_BUF_SIZE(uart_data_p, size) \
|
|
uart_data_p->rx_ringbuf.buf_size = size
|
|
#define GET_RX_BUF_SIZE(uart_data_p) (uart_data_p->rx_ringbuf.buf_size)
|
|
|
|
#define SET_DMA_BLK_SIZE(uart_data_p, size) \
|
|
uart_data_p->rx_ringbuf.dma_block_size = size
|
|
#define GET_DMA_BLK_SIZE(uart_data_p) (uart_data_p->rx_ringbuf.dma_block_size)
|
|
|
|
#define DEFINE_UART_CB(id, mode) \
|
|
static void \
|
|
uart ## id ## _ ## mode ## bit_cb() {\
|
|
uart_ ## mode ## bit_cb(id); }
|
|
#define GET_UART_CB(id, mode) uart ## id ## _ ## mode ## bit_cb
|
|
|
|
/* UART callback functions */
|
|
static void uart_8bit_cb(int port_num)
|
|
{
|
|
uint8_t recv_byte;
|
|
platform_uart_driver_t* driver = &uart_drivers[port_num];
|
|
|
|
|
|
/* Receive new data */
|
|
while (UART_GetLineStatus(port_num, UART_LINESTATUS_DR) == SET) {
|
|
if (ring_buffer_is_full(driver->rx_ring_buffer) == 0) {
|
|
recv_byte = UART_ReceiveData(port_num);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
if ( ( driver->rx_size > 0 ) &&
|
|
( ring_buffer_used_space( driver->rx_ring_buffer) >= driver->rx_size ) ) {
|
|
mico_rtos_set_semaphore( &driver->rx_complete );
|
|
driver->rx_size = 0;
|
|
|
|
}
|
|
} else {
|
|
/* Rx Buffer is full, discard received data */
|
|
if (driver->flow_control != FLOW_CONTROL_DISABLED) {
|
|
/* We need to mask the interrupt till the data
|
|
is read; otherwise we keep getting
|
|
data-ready interrupt infinitely */
|
|
UART_IntMask(port_num, UART_INT_RDA, MASK);
|
|
return;
|
|
} else {
|
|
UART_ReceiveData(port_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void uart_9bit_cb(int port_num)
|
|
{
|
|
uint16_t data;
|
|
platform_uart_driver_t* driver = &uart_drivers[port_num];
|
|
uint8_t recv_byte;
|
|
/* Receive new data */
|
|
while (UART_GetLineStatus(port_num, UART_LINESTATUS_DR) == SET) {
|
|
if (ring_buffer_free_space(driver->rx_ring_buffer) > 1) {
|
|
data = UART_Receive9bits(port_num);
|
|
recv_byte = (uint8_t) ((data >> 8) & 0x01);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
recv_byte = (uint8_t) (data & 0xFF);
|
|
ring_buffer_write( driver->rx_ring_buffer, &recv_byte,1 );
|
|
|
|
if ( ( driver->rx_size > 0 ) &&
|
|
( ring_buffer_used_space( driver->rx_ring_buffer ) >= driver->rx_size ) ) {
|
|
mico_rtos_set_semaphore( &driver->rx_complete );
|
|
driver->rx_size = 0;
|
|
}
|
|
} else {
|
|
/* Rx Buffer is full, discard received data */
|
|
if (driver->flow_control != FLOW_CONTROL_DISABLED) {
|
|
/* We need to mask the interrupt till the data
|
|
is read; otherwise we keep getting
|
|
data-ready interrupt infinitely */
|
|
UART_IntMask(port_num, UART_INT_RDA, MASK);
|
|
return;
|
|
} else {
|
|
UART_Receive9bits(port_num);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DEFINE_UART_CB(0, 8)
|
|
DEFINE_UART_CB(1, 8)
|
|
DEFINE_UART_CB(0, 9)
|
|
DEFINE_UART_CB(1, 9)
|
|
#if (NUM_UART_PORTS > 2)
|
|
DEFINE_UART_CB(2, 8)
|
|
DEFINE_UART_CB(2, 9)
|
|
#if (NUM_UART_PORTS > 3)
|
|
DEFINE_UART_CB(3, 8)
|
|
DEFINE_UART_CB(3, 9)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static void fill_cb_array()
|
|
{
|
|
uart_8bit_cb_p[0] = GET_UART_CB(0, 8);
|
|
uart_8bit_cb_p[1] = GET_UART_CB(1, 8);
|
|
uart_9bit_cb_p[0] = GET_UART_CB(0, 9);
|
|
uart_9bit_cb_p[1] = GET_UART_CB(1, 9);
|
|
#if (NUM_UART_PORTS > 2)
|
|
uart_8bit_cb_p[2] = GET_UART_CB(2, 8);
|
|
uart_9bit_cb_p[2] = GET_UART_CB(2, 9);
|
|
#if (NUM_UART_PORTS > 3)
|
|
uart_8bit_cb_p[3] = GET_UART_CB(3, 8);
|
|
uart_9bit_cb_p[3] = GET_UART_CB(3, 9);
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
|
|
int platform_uart_init(int port_id, const platform_uart_config_t* config, ring_buffer_t* optional_ring_buffer)
|
|
{
|
|
UART_CFG_Type uartcfg;
|
|
UART_FifoCfg_Type fifocfg;
|
|
platform_uart_driver_t* driver;
|
|
int ret;
|
|
|
|
//sys_work_queue_init();
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return -1;
|
|
}
|
|
fill_cb_array();
|
|
|
|
driver = &uart_drivers[port_id];
|
|
driver->id = port_id;
|
|
|
|
switch (driver->id) {
|
|
case UART0_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_0, CLK_UART_FAST);
|
|
CLK_ModuleClkEnable(CLK_UART0);
|
|
break;
|
|
case UART1_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_1, CLK_UART_SLOW);
|
|
CLK_ModuleClkEnable(CLK_UART1);
|
|
break;
|
|
case UART2_ID:
|
|
CLK_SetUARTClkSrc(CLK_UART_ID_2, CLK_UART_SLOW);
|
|
CLK_ModuleClkEnable(CLK_UART2);
|
|
break;
|
|
}
|
|
/* Initialize the UART port's mdev structure */
|
|
driver->rx_size = 0;
|
|
driver->tx_size = 0;
|
|
driver->last_transmit_result = kNoErr;
|
|
driver->last_receive_result = kNoErr;
|
|
|
|
uartcfg.baudRate = config->baud_rate;
|
|
uartcfg.stickyParity = DISABLE;
|
|
fifocfg.fifoEnable = ENABLE;
|
|
|
|
switch (config->data_width) {
|
|
case DATA_WIDTH_5BIT:
|
|
uartcfg.dataBits = UART_DATABITS_5;
|
|
break;
|
|
case DATA_WIDTH_6BIT:
|
|
uartcfg.dataBits = UART_DATABITS_6;
|
|
break;
|
|
case DATA_WIDTH_7BIT:
|
|
uartcfg.dataBits = UART_DATABITS_7;
|
|
break;
|
|
case DATA_WIDTH_8BIT:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
break;
|
|
case DATA_WIDTH_9BIT:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
uartcfg.parity = UART_PARITY_EVEN;
|
|
uartcfg.stickyParity = DISABLE;
|
|
fifocfg.fifoEnable = DISABLE;
|
|
break;
|
|
default:
|
|
uartcfg.dataBits = UART_DATABITS_8;
|
|
break;
|
|
}
|
|
switch ( config->parity )
|
|
{
|
|
case NO_PARITY:
|
|
uartcfg.parity = UART_PARITY_NONE;
|
|
break;
|
|
|
|
case EVEN_PARITY:
|
|
uartcfg.parity = UART_PARITY_EVEN;
|
|
break;
|
|
|
|
case ODD_PARITY:
|
|
uartcfg.parity = UART_PARITY_ODD;
|
|
break;
|
|
|
|
default:
|
|
uartcfg.parity = UART_PARITY_NONE;
|
|
break;
|
|
}
|
|
if (config->flow_control != FLOW_CONTROL_DISABLED) {
|
|
fifocfg.autoFlowControl = ENABLE;
|
|
} else {
|
|
fifocfg.autoFlowControl = DISABLE;
|
|
}
|
|
|
|
if ( config->stop_bits == STOP_BITS_1 )
|
|
UART_SetStopBits(port_id, UART_STOPBITS_1);
|
|
else
|
|
UART_SetStopBits(port_id, UART_STOPBITS_2);
|
|
|
|
fifocfg.rxFifoLevel = UART_RXFIFO_BYTE_1;
|
|
fifocfg.txFifoLevel = UART_TXFIFO_HALF_EMPTY;
|
|
fifocfg.peripheralBusType = UART_PERIPHERAL_BITS_8;
|
|
fifocfg.fifoDmaEnable = DISABLE;
|
|
|
|
UART_Disable(driver->id);
|
|
UART_Enable(driver->id);
|
|
UART_Init(driver->id, &uartcfg);
|
|
UART_FifoConfig(driver->id, &fifocfg);
|
|
|
|
/* initialize dma driver */
|
|
ret = dma_drv_init();
|
|
if (ret != WM_SUCCESS) {
|
|
UART_LOG("Failed to initialize dma driver\r\n");
|
|
return NULL;
|
|
}
|
|
ret = sys_work_queue_init();
|
|
if (ret != WM_SUCCESS) {
|
|
UART_LOG("Failed to initialize system workqueue\r\n");
|
|
return NULL;
|
|
}
|
|
if (optional_ring_buffer != NULL){
|
|
/* Note that the ring_buffer should've been initialised first */
|
|
driver->rx_ring_buffer = optional_ring_buffer;
|
|
|
|
} else {
|
|
uint8_t *pbuf;
|
|
pbuf = os_mem_alloc(512);
|
|
ring_buffer_init(driver->rx_ring_buffer, pbuf, 512);
|
|
}
|
|
driver->rx_size = 0;
|
|
|
|
/* Enable UART to send dma request to DMAC */
|
|
UART_DmaCmd(port_id, ENABLE);
|
|
uart_dma_read_start(port_id,
|
|
(uint8_t *)driver->rx_ring_buffer->buffer,
|
|
driver->rx_ring_buffer->size);
|
|
UART_IntMask(driver->id, UART_INT_RDA, UNMASK);
|
|
|
|
/* Configure the pinmux for uart pins */
|
|
board_uart_pin_config(driver->id);
|
|
|
|
|
|
return WM_SUCCESS;
|
|
}
|
|
|
|
uint32_t mico_get_time_no_os(void)
|
|
{
|
|
return os_total_ticks_get();
|
|
}
|
|
|
|
OSStatus platform_uart_receive_bytes( int port_id, uint8_t* data_in, uint32_t expected_data_size, uint32_t timeout_ms )
|
|
{
|
|
OSStatus err = kNoErr;
|
|
platform_uart_driver_t* driver;
|
|
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return -1;
|
|
}
|
|
|
|
|
|
driver = &uart_drivers[port_id];
|
|
|
|
|
|
if (( data_in == NULL ) || ( expected_data_size == 0 )) {
|
|
err = kParamErr;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
while (expected_data_size != 0)
|
|
{
|
|
uint32_t transfer_size = MIN( driver->rx_ring_buffer->size/2, expected_data_size );
|
|
|
|
/* Check if ring buffer already contains the required amount of data. */
|
|
if ( transfer_size > ring_buffer_used_space( driver->rx_ring_buffer ) )
|
|
{
|
|
/* Set rx_size and wait in rx_complete semaphore until data reaches rx_size or timeout occurs */
|
|
driver->rx_size = transfer_size;
|
|
|
|
if ( mico_rtos_get_semaphore( &driver->rx_complete, timeout_ms) != kNoErr )
|
|
{
|
|
driver->rx_size = 0;
|
|
return kTimeoutErr;
|
|
}
|
|
|
|
/* Reset rx_size to prevent semaphore being set while nothing waits for the data */
|
|
driver->rx_size = 0;
|
|
}
|
|
|
|
expected_data_size -= transfer_size;
|
|
|
|
// Grab data from the buffer
|
|
do
|
|
{
|
|
uint8_t* available_data;
|
|
uint32_t bytes_available;
|
|
|
|
ring_buffer_get_data( driver->rx_ring_buffer, &available_data, &bytes_available );
|
|
bytes_available = MIN( bytes_available, transfer_size );
|
|
memcpy( data_in, available_data, bytes_available );
|
|
transfer_size -= bytes_available;
|
|
data_in = ( (uint8_t*) data_in + bytes_available );
|
|
ring_buffer_consume( driver->rx_ring_buffer, bytes_available );
|
|
} while ( transfer_size != 0 );
|
|
}
|
|
|
|
if ( expected_data_size != 0 )
|
|
{
|
|
return kGeneralErr;
|
|
}
|
|
else
|
|
{
|
|
return kNoErr;
|
|
}
|
|
|
|
|
|
exit:
|
|
//platform_mcu_powersave_enable();
|
|
return err;
|
|
}
|
|
|
|
|
|
OSStatus platform_uart_transmit_bytes( int port_id, const uint8_t* data_out, uint32_t size )
|
|
{
|
|
int i;
|
|
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return kGeneralErr;
|
|
}
|
|
|
|
for(i=0; i<size; i++) {
|
|
while (UART_GetLineStatus(port_id,
|
|
UART_LINESTATUS_TDRQ) != SET) {
|
|
os_thread_relinquish();
|
|
}
|
|
|
|
UART_SendData(port_id, data_out[i]);
|
|
}
|
|
return kNoErr;
|
|
}
|
|
|
|
|
|
|
|
OSStatus platform_uart_get_length_in_buffer( int port_id )
|
|
{
|
|
platform_uart_driver_t* driver;
|
|
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return 0;
|
|
}
|
|
|
|
|
|
driver = &uart_drivers[port_id];
|
|
|
|
return ring_buffer_used_space( driver->rx_ring_buffer );
|
|
}
|
|
|
|
|
|
OSStatus platform_uart_deinit( int port_id )
|
|
{
|
|
platform_uart_driver_t* driver;
|
|
|
|
if (port_id < 0 || port_id >= NUM_UART_PORTS) {
|
|
UART_LOG("Port %d not enabled\r\n", port_id);
|
|
return 0;
|
|
}
|
|
|
|
|
|
driver = &uart_drivers[port_id];
|
|
|
|
mico_rtos_deinit_semaphore( &driver->rx_complete );
|
|
mico_rtos_deinit_semaphore( &driver->tx_complete );
|
|
mico_rtos_deinit_semaphore( &driver->sem_wakeup );
|
|
mico_rtos_deinit_mutex( &driver->tx_mutex );
|
|
driver->rx_size = 0;
|
|
driver->tx_size = 0;
|
|
driver->last_transmit_result = kNoErr;
|
|
driver->last_receive_result = kNoErr;
|
|
|
|
while (UART_GetLineStatus(port_id, UART_LINESTATUS_TEMT)!= SET)
|
|
;
|
|
|
|
UART_Disable(port_id);
|
|
|
|
/* de-register interrupt callbacks */
|
|
NVIC_DisableIRQ(UART_IRQn_BASE + port_id);
|
|
install_int_callback(UART_INT_BASE + port_id, UART_INT_RDA, 0);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|