📄 os_uart.c
字号:
#include "config.h"
#include "2410addr.h"
#include "hal/isr.h"
#include "os_uart.h"
#include "os_ring.h"
#include <ucos_ii.h>
static uart_buf_t uart_buf;
__inline void enable_uart0_irq(void) { rINTMSK &= ~BIT_UART0; }
__inline void disable_uart0_irq(void) { rINTMSK |= BIT_UART0; }
__inline void enable_uart0_tx_irq(void) { rINTSUBMSK &= ~BIT_SUB_TXD0; }
__inline void disable_uart0_tx_irq(void) { rINTSUBMSK |= BIT_SUB_TXD0; }
__inline void enable_uart0_rx_irq(void) { rINTSUBMSK &= ~BIT_SUB_RXD0; }
__inline void disable_uart0_rx_irq(void) { rINTSUBMSK |= BIT_SUB_RXD0; }
__inline static void OS_Uart_SendByte(int data) { rUTXH0 = data; }
__inline static unsigned char OS_Uart_ReadByte() { return rURXH0; }
/* ---------- */
#define UART_FIFO_SIZE (16)
void uart_tx_irq_handler()
{
unsigned char buf[UART_FIFO_SIZE/2];
unsigned int free_fifo_size;
unsigned int i;
int len_str;
while( ((rUFSTAT0>>9)&1) == 0) // FIFO isn't full
{
free_fifo_size = (UART_FIFO_SIZE - ((rUFSTAT0>>4) & 0xF));
if(free_fifo_size < 2) // If we want to send '\n', 2 fifo entries are required...
break;
// For the special case that buf are all '\n', then we can utilize only half of buffer size
len_str = getring(&uart_buf.tx_buf, buf, free_fifo_size/2);
if(len_str == -1)
break;
for(i=0; i<len_str; i++)
{
OS_Uart_SendByte(buf[i]);
if(buf[i] == '\n')
OS_Uart_SendByte('\r');
}
}
rSUBSRCPND = BIT_SUB_TXD0;
}
void OS_uart_putstring(char *str, unsigned int len)
{
putring(&uart_buf.tx_buf, (unsigned char*)str, len);
OS_Uart_SendByte(0); // trigger TX IRQ
}
/* ---------- */
void uart_rx_irq_handler(void)
{
static int cursor_pos = 0;
unsigned char rx_data;
while( (rUFSTAT0&0xF) != 0) // RX FIFO isn't empty
{
rx_data = OS_Uart_ReadByte();
putring_char(&uart_buf.rx_buf, rx_data);
switch(rx_data)
{
case '\r': // user pressed Enter
case '\n':
putring_char(&uart_buf.tx_buf, '\n');
putring_char(&uart_buf.tx_buf, '\r');
cursor_pos = 0;
OSSemPost(uart_buf.rx_sem);
break;
case 8: // backspace
if(cursor_pos > 0)
{
putring_char(&uart_buf.tx_buf, 8); // backspace
putring_char(&uart_buf.tx_buf, ' '); // space (used to clear screen)
putring_char(&uart_buf.tx_buf, 8); // backscape
cursor_pos--;
}
break;
default:
putring_char(&uart_buf.tx_buf, rx_data);
cursor_pos++;
break;
}
enable_uart0_tx_irq();
}
uart_tx_irq_handler(); // Trigger TX IRQ
rSUBSRCPND = BIT_SUB_RXD0 | BIT_SUB_ERR0;
}
int OS_uart_getstring(char *buf, int size_buf)
{
INT8U perr;
int i, len_str, index_write = 0;
OSSemPend(uart_buf.rx_sem, 0, &perr); // wait for user press enter
len_str = getring(&uart_buf.rx_buf, (unsigned char*)buf, size_buf-1); // Get only allowed length of string (-1 is because '\0')
ring_flush(&uart_buf.rx_buf); // Flush remaining characters...
for(i=0; i<len_str; i++)
{
unsigned char c = buf[i];
switch(c)
{
case '\r':
case '\n':
break;
case 8: // backspace, we need special processing...
if(index_write > 0) // if we already have something in the buffer...
index_write--;
break;
default:
buf[index_write] = buf[i];
index_write++;
}
}
buf[index_write] = '\0';
return index_write; // index_write is the length of the string
}
// The IRQ is triggered due to empty-FIFO
void HandlerUART0(void)
{
uart_tx_irq_handler();
uart_rx_irq_handler();
}
void OS_uart_init_115200(void)
{
// Register TX & RX semaphore
uart_buf.tx_sem = OSSemCreate(1);
uart_buf.rx_sem = OSSemCreate(0);
ring_flush(&uart_buf.tx_buf);
ring_flush(&uart_buf.rx_buf);
// UART is already started in bootloader code
// The code here is to enable UART IRQ & set ISR funcrion
enable_uart0_irq();
enable_uart0_tx_irq();
enable_uart0_rx_irq();
install_IRQ_handler(nUART0_INT, HandlerUART0);
}
/* ---------- */
uart_buf_t* uart_get_buf(void)
{
return &uart_buf;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -