⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_uart.c

📁 arm_bootloader _flash writter &USB
💻 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 + -