Skip to content

Ambiq apollo3 serial fix #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 50 additions & 111 deletions targets/TARGET_Ambiq_Micro/TARGET_Apollo3/device/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ void uart_configure_pin_function(PinName pin, UARTName uart, const PinMap *map);
*/

void serial_init(serial_t *obj, PinName tx, PinName rx) {
//TODO: we should be able to call this multiple times
// determine the UART to use
UARTName uart_tx = (UARTName)pinmap_peripheral(tx, serial_tx_pinmap());
UARTName uart_rx = (UARTName)pinmap_peripheral(rx, serial_rx_pinmap());
Expand All @@ -127,41 +126,41 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
obj->serial.uart_control = &ap3_uart_control[uart];
obj->serial.uart_control->inst = uart;

// ensure that HAL queueing is disabled (we want to use the FIFOs directly)
obj->serial.uart_control->cfg.pui8RxBuffer = NULL;
obj->serial.uart_control->cfg.pui8TxBuffer = NULL;
obj->serial.uart_control->cfg.ui32RxBufferSize = 0;
obj->serial.uart_control->cfg.ui32TxBufferSize = 0;

// memset(obj->serial.uart_control->cfg, 0x00, sizeof(am_hal_uart_config_t)); // ensure config begins zeroed

// config uart pins
pinmap_config(tx, serial_tx_pinmap());
pinmap_config(rx, serial_rx_pinmap());

// start UART instance
MBED_ASSERT(am_hal_uart_initialize(uart, &(obj->serial.uart_control->handle)) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_power_control(obj->serial.uart_control->handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS);
if(!obj->serial.uart_control->handle) {
// if handle uninitialized this is first time set up
// ensure that HAL queueing is disabled (we want to use the FIFOs directly)
obj->serial.uart_control->cfg.pui8RxBuffer = NULL;
obj->serial.uart_control->cfg.pui8TxBuffer = NULL;
obj->serial.uart_control->cfg.ui32RxBufferSize = 0;
obj->serial.uart_control->cfg.ui32TxBufferSize = 0;

obj->serial.uart_control->cfg.ui32FifoLevels = AM_HAL_UART_RX_FIFO_7_8;

// start UART instance
MBED_ASSERT(am_hal_uart_initialize(uart, &(obj->serial.uart_control->handle)) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_power_control(obj->serial.uart_control->handle, AM_HAL_SYSCTRL_WAKE, false) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_configure_fifo(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg), false) == AM_HAL_STATUS_SUCCESS);

// set default baud rate and format
serial_baud(obj, 9600);
serial_format(obj, 8, ParityNone, 1);
// set default format
serial_format(obj, 8, ParityNone, 1);
}
}

void serial_free(serial_t *obj)
{
void serial_free(serial_t *obj) {
// nothing to do unless resources are allocated for members of the serial_s serial member of obj
// assuming mbed handles obj and its members
}

void serial_baud(serial_t *obj, int baudrate) {
obj->serial.uart_control->cfg.ui32BaudRate = (uint32_t)baudrate;
MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_configure_fifo(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg), false) == AM_HAL_STATUS_SUCCESS);
}

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) {
uint32_t am_hal_data_bits = 0;
switch (data_bits) {
case 5:
Expand Down Expand Up @@ -214,36 +213,44 @@ void serial_format(serial_t *obj, int data_bits, SerialParity parity, int stop_b
obj->serial.uart_control->cfg.ui32DataBits = (uint32_t)am_hal_data_bits;
obj->serial.uart_control->cfg.ui32Parity = (uint32_t)am_hal_parity;
obj->serial.uart_control->cfg.ui32StopBits = (uint32_t)am_hal_stop_bits;
MBED_ASSERT(am_hal_uart_configure(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg)) == AM_HAL_STATUS_SUCCESS);
MBED_ASSERT(am_hal_uart_configure_fifo(obj->serial.uart_control->handle, &(obj->serial.uart_control->cfg), false) == AM_HAL_STATUS_SUCCESS);
}

void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id)
{
void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) {
irq_handler = handler;
obj->serial.uart_control->serial_irq_id = id;
}

void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable)
{
MBED_ASSERT(obj->serial.uart_control != NULL);

am_hal_uart_interrupt_enable(obj->serial.uart_control->handle, (AM_HAL_UART_INT_RX | AM_HAL_UART_INT_TX | AM_HAL_UART_INT_TXCMP));

switch (obj->serial.uart_control->inst)
{
case 0:
NVIC_SetVector((IRQn_Type)UART0_IRQn, (uint32_t)am_uart_isr);
break;
case 1:
NVIC_SetVector((IRQn_Type)UART1_IRQn, (uint32_t)am_uart1_isr);
break;
void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) {
MBED_ASSERT(obj->serial.uart_control->handle != NULL);
if (enable) {
switch (irq) {
case RxIrq:
MBED_ASSERT(am_hal_uart_interrupt_enable(obj->serial.uart_control->handle, AM_HAL_UART_INT_RX) == AM_HAL_STATUS_SUCCESS);
break;
case TxIrq:
MBED_ASSERT(am_hal_uart_interrupt_enable(obj->serial.uart_control->handle, AM_HAL_UART_INT_TXCMP) == AM_HAL_STATUS_SUCCESS);
break;
default:
break;
}
// NVIC_SetVector(uart_irqs[obj->serial.index], vector);
NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.uart_control->inst));
} else { // disable
switch (irq) {
case RxIrq:
MBED_ASSERT(am_hal_uart_interrupt_disable(obj->serial.uart_control->handle, AM_HAL_UART_INT_RX) == AM_HAL_STATUS_SUCCESS);
break;
case TxIrq:
MBED_ASSERT(am_hal_uart_interrupt_disable(obj->serial.uart_control->handle, AM_HAL_UART_INT_TXCMP) == AM_HAL_STATUS_SUCCESS);
break;
default:
break;
}
}

NVIC_EnableIRQ((IRQn_Type)(UART0_IRQn + obj->serial.uart_control->inst));
}

int serial_getc(serial_t *obj)
{
int serial_getc(serial_t *obj) {
MBED_ASSERT(obj->serial.uart_control != NULL);

uint8_t rx_c = 0x00;
Expand All @@ -263,8 +270,7 @@ int serial_getc(serial_t *obj)
return (int)rx_c;
}

void serial_putc(serial_t *obj, int c)
{
void serial_putc(serial_t *obj, int c) {
MBED_ASSERT(obj->serial.uart_control != NULL);

volatile uint32_t bytes_sent = 0;
Expand Down Expand Up @@ -343,72 +349,6 @@ const PinMap *serial_rts_pinmap(void) {
}
#endif

#if DEVICE_SERIAL_ASYNCH

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)
{
MBED_ASSERT(obj->serial.uart_control != NULL);
uint32_t bytes_written = 0;

am_hal_uart_transfer_t am_hal_uart_xfer_write = {
.ui32Direction = AM_HAL_UART_WRITE,
.pui8Data = (uint8_t *)obj->tx_buff.buffer,
.ui32NumBytes = tx_length, // todo: consider maybe this? (uint32_t)obj->tx_buff.length,
.ui32TimeoutMs = 0,
.pui32BytesTransferred = &bytes_written,
};

am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_write);

return (int)bytes_written;
}

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)
{
// todo: revisit
MBED_ASSERT(obj->serial.uart_control != NULL);
uint32_t bytes_read = 0;

am_hal_uart_transfer_t am_hal_uart_xfer_read = {
.ui32Direction = AM_HAL_UART_READ,
.pui8Data = (uint8_t *)obj->rx_buff.buffer,
.ui32NumBytes = rx_length, // todo: consider this (uint32_t)obj->rx_buff.length,
.ui32TimeoutMs = 0,
.pui32BytesTransferred = &bytes_read,
};

am_hal_uart_transfer(obj->serial.uart_control->handle, &am_hal_uart_xfer_read);
}

uint8_t serial_tx_active(serial_t *obj) {
// todo:
MBED_ASSERT(0);
}

uint8_t serial_rx_active(serial_t *obj) {
// todo:
MBED_ASSERT(0);
}

int serial_irq_handler_asynch(serial_t *obj) {
// todo:
MBED_ASSERT(0);
}

void serial_tx_abort_asynch(serial_t *obj) {
// todo:
MBED_ASSERT(0);
}

void serial_rx_abort_asynch(serial_t *obj) {
// todo:
MBED_ASSERT(0);
}

/**@}*/

#endif

static inline void uart_irq(uint32_t instance)
{
void *handle = ap3_uart_control[instance].handle;
Expand All @@ -434,7 +374,6 @@ static inline void uart_irq(uint32_t instance)
}

extern void am_uart_isr(void) {
am_hal_gpio_output_set(16); // todo: this should not be here!
uart_irq(UART_0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,96 @@ am_hal_uart_configure(void *pHandle, const am_hal_uart_config_t *psConfig)
return AM_HAL_STATUS_SUCCESS;
} // am_hal_uart_configure()

uint32_t
am_hal_uart_configure_fifo(void *pHandle, const am_hal_uart_config_t *psConfig, bool bEnableFIFO)
{
am_hal_uart_state_t *pState = (am_hal_uart_state_t *) pHandle;
uint32_t ui32Module = pState->ui32Module;

uint32_t ui32ErrorStatus;

//
// Check to make sure this is a valid handle.
//
if (!AM_HAL_UART_CHK_HANDLE(pHandle))
{
return AM_HAL_STATUS_INVALID_HANDLE;
}

//
// Reset the CR register to a known value.
//
UARTn(ui32Module)->CR = 0;

//
// Start by enabling the clocks, which needs to happen in a critical
// section.
//
AM_CRITICAL_BEGIN

UARTn(ui32Module)->CR_b.CLKEN = 1;
UARTn(ui32Module)->CR_b.CLKSEL = UART0_CR_CLKSEL_24MHZ;

AM_CRITICAL_END

//
// Disable the UART.
//
AM_CRITICAL_BEGIN

UARTn(ui32Module)->CR_b.UARTEN = 0;
UARTn(ui32Module)->CR_b.RXE = 0;
UARTn(ui32Module)->CR_b.TXE = 0;

AM_CRITICAL_END

//
// Set the baud rate.
//
ui32ErrorStatus = config_baudrate(ui32Module, psConfig->ui32BaudRate,
&(pState->ui32BaudRate));

RETURN_ON_ERROR(ui32ErrorStatus);

//
// Copy the configuration options into the appropriate registers.
//
UARTn(ui32Module)->CR_b.RTSEN = 0;
UARTn(ui32Module)->CR_b.CTSEN = 0;
UARTn(ui32Module)->CR |= psConfig->ui32FlowControl;

UARTn(ui32Module)->IFLS = psConfig->ui32FifoLevels;

UARTn(ui32Module)->LCRH = (psConfig->ui32DataBits |
psConfig->ui32Parity |
psConfig->ui32StopBits |
((bEnableFIFO) ? AM_HAL_UART_FIFO_ENABLE : AM_HAL_UART_FIFO_DISABLE));

//
// Enable the UART, RX, and TX.
//
AM_CRITICAL_BEGIN

UARTn(ui32Module)->CR_b.UARTEN = 1;
UARTn(ui32Module)->CR_b.RXE = 1;
UARTn(ui32Module)->CR_b.TXE = 1;

AM_CRITICAL_END

if(bEnableFIFO){
//
// Set up any buffers that might exist.
//
buffer_configure(pHandle,
psConfig->pui8TxBuffer,
psConfig->ui32TxBufferSize,
psConfig->pui8RxBuffer,
psConfig->ui32RxBufferSize);
}

return AM_HAL_STATUS_SUCCESS;
} // am_hal_uart_configure_fifo()

//*****************************************************************************
//
// Allows the UART HAL to use extra space to store TX and RX data.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ extern uint32_t am_hal_uart_power_control(void *pHandle,
extern uint32_t am_hal_uart_configure(void *pHandle,
const am_hal_uart_config_t *psConfig);

extern uint32_t am_hal_uart_configure_fifo(void *pHandle,
const am_hal_uart_config_t *psConfig,
bool bEnableFIFO);

//*****************************************************************************
//
//! @brief Transfer data through the UART interface.
Expand Down