参照模板自己写了一遍,期间出现很多问题。比如定义全局uart0设备指针后未初始化,导致RT_ASSERT(device != RT_NULL)执行,使设备注册时死机。
初始化函数没写对,也导致了程序崩溃。
// uart.h // 2015.12.18 by Huangtao #ifndef __UART_H__ #define __UART_H__ #include <rtthread.h> #include <rthw.h> #include <rtthread.h> #include <s3c24x0.h> #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 64 typedef 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 interrupt void 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); } }