system/uart/main.c

/*******************************************************************************
* # License
* Copyright 2019 Silicon Laboratories Inc. www.silabs.com
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
/* Documentation for this app is available online.
* See https://docs.silabs.com/gecko-os/4/standard/latest/sdk/examples/system/uart
*/
#include "gos.h"
#define UART_MAX_IRQ_EVENTS (3)
#define UART_RX_TIMEOUT_MS (30)
#define UART_RX_THRESHOLD_LENGTH (100)
#define APPLICATION_START_LINE "\r\nUART example starting ...\r\n"
GOS_CMD_CREATE_COMMAND(uart, init, "uart_init", "uinit", 0, 0, true);
static uint8_t rx_buffer[1024];
static uint8_t ring_buffer_data[1024];
static uint32_t uart_rx_timestamp;
/*************************************************************************************************/
void gos_app_init(void)
{
GOS_LOG(APPLICATION_START_LINE);
}
GOS_DEFINE_COMMAND(uart, init)
{
const gos_uart_config_t config =
{
.baud_rate = 115200,
.data_width = GOS_UART_WIDTH_8BIT,
.parity = GOS_UART_NO_PARITY,
.stop_bits = GOS_UART_STOP_BITS_1,
};
const gos_buffer_t uart_buffer =
{
.data = ring_buffer_data,
.size = sizeof(ring_buffer_data)
};
GOS_LOG("\r\nType something ...");
GOS_LOG("NOTE: The command console is disabled, type: '$' to re-enable the console");
gos_event_enable_irq_events(UART_MAX_IRQ_EVENTS);
gos_uart_configure(PLATFORM_STD_UART, &config, &uart_buffer);
set_uart_data_forwarding_enabled(true);
}
/*************************************************************************************************
* Executes in the UART IRQ
*/
static gos_result_t uart_rx_callback(void *arg)
{
uint32_t bytes_read = 0;
bool invoke_rx_event = false;
const uint32_t now = gos_rtos_get_time();
if ((now - uart_rx_timestamp) >= UART_RX_TIMEOUT_MS)
{
// If the time elapsed since the last rx event was invoked is greater than UART_RX_TIMEOUT_MS, then invoke the rx event again
invoke_rx_event = true;
}
else
{
gos_uart_peek_bytes(PLATFORM_STD_UART, NULL, &bytes_read);
if (bytes_read >= UART_RX_THRESHOLD_LENGTH)
{
// If the number of RX bytes pending is greater than UART_RX_THRESHOLD_LENGTH, then invoke the rx event
invoke_rx_event = true;
}
}
if (invoke_rx_event)
{
// Update the RX event timestamp and issue the RX event
uart_rx_timestamp = now;
gos_event_issue(uart_rx_event_handler, NULL, GOS_EVENT_FLAG_NONE);
}
return GOS_SUCCESS;
}
/*************************************************************************************************/
static void uart_rx_event_handler(void *arg)
{
uint32_t bytes_available;
gos_uart_peek_bytes(PLATFORM_STD_UART, NULL, &bytes_available);
uint32_t rx_len = MIN(bytes_available, sizeof(rx_buffer)-1);
if ((rx_len > 0) && (gos_uart_receive_bytes(PLATFORM_STD_UART, rx_buffer, rx_len, &rx_len, GOS_WAIT_FOREVER) == GOS_SUCCESS))
{
gos_uart_transmit_bytes(PLATFORM_STD_UART, rx_buffer, rx_len, NULL, GOS_WAIT_FOREVER);
rx_buffer[rx_len] = 0;
if (strchr((char*)rx_buffer, '$') != NULL)
{
set_uart_data_forwarding_enabled(false);
}
}
}
/*************************************************************************************************
* Since we're overriding the STD uart we need to ensure the Gecko OS command console is disabled.
* Note that the command console can also be disable by setting the build flag:
* GLOBAL_DEFINES := GOS_FLAGS=GOS_APP_FLAG_DISABLE_CMD_CONSOLE
*/
static void set_uart_data_forwarding_enabled(bool enabled)
{
if (enabled == true)
{
GOS_LOG("Disabling command console");
gos_uart_set_rx_callback(PLATFORM_STD_UART, uart_rx_callback);
}
else
{
GOS_LOG("\r\nEnabling command console");
gos_uart_clear_rx_callback(PLATFORM_STD_UART, uart_rx_callback);
}
}