EFM32 Pearl Gecko Serial: Remove dynamic peripheral allocation.

pull/1501/head
Aksel Skauge Mellbye 2016-01-04 17:33:27 +01:00 committed by Steven Cooreman
parent c0ec7ad8d9
commit f05fd7fcea
4 changed files with 88 additions and 267 deletions

View File

@ -348,10 +348,6 @@ const PinMap PinMap_SPI_CS[] = {
/************UART**************/ /************UART**************/
const PinMap PinMap_UART_TX[] = { const PinMap PinMap_UART_TX[] = {
/* USART0, USART1, LEUART0. Pinmaps are identical
so peripheral selection is dynamic */
{PA0, USART_0, 0}, {PA0, USART_0, 0},
{PA1, USART_0, 1}, {PA1, USART_0, 1},
{PA2, USART_0, 2}, {PA2, USART_0, 2},
@ -363,36 +359,34 @@ const PinMap PinMap_UART_TX[] = {
{PB13, USART_0, 8}, {PB13, USART_0, 8},
{PB14, USART_0, 9}, {PB14, USART_0, 9},
{PB15, USART_0, 10}, {PB15, USART_0, 10},
{PC6, USART_0, 11},
{PC7, USART_0, 12},
{PC8, USART_0, 13},
{PC9, USART_0, 14},
{PC10, USART_0, 15},
{PC11, USART_0, 16},
{PD10, USART_0, 18}, {PD10, LEUART_0, 18},
{PD11, USART_0, 19}, {PD11, LEUART_0, 19},
{PD12, USART_0, 20}, {PD12, LEUART_0, 20},
{PD13, USART_0, 21}, {PD13, LEUART_0, 21},
{PD14, USART_0, 22}, {PD14, LEUART_0, 22},
{PD15, USART_0, 23}, {PD15, LEUART_0, 23},
{PF0, USART_0, 24},
{PF1, USART_0, 25}, {PC6, USART_1, 11},
{PF2, USART_0, 26}, {PC7, USART_1, 12},
{PF3, USART_0, 27}, {PC8, USART_1, 13},
{PF4, USART_0, 28}, {PC9, USART_1, 14},
{PF5, USART_0, 29}, {PC10, USART_1, 15},
{PF6, USART_0, 30}, {PC11, USART_1, 16},
{PF7, USART_0, 31}, {PF0, USART_1, 24},
{PF1, USART_1, 25},
{PF2, USART_1, 26},
{PF3, USART_1, 27},
{PF4, USART_1, 28},
{PF5, USART_1, 29},
{PF6, USART_1, 30},
{PF7, USART_1, 31},
{NC , NC , NC} {NC , NC , NC}
}; };
const PinMap PinMap_UART_RX[] = { const PinMap PinMap_UART_RX[] = {
{PA0, USART_0, 31},
/* USART0, USART1, LEUART0. Pinmaps are identical
so peripheral selection is dynamic */
{PA1, USART_0, 0}, {PA1, USART_0, 0},
{PA2, USART_0, 1}, {PA2, USART_0, 1},
{PA3, USART_0, 2}, {PA3, USART_0, 2},
@ -403,28 +397,28 @@ const PinMap PinMap_UART_RX[] = {
{PB13, USART_0, 7}, {PB13, USART_0, 7},
{PB14, USART_0, 8}, {PB14, USART_0, 8},
{PB15, USART_0, 9}, {PB15, USART_0, 9},
{PC6, USART_0, 10},
{PC7, USART_0, 11},
{PC8, USART_0, 12},
{PC9, USART_0, 13},
{PC10, USART_0, 14},
{PC11, USART_0, 15},
{PD10, USART_0, 17}, {PD10, LEUART_0, 17},
{PD11, USART_0, 18}, {PD11, LEUART_0, 18},
{PD12, USART_0, 19}, {PD12, LEUART_0, 19},
{PD13, USART_0, 20}, {PD13, LEUART_0, 20},
{PD14, USART_0, 21}, {PD14, LEUART_0, 21},
{PD15, USART_0, 22}, {PD15, LEUART_0, 22},
{PF0, USART_0, 23},
{PF1, USART_0, 24}, {PC6, USART_1, 10},
{PF2, USART_0, 25}, {PC7, USART_1, 11},
{PF3, USART_0, 26}, {PC8, USART_1, 12},
{PF4, USART_0, 27}, {PC9, USART_1, 13},
{PF5, USART_0, 28}, {PC10, USART_1, 14},
{PF6, USART_0, 29}, {PC11, USART_1, 15},
{PF7, USART_0, 30}, {PF0, USART_1, 23},
{PA0, USART_0, 31}, {PF1, USART_1, 24},
{PF2, USART_1, 25},
{PF3, USART_1, 26},
{PF4, USART_1, 27},
{PF5, USART_1, 28},
{PF6, USART_1, 29},
{PF7, USART_1, 30},
{NC , NC , NC} {NC , NC , NC}
}; };

View File

@ -47,6 +47,11 @@ void mbed_sdk_init()
{ {
CHIP_Init(); CHIP_Init();
#if defined(_SILICON_LABS_32B_PLATFORM_2)
EMU_DCDCInit_TypeDef dcdcInit = EMU_DCDCINIT_DEFAULT;
EMU_DCDCInit(&dcdcInit);
#endif
/* Set up the clock sources for this chip */ /* Set up the clock sources for this chip */
#if( CORE_CLOCK_SOURCE == HFXO) #if( CORE_CLOCK_SOURCE == HFXO)
CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);

View File

@ -68,19 +68,6 @@
#error Undefined number of low energy UARTs (LEUART). #error Undefined number of low energy UARTs (LEUART).
#endif #endif
#ifdef _SILICON_LABS_32B_PLATFORM_2
#define SERIAL_LEUART_MAX_BAUDRATE 9600
#ifndef LEUART_USING_LFXO
# define SERIAL_LEUART_MIN_BAUDRATE (LEUART_REF_FREQ>>10)
#endif
static void serial_switch_to_usart(serial_t *obj, int baudrate);
static uint8_t leuart0_reserved = 0;
static uint8_t usart_reserved[USART_COUNT] = { 0, 0 };
static USART_TypeDef * const usart_map[USART_COUNT] = { USART0, USART1 };
#endif
/* Store IRQ id for each UART */ /* Store IRQ id for each UART */
static uint32_t serial_irq_ids[SERIAL_NUM_UARTS] = { 0 }; static uint32_t serial_irq_ids[SERIAL_NUM_UARTS] = { 0 };
/* Interrupt handler from mbed common */ /* Interrupt handler from mbed common */
@ -190,7 +177,7 @@ static void uart_init(serial_t *obj, uint32_t baudrate, SerialParity parity, int
#ifdef LEUART_USING_LFXO #ifdef LEUART_USING_LFXO
init.refFreq = LEUART_LF_REF_FREQ; init.refFreq = LEUART_LF_REF_FREQ;
#else #else
init.refFreq = 0; init.refFreq = LEUART_REF_FREQ;
#endif #endif
LEUART_Init(obj->serial.periph.leuart, &init); LEUART_Init(obj->serial.periph.leuart, &init);
@ -223,7 +210,7 @@ static void uart_init(serial_t *obj, uint32_t baudrate, SerialParity parity, int
init.baudrate = baudrate; init.baudrate = baudrate;
init.oversampling = usartOVS16; init.oversampling = usartOVS16;
init.databits = usartDatabits8; init.databits = usartDatabits8;
init.refFreq = 0; /* Emlib will read HFPER clock to figure out the divider */ init.refFreq = REFERENCE_FREQUENCY;
USART_InitAsync(obj->serial.periph.uart, &init); USART_InitAsync(obj->serial.periph.uart, &init);
} }
@ -398,55 +385,8 @@ inline CMU_Clock_TypeDef serial_get_clock(serial_t *obj)
} }
} }
#ifdef _SILICON_LABS_32B_PLATFORM_2 void serial_preinit(serial_t *obj, PinName tx, PinName rx)
void *serial_uart_allocate(unsigned int uart_type)
{ {
int i;
if( uart_type & UART_TYPE_LEUART ) {
if( !leuart0_reserved ) {
leuart0_reserved = 1;
return LEUART0;
}
}
if( uart_type & UART_TYPE_USART ) {
for( i=0 ; i<USART_COUNT ; i++ ) {
if( !usart_reserved[i] ) {
usart_reserved[i] = 1;
return usart_map[i];
}
}
}
return NULL;
}
void serial_uart_free(void *uart)
{
int i;
for( i=0 ; i<USART_COUNT ; i++ ) {
if( usart_map[i] == uart ) {
usart_reserved[i] = 0;
return;
}
}
if( uart == LEUART0 ) {
leuart0_reserved = 0;
return;
}
MBED_ASSERT(0);
}
#endif /* _SILICON_LABS_32B_PLATFORM_2 */
void serial_preinit(serial_t *obj, PinName tx, PinName rx, int allow_leuart)
{
#ifndef _SILICON_LABS_32B_PLATFORM_2
/* Older platforms with fixed pin mappings per UART */
/* Get UART object connected to the given pins */ /* Get UART object connected to the given pins */
UARTName uart_tx = (UARTName) pinmap_peripheral(tx, PinMap_UART_TX); UARTName uart_tx = (UARTName) pinmap_peripheral(tx, PinMap_UART_TX);
UARTName uart_rx = (UARTName) pinmap_peripheral(rx, PinMap_UART_RX); UARTName uart_rx = (UARTName) pinmap_peripheral(rx, PinMap_UART_RX);
@ -459,26 +399,18 @@ void serial_preinit(serial_t *obj, PinName tx, PinName rx, int allow_leuart)
/* Get location */ /* Get location */
uint32_t uart_tx_loc = pin_location(tx, PinMap_UART_TX); uint32_t uart_tx_loc = pin_location(tx, PinMap_UART_TX);
uint32_t uart_rx_loc = pin_location(rx, PinMap_UART_RX); uint32_t uart_rx_loc = pin_location(rx, PinMap_UART_RX);
#if defined(_SILICON_LABS_32B_PLATFORM_1)
/* Check that pins are used by same location for the given UART */ /* Check that pins are used by same location for the given UART */
obj->serial.location = pinmap_merge(uart_tx_loc, uart_rx_loc); obj->serial.location = pinmap_merge(uart_tx_loc, uart_rx_loc);
MBED_ASSERT(obj->serial.location != (uint32_t)NC); MBED_ASSERT(obj->serial.location != (uint32_t)NC);
#else #else
/* New platforms with free pin mapping */
uint32_t type = allow_leuart ? (UART_TYPE_USART|UART_TYPE_LEUART) : UART_TYPE_USART;
obj->serial.periph.uart = serial_uart_allocate(type);
MBED_ASSERT(obj->serial.periph.uart);
uint32_t uart_tx_loc = pin_location(tx, PinMap_UART_TX);
uint32_t uart_rx_loc = pin_location(rx, PinMap_UART_RX);
MBED_ASSERT((uart_tx_loc != NC) && (uart_rx_loc != NC));
obj->serial.location_tx = uart_tx_loc; obj->serial.location_tx = uart_tx_loc;
obj->serial.location_rx = uart_rx_loc; obj->serial.location_rx = uart_rx_loc;
#endif #endif
/* Store pins in object for easy disabling in serial_free() */ /* Store pins in object for easy disabling in serial_free() */
//TODO: replace all usages with AF_USARTx_TX_PORT(location) macro to save 8 bytes from struct
obj->serial.rx_pin = rx; obj->serial.rx_pin = rx;
obj->serial.tx_pin = tx; obj->serial.tx_pin = tx;
@ -549,28 +481,20 @@ static void serial_enable_pins(serial_t *obj, uint8_t enable)
void serial_init(serial_t *obj, PinName tx, PinName rx) void serial_init(serial_t *obj, PinName tx, PinName rx)
{ {
uint32_t baudrate; uint32_t baudrate;
uint32_t allow_leuart = true;
uint32_t uart_for_stdio = false; uint32_t uart_for_stdio = false;
#ifdef _SILICON_LABS_32B_PLATFORM_2 serial_preinit(obj, tx, rx);
if((tx == STDIO_UART_TX) && (rx == STDIO_UART_RX)) {
allow_leuart = false;
}
#endif
serial_preinit(obj, tx, rx, allow_leuart);
if(LEUART_REF_VALID(obj->serial.periph.leuart)) { if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
// Set up LEUART clock tree // Set up LEUART clock tree
#ifdef LEUART_USING_LFXO #ifdef LEUART_USING_LFXO
//set to use LFXO //set to use LFXO
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
CMU_ClockEnable(cmuClock_CORELE, true); CMU_ClockEnable(cmuClock_CORELE, true);
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO);
#else #else
//set to use high-speed clock //set to use high-speed clock
#ifdef _SILICON_LABS_32B_PLATFORM_2 #ifdef _SILICON_LABS_32B_PLATFORM_2
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_HFCLKLE); CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_HFCLKLE);
CMU_ClockDivSet(serial_get_clock(obj), 8);
#else #else
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2); CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
#endif #endif
@ -581,10 +505,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
/* Limitations of board controller: CDC port only supports 115kbaud */ /* Limitations of board controller: CDC port only supports 115kbaud */
if((tx == STDIO_UART_TX) && (rx == STDIO_UART_RX) if((tx == STDIO_UART_TX) && (rx == STDIO_UART_RX)
#ifndef _SILICON_LABS_32B_PLATFORM_2
&& (obj->serial.periph.uart == (USART_TypeDef*)STDIO_UART ) && (obj->serial.periph.uart == (USART_TypeDef*)STDIO_UART )
#endif ) {
) {
baudrate = 115200; baudrate = 115200;
uart_for_stdio = true; uart_for_stdio = true;
} else { } else {
@ -640,10 +562,6 @@ void serial_free(serial_t *obj)
} else { } else {
USART_Enable(obj->serial.periph.uart, usartDisable); USART_Enable(obj->serial.periph.uart, usartDisable);
} }
#ifdef _SILICON_LABS_32B_PLATFORM_2
serial_uart_free(obj->serial.periph.uart);
#endif
} }
static void serial_enable(serial_t *obj, uint8_t enable) static void serial_enable(serial_t *obj, uint8_t enable)
@ -670,37 +588,52 @@ static void serial_enable(serial_t *obj, uint8_t enable)
void serial_baud(serial_t *obj, int baudrate) void serial_baud(serial_t *obj, int baudrate)
{ {
if(LEUART_REF_VALID(obj->serial.periph.leuart)) { if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
#ifndef _SILICON_LABS_32B_PLATFORM_2
serial_leuart_baud(obj, baudrate); serial_leuart_baud(obj, baudrate);
#else
/* For Pearl, we must check if we need to upgrade to using a standard USART */
if( (baudrate > SERIAL_LEUART_MAX_BAUDRATE)
#ifndef LEUART_USING_LFXO
|| (baudrate < SERIAL_LEUART_MIN_BAUDRATE)
#endif
) {
serial_switch_to_usart(obj, baudrate);
} else {
serial_leuart_baud(obj, baudrate);
}
#endif
} else { } else {
USART_BaudrateAsyncSet(obj->serial.periph.uart, 0, (uint32_t)baudrate, usartOVS16); USART_BaudrateAsyncSet(obj->serial.periph.uart, 0, (uint32_t)baudrate, usartOVS16);
} }
} }
/**
* Set LEUART baud rate
* Calculate whether LF or HF clock should be used.
*/
static void serial_leuart_baud(serial_t *obj, int baudrate) static void serial_leuart_baud(serial_t *obj, int baudrate)
{ {
#ifdef LEUART_USING_LFXO #ifdef LEUART_USING_LFXO
/* check if baudrate is within allowed range */ /* check if baudrate is within allowed range */
#if defined(_SILICON_LABS_32B_PLATFORM_2)
// P2 has 9 bits + 5 fractional bits in LEUART CLKDIV register
MBED_ASSERT(baudrate >= (LEUART_LF_REF_FREQ >> 9));
#else
// P1 has 7 bits + 5 fractional bits in LEUART CLKDIV register
MBED_ASSERT(baudrate >= (LEUART_LF_REF_FREQ >> 7)); MBED_ASSERT(baudrate >= (LEUART_LF_REF_FREQ >> 7));
#endif
if(baudrate > (LEUART_LF_REF_FREQ >> 1)){ if(baudrate > (LEUART_LF_REF_FREQ >> 1)){
/* check if baudrate is within allowed range */ // Baudrate is bigger than LFCLK/2 - we need to use the HF clock
uint8_t divisor = 1;
#if defined(_SILICON_LABS_32B_PLATFORM_2)
/* Check if baudrate is within allowed range: (HFCLK/4096, HFCLK/2] */
MBED_ASSERT((baudrate <= (LEUART_HF_REF_FREQ >> 1)) && (baudrate > (LEUART_HF_REF_FREQ >> 12)));
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_HFCLKLE);
if(baudrate > (LEUART_HF_REF_FREQ >> 9)){
divisor = 1;
}else if(baudrate > (LEUART_HF_REF_FREQ >> 10)){
divisor = 2;
}else if(baudrate > (LEUART_HF_REF_FREQ >> 11)){
divisor = 4;
}else{
divisor = 8;
}
#else // P1
/* Check if baudrate is within allowed range */
MBED_ASSERT((baudrate <= (LEUART_HF_REF_FREQ >> 1)) && (baudrate > (LEUART_HF_REF_FREQ >> 10))); MBED_ASSERT((baudrate <= (LEUART_HF_REF_FREQ >> 1)) && (baudrate > (LEUART_HF_REF_FREQ >> 10)));
CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2); CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
uint8_t divisor = 1;
if(baudrate > (LEUART_HF_REF_FREQ >> 7)){ if(baudrate > (LEUART_HF_REF_FREQ >> 7)){
divisor = 1; divisor = 1;
@ -711,6 +644,7 @@ static void serial_leuart_baud(serial_t *obj, int baudrate)
}else{ }else{
divisor = 8; divisor = 8;
} }
#endif
CMU_ClockDivSet(serial_get_clock(obj), divisor); CMU_ClockDivSet(serial_get_clock(obj), divisor);
LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_HF_REF_FREQ/divisor, (uint32_t)baudrate); LEUART_BaudrateSet(obj->serial.periph.leuart, LEUART_HF_REF_FREQ/divisor, (uint32_t)baudrate);
}else{ }else{
@ -736,120 +670,11 @@ static void serial_leuart_baud(serial_t *obj, int baudrate)
#endif #endif
} }
#ifdef _SILICON_LABS_32B_PLATFORM_2
/**
* Deinit LEUART, and allocate and init an USART on the same pins with
* the same configuration.
*/
static void serial_switch_to_usart(serial_t *obj, int baudrate)
{
LEUART_TypeDef *leuart = obj->serial.periph.leuart;
while(leuart->SYNCBUSY & LEUART_SYNCBUSY_CMD);
/* Grab all relevant status */
uint32_t ien_rxd = leuart->IEN & LEUART_IEN_RXDATAV;
uint32_t ien_txc = leuart->IEN & LEUART_IEN_TXC;
uint32_t ien_ferr = leuart->IEN & LEUART_IEN_FERR;
uint32_t ien_perr = leuart->IEN & LEUART_IEN_PERR;
uint32_t ien_rxof = leuart->IEN & LEUART_IEN_RXOF;
uint32_t parity = leuart->CTRL & _LEUART_CTRL_PARITY_MASK;
uint32_t stop_bits = leuart->CTRL & _LEUART_CTRL_STOPBITS_MASK;
uint32_t irq_id = serial_irq_ids[serial_get_index(obj)];
/* Disable LEUART */
serial_enable(obj, false);
/* Remove IRQ callback */
serial_irq_ids[serial_get_index(obj)] = 0;
/* Free DMA channels */
if( obj->serial.dmaOptionsTX.dmaChannel != -1 )
dma_channel_free(obj->serial.dmaOptionsTX.dmaChannel);
if( obj->serial.dmaOptionsRX.dmaChannel != -1 )
dma_channel_free(obj->serial.dmaOptionsRX.dmaChannel);
obj->serial.dmaOptionsTX.dmaChannel = -1;
obj->serial.dmaOptionsTX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
obj->serial.dmaOptionsRX.dmaChannel = -1;
obj->serial.dmaOptionsRX.dmaUsageState = DMA_USAGE_OPPORTUNISTIC;
/* TODO: disable clocks? */
/* Disable sleep */
uint32_t sleep_count = obj->serial.sleep_blocked;
while( obj->serial.sleep_blocked > 0 )
serial_unblock_sleep(obj);
SerialParity par = ParityNone;
switch( parity ) {
case LEUART_CTRL_PARITY_NONE: par = ParityNone; break;
case LEUART_CTRL_PARITY_EVEN: par = ParityEven; break;
case LEUART_CTRL_PARITY_ODD: par = ParityOdd; break;
default:
MBED_ASSERT(0);
break;
}
int stopb = 1;
switch( stop_bits ) {
case LEUART_CTRL_STOPBITS_ONE: stopb = 1; break;
case LEUART_CTRL_STOPBITS_TWO: stopb = 2; break;
default:
MBED_ASSERT(0);
break;
}
/* Replace LEUART with USART */
serial_preinit(obj, obj->serial.tx_pin, obj->serial.rx_pin, false);
CMU_ClockEnable(serial_get_clock(obj), true);
uart_init(obj, baudrate, par, stopb);
USART_TypeDef *usart = obj->serial.periph.uart;
/* Disable/enable routing */
usart->ROUTELOC0 = (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT) |
(obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
leuart->ROUTEPEN = 0;
usart->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
usart->IFC = USART_IFC_TXC;
serial_uart_free(leuart);
serial_enable(obj, true);
/* Restore sleep */
while( obj->serial.sleep_blocked < sleep_count )
serial_block_sleep(obj);
/* Restore interrupts */
serial_irq_ids[serial_get_index(obj)] = irq_id;
if( ien_rxd ) serial_irq_set(obj, RxIrq, 1);
if( ien_txc ) serial_irq_set(obj, TxIrq, 1);
if( ien_ferr ) usart->IEN |= USART_IEN_FERR;
if( ien_perr ) usart->IEN |= USART_IEN_PERR;
if( ien_rxof ) usart->IEN |= USART_IEN_RXOF;
}
#endif /* _SILICON_LABS_32B_PLATFORM_2 */
/** /**
* Set UART format by re-initializing the peripheral. * Set UART format by re-initializing the peripheral.
*/ */
void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits) void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_bits)
{ {
#ifdef _SILICON_LABS_32B_PLATFORM_2
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
if (data_bits != 8) {
/* Only have 8 bit support on LEUART so need to move to standard USART */
serial_switch_to_usart(obj, LEUART_BaudrateGet(obj->serial.periph.leuart));
}
}
#endif
if(LEUART_REF_VALID(obj->serial.periph.leuart)) { if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
/* Save the serial state */ /* Save the serial state */
uint8_t was_enabled = LEUART_StatusGet(obj->serial.periph.leuart) & (LEUART_STATUS_TXENS | LEUART_STATUS_RXENS); uint8_t was_enabled = LEUART_StatusGet(obj->serial.periph.leuart) & (LEUART_STATUS_TXENS | LEUART_STATUS_RXENS);

View File

@ -42,9 +42,6 @@
extern "C" { extern "C" {
#endif #endif
void *serial_uart_allocate(unsigned int uart_type);
void serial_uart_free(void *uart);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif