UART API¶
The UART API provides console I/O functions for serial communication.
Overview¶
The UART module provides:
- Character and string I/O
- Printf-style formatted output
- Input buffering and line editing
- Non-blocking input checking
- Buffer management
The SDK configures UART0 for:
- 115200 baud rate
- 8 data bits, no parity, 1 stop bit (8N1)
- No hardware flow control
Header¶
Initialization¶
embsec_uart_init¶
Initialize UART for console I/O. This is automatically called by embsec_init().
Note: You don't need to call this directly unless reinitializing UART.
Character I/O¶
embsec_putchar¶
Send a single character to UART.
Parameters:
c: Character to send (0-255)
Example:
embsec_getchar¶
Get a single character from UART. This function blocks until a character is available.
Returns:
- Character received (0-255)
Example:
embsec_printf("Press any key to continue...");
int c = embsec_getchar();
embsec_printf("\nYou pressed: %c\n", c);
embsec_kbhit¶
Check if a character is available without blocking.
Returns:
trueif character availablefalseotherwise
Example:
String I/O¶
embsec_puts¶
Send a null-terminated string to UART. Does not append newline.
Parameters:
str: Null-terminated string to send
Example:
embsec_gets¶
Get a line of input from UART. Reads until newline or buffer full.
Parameters:
buffer: Buffer to store inputsize: Maximum size of buffer (including null terminator)
Returns:
- Pointer to buffer on success
- NULL on error
Features:
- Handles backspace for line editing
- Null-terminates the string
- Newline is not included in buffer
- Echoes characters as typed
Example:
char name[32];
embsec_printf("Enter your name: ");
if (embsec_gets(name, sizeof(name))) {
embsec_printf("Hello, %s!\n", name);
} else {
embsec_printf("Error reading input\n");
}
Formatted Output¶
embsec_printf¶
Printf-style formatted output to UART.
Parameters:
format: Format string...: Variable arguments
Returns:
- Number of characters printed
Supported format specifiers:
%c- Character%s- String%d,%i- Signed decimal integer%u- Unsigned decimal integer%x- Unsigned hexadecimal (lowercase)%X- Unsigned hexadecimal (uppercase)%p- Pointer%%- Literal percent sign
Example:
int value = 42;
embsec_printf("The answer is %d (0x%02X)\n", value, value);
// Print table
embsec_printf("%-10s %5s %8s\n", "Name", "Score", "Hex");
embsec_printf("%-10s %5d %8X\n", "Alice", 95, 95);
embsec_vprintf¶
Vprintf-style formatted output. Useful for creating wrapper functions.
Parameters:
format: Format stringargs: Variable argument list
Returns:
- Number of characters printed
Example:
void debug_printf(const char *format, ...) {
embsec_puts("[DEBUG] ");
va_list args;
va_start(args, format);
embsec_vprintf(format, args);
va_end(args);
}
Buffer Management¶
embsec_uart_flush¶
Wait until all pending transmit data has been sent. Useful before system reset or power down.
Example:
embsec_printf("System shutting down...\n");
embsec_uart_flush(); // Ensure message is sent
embsec_system_reset();
embsec_uart_clear¶
Clear the UART receive buffer, discarding any pending data.
Example:
Common Patterns¶
Menu System¶
void show_menu(void) {
embsec_printf("\n=== Main Menu ===\n");
embsec_printf("1. Option One\n");
embsec_printf("2. Option Two\n");
embsec_printf("3. Exit\n");
embsec_printf("Choice: ");
}
int main(void) {
embsec_init();
while (1) {
show_menu();
char choice = embsec_getchar();
embsec_printf("%c\n", choice); // Echo choice
switch (choice) {
case '1':
embsec_printf("You selected Option One\n");
break;
case '2':
embsec_printf("You selected Option Two\n");
break;
case '3':
embsec_printf("Goodbye!\n");
embsec_uart_flush();
return 0;
default:
embsec_printf("Invalid choice!\n");
}
}
}
Command Parser¶
void process_command(const char *cmd) {
if (strcmp(cmd, "help") == 0) {
embsec_printf("Available commands:\n");
embsec_printf(" help - Show this help\n");
embsec_printf(" status - Show system status\n");
embsec_printf(" reset - Reset system\n");
} else if (strcmp(cmd, "status") == 0) {
embsec_printf("System uptime: %u ms\n", embsec_get_tick_ms());
} else if (strcmp(cmd, "reset") == 0) {
embsec_system_reset();
} else {
embsec_printf("Unknown command: %s\n", cmd);
}
}
int main(void) {
embsec_init();
char buffer[64];
embsec_printf("Command Line Interface\n");
embsec_printf("Type 'help' for commands\n");
while (1) {
embsec_printf("> ");
if (embsec_gets(buffer, sizeof(buffer))) {
if (strlen(buffer) > 0) {
process_command(buffer);
}
}
}
}
Debug Output¶
#define DEBUG 1
#if DEBUG
#define DEBUG_PRINT(...) embsec_printf("[DEBUG] " __VA_ARGS__)
#else
#define DEBUG_PRINT(...)
#endif
void some_function(int value) {
DEBUG_PRINT("Entering function with value=%d\n", value);
// Function implementation
DEBUG_PRINT("Function completed\n");
}
Progress Indicator¶
void show_progress(int current, int total) {
int percent = (current * 100) / total;
embsec_printf("\rProgress: [");
// Draw progress bar
for (int i = 0; i < 20; i++) {
if (i < (percent / 5)) {
embsec_putchar('#');
} else {
embsec_putchar(' ');
}
}
embsec_printf("] %d%%", percent);
if (current >= total) {
embsec_printf("\n");
}
}
// Usage
for (int i = 0; i <= 100; i++) {
show_progress(i, 100);
embsec_delay_ms(50);
}
Terminal Compatibility¶
The UART functions work with standard terminal emulators:
- Supports VT100 escape sequences
- Backspace handling for line editing
- Carriage return and line feed handling
ANSI Color Codes¶
// Color code definitions
#define ANSI_RED "\x1b[31m"
#define ANSI_GREEN "\x1b[32m"
#define ANSI_YELLOW "\x1b[33m"
#define ANSI_BLUE "\x1b[34m"
#define ANSI_RESET "\x1b[0m"
// Colored output
embsec_printf(ANSI_GREEN "Success!" ANSI_RESET "\n");
embsec_printf(ANSI_RED "Error: " ANSI_RESET "Invalid input\n");
Performance Considerations¶
Buffering¶
- UART transmission is interrupt-driven
- Small transmit FIFO (16 bytes)
- No receive buffering beyond hardware FIFO
Throughput¶
At 115200 baud:
- ~11,520 characters per second theoretical maximum
- ~10,000 characters per second practical throughput
- Printf operations may block if buffer full
Best Practices¶
-
Use flush before critical operations:
-
Clear input buffer before prompts:
-
Check for input in main loop:
-
Limit printf in interrupts:
// BAD - Printf in interrupt void timer_isr(void) { embsec_printf("Timer fired!\n"); // May cause issues } // GOOD - Set flag in interrupt volatile bool timer_fired = false; void timer_isr(void) { timer_fired = true; } // Print in main loop if (timer_fired) { timer_fired = false; embsec_printf("Timer fired!\n"); }
Troubleshooting¶
No Output¶
- Check terminal settings: 115200 8N1
- Verify
embsec_init()was called - Check TX/RX connections
Garbled Characters¶
- Verify baud rate matches terminal
- Check for clock configuration issues
- Ensure proper grounding
Missing Characters¶
- Add
embsec_uart_flush()after output - Check for buffer overruns
- Reduce output rate
Example: Interactive Shell¶
#include <embsec/embsec.h>
#include <embsec/uart.h>
#include <string.h>
#define CMD_BUFFER_SIZE 64
#define HISTORY_SIZE 5
typedef struct {
char buffer[CMD_BUFFER_SIZE];
} cmd_history_t;
int main(void) {
embsec_init();
cmd_history_t history[HISTORY_SIZE] = {0};
int history_index = 0;
char cmd_buffer[CMD_BUFFER_SIZE];
embsec_printf("\n=== EmbSec Interactive Shell ===\n");
embsec_printf("Type 'help' for commands\n\n");
while (1) {
// Show prompt
embsec_printf("embsec> ");
// Get command
if (!embsec_gets(cmd_buffer, sizeof(cmd_buffer))) {
continue;
}
// Skip empty commands
if (strlen(cmd_buffer) == 0) {
continue;
}
// Save to history
strcpy(history[history_index].buffer, cmd_buffer);
history_index = (history_index + 1) % HISTORY_SIZE;
// Process command
if (strcmp(cmd_buffer, "help") == 0) {
embsec_printf("Commands:\n");
embsec_printf(" help - Show this help\n");
embsec_printf(" clear - Clear screen\n");
embsec_printf(" echo MSG - Echo message\n");
embsec_printf(" history - Show command history\n");
embsec_printf(" uptime - Show system uptime\n");
embsec_printf(" exit - Exit shell\n");
}
else if (strcmp(cmd_buffer, "clear") == 0) {
embsec_printf("\x1b[2J\x1b[H"); // ANSI clear screen
}
else if (strncmp(cmd_buffer, "echo ", 5) == 0) {
embsec_printf("%s\n", cmd_buffer + 5);
}
else if (strcmp(cmd_buffer, "history") == 0) {
embsec_printf("Command history:\n");
for (int i = 0; i < HISTORY_SIZE; i++) {
if (strlen(history[i].buffer) > 0) {
embsec_printf(" %s\n", history[i].buffer);
}
}
}
else if (strcmp(cmd_buffer, "uptime") == 0) {
uint32_t ms = embsec_get_tick_ms();
uint32_t sec = ms / 1000;
embsec_printf("Uptime: %u:%02u:%02u\n",
sec / 3600, (sec / 60) % 60, sec % 60);
}
else if (strcmp(cmd_buffer, "exit") == 0) {
embsec_printf("Goodbye!\n");
break;
}
else {
embsec_printf("Unknown command: %s\n", cmd_buffer);
}
}
return 0;
}