mirror of https://github.com/ARMmbed/mbed-os.git
SiLabs Pearl: Free(er), dynamic allocation of UARTs
UARTs are no longer fixed to certain pins on Pearl, so we need to allocate them as needed, and allow for free pin selection. TX and RX pin locations in the main serial struct have been separated, and pin routing modified accordingly. serial_api_HAL.h interface keeps track of which UARTS are currently in use, and provides alloc/free functions. Serial and SPI components modified to use the new API. TODO: Magic to support LEUART. This code will also need to be able to dynamically switch from LEUART to standard USART if the user later sets params (baud rate or format) that can not be supported on LEUART.pull/1501/head
parent
87aee51f52
commit
763ce3dbbc
|
|
@ -494,9 +494,9 @@ const PinMap PinMap_SPI_CS[] = {
|
|||
/************UART**************/
|
||||
const PinMap PinMap_UART_TX[] = {
|
||||
|
||||
// Pearl ok
|
||||
/* USART0, USART1, LEUART0. Pinmaps are identical
|
||||
so peripheral selection is dynamic */
|
||||
|
||||
/* USART0 */
|
||||
{PA0, USART_0, 0},
|
||||
{PA1, USART_0, 1},
|
||||
{PA2, USART_0, 2},
|
||||
|
|
@ -530,18 +530,14 @@ const PinMap PinMap_UART_TX[] = {
|
|||
{PF6, USART_0, 30},
|
||||
{PF7, USART_0, 31},
|
||||
|
||||
/* USART1, LEUART0, LEUART1 excluded as they can not
|
||||
be selected through the Mbed API since their
|
||||
pin maps completely overlap each other - FIXME */
|
||||
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
||||
const PinMap PinMap_UART_RX[] = {
|
||||
|
||||
// Pearl ok
|
||||
/* USART0, USART1, LEUART0. Pinmaps are identical
|
||||
so peripheral selection is dynamic */
|
||||
|
||||
/* USART0 */
|
||||
{PA1, USART_0, 0},
|
||||
{PA2, USART_0, 1},
|
||||
{PA3, USART_0, 2},
|
||||
|
|
@ -575,9 +571,5 @@ const PinMap PinMap_UART_RX[] = {
|
|||
{PF7, USART_0, 30},
|
||||
{PA0, USART_0, 31},
|
||||
|
||||
/* USART1, LEUART0, LEUART1 excluded as they can not
|
||||
be selected through the Mbed API since their
|
||||
pin maps completely overlap each other - FIXME */
|
||||
|
||||
{NC , NC , NC}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -124,6 +124,9 @@ int dma_channel_allocate(uint32_t capabilities)
|
|||
|
||||
int dma_channel_free(int channelid)
|
||||
{
|
||||
channels &= ~(1 << channelid);
|
||||
if( channelid >= 0 ) {
|
||||
channels &= ~(1 << channelid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,7 +114,12 @@ struct serial_s {
|
|||
USART_TypeDef *uart;
|
||||
LEUART_TypeDef *leuart;
|
||||
} periph;
|
||||
#ifndef _SILICON_LABS_32B_PLATFORM_2
|
||||
uint32_t location;
|
||||
#else
|
||||
uint32_t location_tx;
|
||||
uint32_t location_rx;
|
||||
#endif
|
||||
PinName rx_pin;
|
||||
PinName tx_pin;
|
||||
#if DEVICE_SERIAL_ASYNCH
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "mbed_assert.h"
|
||||
#include "serial_api.h"
|
||||
#include "serial_api_HAL.h"
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
|
@ -67,6 +68,12 @@
|
|||
#error Undefined number of low energy UARTs (LEUART).
|
||||
#endif
|
||||
|
||||
#ifdef _SILICON_LABS_32B_PLATFORM_2
|
||||
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 */
|
||||
static uint32_t serial_irq_ids[SERIAL_NUM_UARTS] = { 0 };
|
||||
/* Interrupt handler from mbed common */
|
||||
|
|
@ -334,8 +341,55 @@ inline CMU_Clock_TypeDef serial_get_clock(serial_t *obj)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _SILICON_LABS_32B_PLATFORM_2
|
||||
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)
|
||||
{
|
||||
#ifndef _SILICON_LABS_32B_PLATFORM_2
|
||||
/* Older platforms with fixed pin mappings per UART */
|
||||
|
||||
/* Get UART object connected to the given pins */
|
||||
UARTName uart_tx = (UARTName) pinmap_peripheral(tx, PinMap_UART_TX);
|
||||
UARTName uart_rx = (UARTName) pinmap_peripheral(rx, PinMap_UART_RX);
|
||||
|
|
@ -352,6 +406,22 @@ void serial_preinit(serial_t *obj, PinName tx, PinName rx)
|
|||
obj->serial.location = pinmap_merge(uart_tx_loc, uart_rx_loc);
|
||||
MBED_ASSERT(obj->serial.location != (uint32_t)NC);
|
||||
|
||||
#else
|
||||
/* New platforms with free pin mapping */
|
||||
|
||||
obj->serial.periph.uart = serial_uart_allocate(UART_TYPE_USART);
|
||||
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));
|
||||
MBED_ASSERT(uart_tx_loc != uart_rx_loc);
|
||||
|
||||
obj->serial.location_tx = uart_tx_loc;
|
||||
obj->serial.location_rx = uart_rx_loc;
|
||||
#endif
|
||||
|
||||
/* Store pins in object for easy disabling in serial_free() */
|
||||
obj->serial.rx_pin = rx;
|
||||
obj->serial.tx_pin = tx;
|
||||
|
|
@ -450,8 +520,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
|||
#ifdef _LEUART_ROUTE_LOCATION_SHIFT
|
||||
obj->serial.periph.leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
|
||||
#else
|
||||
obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.location << _LEUART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location << _LEUART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.leuart->ROUTEPEN = LEUART_ROUTEPEN_RXPEN | LEUART_ROUTEPEN_TXPEN;
|
||||
#endif
|
||||
obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
|
||||
|
|
@ -460,8 +530,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
|||
#ifdef _USART_ROUTE_LOCATION_SHIFT
|
||||
obj->serial.periph.uart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
|
||||
#else
|
||||
obj->serial.periph.uart->ROUTELOC0 = (obj->serial.location << _USART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location << _USART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.uart->ROUTELOC0 = (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.uart->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
|
||||
#endif
|
||||
obj->serial.periph.uart->IFC = USART_IFC_TXC;
|
||||
|
|
@ -485,6 +555,19 @@ void serial_init(serial_t *obj, PinName tx, PinName rx)
|
|||
|
||||
}
|
||||
|
||||
void serial_free(serial_t *obj)
|
||||
{
|
||||
if( LEUART_REF_VALID(obj->serial.periph.leuart) ) {
|
||||
LEUART_Enable(obj->serial.periph.leuart, leuartDisable);
|
||||
} else {
|
||||
USART_Enable(obj->serial.periph.uart, usartDisable);
|
||||
}
|
||||
|
||||
#ifdef _SILICON_LABS_32B_PLATFORM_2
|
||||
serial_uart_free(obj->serial.periph.uart);
|
||||
#endif
|
||||
}
|
||||
|
||||
void serial_enable(serial_t *obj, uint8_t enable)
|
||||
{
|
||||
if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
|
||||
|
|
@ -601,8 +684,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
|||
#ifdef _LEUART_ROUTE_LOCATION_SHIFT
|
||||
obj->serial.periph.leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
|
||||
#else
|
||||
obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.location << _LEUART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location << _LEUART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.leuart->ROUTEPEN = LEUART_ROUTEPEN_RXPEN | LEUART_ROUTEPEN_TXPEN;
|
||||
#endif
|
||||
|
||||
|
|
@ -652,8 +735,8 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
|
|||
#ifdef _USART_ROUTE_LOCATION_SHIFT
|
||||
obj->serial.periph.uart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
|
||||
#else
|
||||
obj->serial.periph.uart->ROUTELOC0 = (obj->serial.location << _USART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location << _USART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.uart->ROUTELOC0 = (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT) |
|
||||
(obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
|
||||
obj->serial.periph.uart->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
/***************************************************************************//**
|
||||
* @file serial_api_HAL.h
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2015 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no
|
||||
* obligation to support this Software. Silicon Labs is providing the
|
||||
* Software "AS IS", with no express or implied warranties of any kind,
|
||||
* including, but not limited to, any implied warranties of merchantability
|
||||
* or fitness for any particular purpose or warranties against infringement
|
||||
* of any proprietary rights of a third party.
|
||||
*
|
||||
* Silicon Labs will not be liable for any consequential, incidental, or
|
||||
* special damages, or any other relief, or for any claim by any third party,
|
||||
* arising from your use of this Software.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef MBED_SERIAL_API_HAL_H
|
||||
#define MBED_SERIAL_API_HAL_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#ifdef _SILICON_LABS_32B_PLATFORM_2
|
||||
|
||||
#define UART_TYPE_USART 0x01
|
||||
#define UART_TYPE_LEUART 0x02
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *serial_uart_allocate(unsigned int uart_type);
|
||||
void serial_uart_free(void *uart);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "dma_api.h"
|
||||
#include "dma_api_HAL.h"
|
||||
#include "serial_api_HAL.h"
|
||||
#include "spi_api.h"
|
||||
#include "em_usart.h"
|
||||
#include "em_cmu.h"
|
||||
|
|
@ -117,10 +118,11 @@ static void usart_init(spi_t *obj, uint32_t baudrate, USART_Databits_TypeDef dat
|
|||
|
||||
USART_InitSync(obj->spi.spi, &init);
|
||||
}
|
||||
#ifdef LDMA_PRESENT
|
||||
#ifdef _SILICON_LABS_32B_PLATFORM_2
|
||||
void spi_preinit(spi_t *obj, PinName mosi, PinName miso, PinName clk, PinName cs)
|
||||
{
|
||||
obj->spi.spi = (USART_TypeDef *) pinmap_peripheral(mosi, PinMap_SPI_MOSI);
|
||||
obj->spi.spi = serial_uart_allocate(UART_TYPE_USART);
|
||||
MBED_ASSERT(obj->spi.spi);
|
||||
SPIName spi_cs = (SPIName) pinmap_peripheral(cs, PinMap_SPI_CS);
|
||||
if (cs != NC) { /* Slave mode */
|
||||
obj->spi.master = false;
|
||||
|
|
|
|||
Loading…
Reference in New Issue