博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
RT-Thread Mini2440串口驱动
阅读量:4680 次
发布时间:2019-06-09

本文共 9640 字,大约阅读时间需要 32 分钟。

参照模板自己写了一遍,期间出现很多问题。比如定义全局uart0设备指针后未初始化,导致RT_ASSERT(device != RT_NULL)执行,使设备注册时死机。

初始化函数没写对,也导致了程序崩溃。

// uart.h// 2015.12.18 by Huangtao#ifndef __UART_H__#define __UART_H__#include 
#include
#include
#include
#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */#define UART_RX_BUFFER_SIZE 64typedef struct uartport{ volatile rt_uint32_t ulcon; volatile rt_uint32_t ucon; volatile rt_uint32_t ufcon; volatile rt_uint32_t umcon; volatile rt_uint32_t ustat; volatile rt_uint32_t urxb; volatile rt_uint32_t ufstat; volatile rt_uint32_t umstat; volatile rt_uint32_t utxh; volatile rt_uint32_t urxh; volatile rt_uint32_t ubrd;}uartport;// 中断接收时的ringbuffer缓冲区定义struct uart_int_rx{ rt_uint8_t rx_buffer[UART_RX_BUFFER_SIZE]; rt_uint32_t read_index, save_index;};// 串口设备struct uart_device{ uartport* uart_device; struct uart_int_rx* int_rx;};extern rt_err_t rt_hw_uart_register(rt_device_t device, const char* name, rt_uint32_t flag, struct uart_device *uart);extern void rt_hw_uart_isr(rt_device_t device);extern void rt_hw_uart_init(void);#endif
// uart.c// uart驱动// 2015.12.18 by Huangtao#include "uart.h"#define baudrate 115200 extern rt_uint32_t PCLK;// 设置好uart0的实际物理地址#define MYUART0   ((struct uartport *)&U0BASE)struct uart_int_rx uart0_int_rx;struct uart_device myUart0 ={    MYUART0,    &uart0_int_rx};// 全局uart0设备struct rt_device myuart0_dev;rt_device_t myUart0_device = &myuart0_dev;// 初始化static rt_err_t uart_init(rt_device_t dev){    struct uart_device* uart;    // 获得真实的UART设备对象        uart = (struct uart_device*)dev->user_data;    // 判断设备是否已经激活了    if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))    {        // 如果是中断接收模式,初始化接收的缓冲区        if (dev->flag & RT_DEVICE_FLAG_INT_RX)        {            rt_memset(uart->int_rx->rx_buffer, 0,                sizeof(uart->int_rx->rx_buffer));            uart->int_rx->read_index = 0;            uart->int_rx->save_index = 0;        }        // 设置设备为激活状态        dev->flag |= RT_DEVICE_FLAG_ACTIVATED;    }    return RT_EOK;}// 打开设备static rt_err_t uart_open(rt_device_t dev, rt_uint16_t oflag){    RT_ASSERT(dev != RT_NULL);        return RT_EOK;}// 关闭设备static rt_err_t uart_close(rt_device_t dev){    RT_ASSERT(device != RT_NULL);       return RT_EOK;}// 从设备中读取数据static rt_size_t uart_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size){    rt_base_t level;    rt_uint8_t* ptr;    struct uart_device* uart;    struct uart_int_rx* int_rx;    ptr = buffer;    uart = (struct uart_device*)dev->user_data;    int_rx = uart->int_rx;    if (ptr == RT_NULL)    {        return RT_ENOMEM;    }    if (dev->flag & RT_DEVICE_FLAG_INT_RX)    {        // 中断模式接收,中断模式接收在中断服务例程中已预先收取到缓冲区中,        // 所以这里只需要从缓冲区中复制出数据        while (size)        {            level = rt_hw_interrupt_disable();            if (int_rx->read_index != int_rx->save_index)            {                *ptr++ = int_rx->rx_buffer[int_rx->read_index];                size--;                int_rx->read_index ++;                if (int_rx->read_index >= UART_RX_BUFFER_SIZE)                    int_rx->read_index = 0;                rt_hw_interrupt_enable(level);            }            else            {                rt_hw_interrupt_enable(level);                break;            }        }    }    else    {        // 轮询模式,直接从串口设备中读取数据        while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)        {            while (uart->uart_device->ustat & RT_SERIAL_EVENT_RX_IND)            {                *ptr = uart->uart_device->urxh & 0xff;                ptr ++;            }        }            }    // 返回读取到的字节数    return (rt_uint32_t)ptr - (rt_uint32_t)buffer;}// 向设备中写入数据static rt_size_t uart_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size){    rt_uint8_t* ptr;    struct uart_device* uart;    ptr = (rt_uint8_t*)buffer;    uart = (struct uart_device*)dev->user_data;    if (ptr == RT_NULL)    {        return RT_ENOMEM;    }    if ((dev->flag & RT_DEVICE_FLAG_INT_TX))    {            }    else    {        // 直接写入        while (size)        {            if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))            {                while (!(uart->uart_device->ustat & RT_SERIAL_EVENT_TX_DONE));                uart->uart_device->utxh = '\r';            }            //wait Tx empty            while(!(uart->uart_device->ustat & RT_SERIAL_EVENT_TX_DONE));            uart->uart_device->utxh = (*ptr & 0xFF);            ++ptr;            --size;        }        }    // 返回写入成功的字节数    return (rt_uint32_t)ptr - (rt_uint32_t)buffer;}// 设备控制操作// 还未实现static rt_err_t uart_control(rt_device_t dev, rt_uint8_t cmd, void *args){    RT_ASSERT(dev != RT_NULL);    switch (cmd)    {    case RT_DEVICE_CTRL_SUSPEND:        // 挂起设备        dev->flag |= RT_DEVICE_FLAG_SUSPENDED;           break;        case RT_DEVICE_CTRL_RESUME:        // 唤醒设备        dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;        break;    }    return RT_EOK;}// 向系统中注册串口设备rt_err_t rt_hw_uart_register(rt_device_t device, const char* name, rt_uint32_t flag, struct uart_device *uart){    RT_ASSERT(device != RT_NULL);    device->type        = RT_Device_Class_Char;    device->rx_indicate = RT_NULL;    device->tx_complete = RT_NULL;    // 设置设备驱动公共接口函数    device->init        = uart_init;    device->open        = uart_open;    device->close       = uart_close;    device->read        = uart_read;    device->write       = uart_write;    device->control     = uart_control;    device->user_data   = uart;    // 注册设备    rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);        return RT_EOK;}// ISR for serial interruptvoid rt_hw_uart_isr(rt_device_t device){    rt_base_t level;    struct uart_device* uart;    struct uart_int_rx* int_rx;            uart = (struct uart_device*)device->user_data;    int_rx = uart->int_rx;    RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);    while (uart->uart_device->ustat & RT_SERIAL_EVENT_RX_IND)    {        level = rt_hw_interrupt_disable();                        int_rx->rx_buffer[int_rx->save_index] = (uart->uart_device->urxh & 0xff);        int_rx->save_index ++;        if(int_rx->save_index >= UART_RX_BUFFER_SIZE)            int_rx->save_index = 0;        // if the next position is read index, discard this 'read char'        if(int_rx->save_index == int_rx->read_index)        {            int_rx->read_index ++;            if(int_rx->read_index >= UART_RX_BUFFER_SIZE)                int_rx->read_index = 0;        }        rt_hw_interrupt_enable(level);    }    // 接收回调函数    if(device->rx_indicate != RT_NULL)    {        rt_size_t rx_length;        level = rt_hw_interrupt_disable();        // get rx length        rx_length = int_rx->read_index > int_rx->save_index ?            UART_RX_BUFFER_SIZE - int_rx->read_index + int_rx->save_index :            int_rx->save_index - int_rx->read_index;        rt_hw_interrupt_enable(level);        device->rx_indicate(device, rx_length);    }}// This function will handle serial (参考board.c)static void rt_uart_handler(int vector, int event){    INTSUBMSK |= (BIT_SUB_RXD0);    rt_hw_uart_isr(myUart0_device);    SUBSRCPND |= BIT_SUB_RXD0;    // Unmask sub interrupt (RXD0)     INTSUBMSK  &=~(BIT_SUB_RXD0);}void rt_hw_uart_init(void){    // TX0 GPH2    // RX0 GPH3    int i;    // UART0 port configure     GPHCON |= 0xAA;    // PULLUP is disable     GPHUP |= 0xF;    // uart FIFO控制寄存器 Disable[0]=0     myUart0.uart_device->ufcon = 0x0;    // uart 模式控制寄存器    myUart0.uart_device->umcon = 0x0;    // uart line控制寄存器  8 bit, 1 stop    myUart0.uart_device->ulcon = 0x3;    // uart控制寄存器    // 中断或轮询模式发送[3:2]=01,中断或轮询模式接收[1:0]=01    myUart0.uart_device->ucon = 0x245;    // Set uart0 bps     myUart0.uart_device->ubrd = (rt_int32_t)(PCLK / (baudrate * 16)) - 1;    // output PCLK to UART0/1, PWMTIMER     CLKCON |= 0x0D00;    for (i = 0; i < 100; i++);    // install uart0 isr     INTSUBMSK &= ~(BIT_SUB_RXD0);    rt_hw_interrupt_install(INTUART0, rt_uart_handler, RT_NULL, "UART0");    rt_hw_interrupt_umask(INTUART0);}

使用时:

在rt_application_init(void)函数中注册和初始化:

rt_hw_uart_register(myUart0_device, "myUart0",        RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,        &myUart0);rt_hw_uart_init();

然后在自己的线程中使用,比如:

// lcd_td35 测试void rt_lcd_thread_entry(void *parameter){    struct RTC_Date getDate;    unsigned char rtcBuffer[20];    unsigned char rx[50] = {
'\0'}; unsigned char *rxBuffer = &rx[0]; Lcd_TD35_Init(); myUart0_device = rt_device_find("myUart0"); if (myUart0_device != RT_NULL) { // 初始化设备 rt_device_init(myUart0_device); // 打开设备 rt_device_open(myUart0_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM); } rt_device_write(myUart0_device, 0, "Hello World !\0", 15); while(1) { Lcd_ClearScr(0); RTC_Time_Get(&getDate,rtcBuffer); Draw_String(0, 0, 200, 100, 0xf800, 12, 1, rtcBuffer); Draw_String(150, 0, 200, 100, 0xf800, 12, 1, "by Huangtao"); rt_device_read(myUart0_device, 0, rxBuffer, 10); Draw_String(0, 200, 200, 100, 0xf800, 12, 1, rxBuffer); rt_device_write(myUart0_device, 0, rxBuffer, 10); rt_thread_delay(10); }}

 

转载于:https://www.cnblogs.com/ht-beyond/p/5061923.html

你可能感兴趣的文章