//---------------------------------------------------- //Copyright (C), 2004-2009, lst. //版权所有 (C), 2004-2009, lst. //所属模块: uart驱动程序 //作者:lst //版本:V1.0.0 //文件描述: 驱动44b0的uart //其他说明: //修订历史: //1. 日期:2009-03-10 // 作者:lst // 新版本号:1.0.0 // 修改说明: 移植字44b0的1.0.1版 //------------------------------------------------------ #include <string.h> #include "inc_os.h" #include "sysctl.h" #include "uart.h" #include "gpio.h" static struct dev_handle *pg_uart0_rhdl; static struct dev_handle *pg_uart1_rhdl; static struct dev_handle *pg_uart2_rhdl; static struct dev_handle *pg_uart3_rhdl; static struct uart_UCB tg_uart0_CB,tg_uart1_CB,tg_uart2_CB,tg_uart3_CB; uint16_t u16g_evtt_uart0_error; uint16_t u16g_evtt_uart1_error; uint16_t u16g_evtt_uart2_error; uint16_t u16g_evtt_uart3_error; uint8_t uart0_ptcl_send_buf[uart0_buf_len]; uint8_t uart1_ptcl_send_buf[uart1_buf_len]; uint8_t uart2_ptcl_send_buf[uart2_buf_len]; uint8_t uart3_ptcl_send_buf[uart3_buf_len]; uint8_t uart0_ptcl_recv_buf[uart0_buf_len]; uint8_t uart1_ptcl_recv_buf[uart1_buf_len]; uint8_t uart2_ptcl_recv_buf[uart2_buf_len]; uint8_t uart3_ptcl_recv_buf[uart3_buf_len]; static const uint32_t u32_SlotTable[16] = {0x0000, 0x0080, 0x0808, 0x0888, 0x2222, 0x4924, 0x4a52, 0x54aa, 0x5555, 0xd555, 0xd5d5, 0xddd5, 0xdddd, 0xdfdd, 0xdfdf, 0xffdf}; //----使能uart发送中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数使能发送中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_tx_int_enable(struct uart_UCB *uart) { uart->my_reg->UINTM &= ~cn_uartint_msk_tx; } //----禁止uart发送中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数禁止发送中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_tx_int_disable(struct uart_UCB *uart) { uart->my_reg->UINTM |= cn_uartint_msk_tx; } //----使能uart接收中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数使能接收中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_rx_int_enable(struct uart_UCB *uart) { uart->my_reg->UINTM &= ~cn_uartint_msk_rx; } //----禁止uart接收中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数禁止接收中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_rx_int_disable(struct uart_UCB *uart) { uart->my_reg->UINTM |= cn_uartint_msk_rx; } //----使能uart error中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数使能error中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_error_int_enable(struct uart_UCB *uart) { uart->my_reg->UINTM &= ~cn_uartint_msk_error; } //----禁止uart error中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数禁止error中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_error_int_disable(struct uart_UCB *uart) { uart->my_reg->UINTM |= cn_uartint_msk_error; } //----使能uart modem中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数使能modem中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_modem_int_enable(struct uart_UCB *uart) { uart->my_reg->UINTM &= ~cn_uartint_msk_modem; } //----使能uart modem中断--------------------------------------------------------- //功能: 6410中,uart中断可能被收、发、err、modem四个源触发,本函数禁止modem中断 //参数: 串口控制块指针 //返回: 无 //----------------------------------------------------------------------------- void __uart_modem_int_disable(struct uart_UCB *uart) { uart->my_reg->UINTM |= cn_uartint_msk_modem; } //----检查串口发送缓冲区是否满------------------------------------------------- //功能: 检查发送fifo缓冲区的状态,如果fifo满就返回true //参数:无。 //返回: true = 缓冲区满,false = 非满 //----------------------------------------------------------------------------- bool_t uart_tx_fifo_full(struct uart_reg *uart_reg) { return (uart_reg->UFSTAT &0x4000); } //----检查串口发送fifo是否空--------------------------------------------------- //功能: 检查发送fifo缓冲区的状态,如果fifo空就返回true //参数:无。 //返回: true = 缓冲区空,false = 非空 //----------------------------------------------------------------------------- bool_t uart_tx_fifo_empty(struct uart_reg *uart_reg) { return (0==(uart_reg->UFSTAT &0x3f00)); } //----检查串口发送寄存器是否空------------------------------------------------- //功能: 检查发送寄存器的状态,如果空就返回true //参数:无。 //返回: true = 缓冲区空,false = 非空 //----------------------------------------------------------------------------- bool_t uart_tx_tran_empty(struct uart_reg *uart_reg) { return (0!=(uart_reg->UTRSTAT & 0x04)); } //----初始化uart0模块---------------------------------------------------------- //功能:初始化uart0模块 //参数:模块初始化函数没有参数 //返回:true = 成功初始化,false = 初始化失败 //----------------------------------------------------------------------------- bool_t module_init_uart0(void) { struct semaphore_LCB *left_semp,*right_semp; struct pan_device *uart_dev; uint16_t uart_send_evtt; uint32_t temp; //保护缓冲区的信号量,使缓冲区中数据量为0时阻塞写入线程,读取线程使缓冲区中 //数据降至trigger_level以下时释放信号量,使写入线程解除阻塞 tg_uart0_CB.send_buf_semp = semp_create(1,0,"uart0 tx buf"); if(tg_uart0_CB.send_buf_semp == NULL) goto exit_from_left_buf_semp; tg_uart0_CB.recv_buf_semp = semp_create(1,0,"uart0 rx buf"); if(tg_uart0_CB.recv_buf_semp == NULL) goto exit_from_right_buf_semp; //分别创建左手和右手访问uart0设备的信号量,第一个参数为1表示串口是独占访问 //的,第二个参数1表示初始状态有一盏信号灯点亮。左手由应用程序使用,右手由硬 //件操作函数使用。 left_semp = semp_create(1,1,"uart0 device left"); if(left_semp == NULL) goto exit_from_left_semp; right_semp = semp_create(1,1,"uart0 device right"); if(right_semp == NULL) goto exit_from_right_semp; //初始化IO端口位uart功能 //Ports : GPA10 GPA9 GPA8 GPA7 GPA6 GPA5 GPA4 GPA3 GPA2 GPA1 GPA0 //Signal : xx xx xx xx xx xx xx xx xx TXD0 RXD0 //Binary : xx xx xx xx xx xx xx xx xx 0010 0010 temp = pg_gpio_reg->GPACON; temp &= ~0xff; temp |= 0x22; pg_gpio_reg->GPACON = temp; pg_gpio_reg->GPAUP &= ~0xf; // The pull u/d function is disabled GPA[1:0] pg_gpio_reg->GPACONSLP |= 0xf; // keep GPA[1:0] Previous state when sleep pg_gpio_reg->GPAUPSLP &= ~0xf; // disabled pull u/d GPA[1:0] when sleep //select mclk as clk source of uartclk ,但不知这个时钟是用来干什么的,肯定 //不是用来产生baud,手册也没讲 pg_syscon_reg->CLK_SRC |= 0x2000; temp = pg_syscon_reg->CLK_DIV2; temp &= 0xfff0ffff; temp |= 0x00010000; pg_syscon_reg->CLK_DIV2 = temp; //uartclk = mclk/2 //初始化uart硬件控制数据结构 tg_uart0_CB.my_reg = (struct uart_reg *)0x7f005000; tg_uart0_CB.my_reg->ULCON = 0x3; tg_uart0_CB.my_reg->UCON = 0x8c5; tg_uart0_CB.my_reg->UFCON = 0x57; //bit0=1使能fifo. tg_uart0_CB.my_reg->UMCON = 0x0; tg_uart0_CB.my_reg->UBRDIV = cn_pclk/(115200*16) -1; temp = cn_pclk%(115200*16)/115200; tg_uart0_CB.my_reg->UDIVSLOT = u32_SlotTable[temp]; //精确微调baud temp = tg_uart0_CB.my_reg->UERSTAT; //读一下清除错误状态 tg_uart0_CB.baud = 115200; //初始化通用串口数据结构 tg_uart0_CB.recv_trigger_level = 0; //缓冲接收触发水平为0 tg_uart0_CB.send_trigger_level = uart0_buf_len>>4; //缓冲发送触发水平为1/16 tg_uart0_CB.timeout = 500; //超时时间=500 tg_uart0_CB.serial_no = 0; //串口号是0 ring_init( &tg_uart0_CB.send_ring_buf, uart0_ptcl_send_buf, uart0_buf_len); ring_init( &tg_uart0_CB.recv_ring_buf, uart0_ptcl_recv_buf, uart0_buf_len); tg_uart0_CB.status = cn_ser_rxbuf_empty; //以下建立uart0设备 uart_dev = dev_add_root_device("uart0", right_semp,left_semp, (dev_write_func) uart_right_write, (dev_read_func ) uart_right_read, (dev_ctrl_func ) uart_ctrl, (dev_write_func ) uart_left_write, (dev_read_func ) uart_left_read, (dev_ctrl_func ) uart_ctrl ); //"uart0"是一个根设备 if(uart_dev == NULL) goto exit_from_add_device; //tg_serial_uart0是uart0设备的私有数据 uart_dev->private_tag = (ptu32_t)(&tg_uart0_CB); pg_uart0_rhdl = dev_open_right("uart0",0); //打开右手句柄 u16g_evtt_uart0_error = djy_evtt_regist( true,false,110,10,uart_error_service,1024,NULL); if(u16g_evtt_uart0_error == cn_invalid_evtt_id) goto exit_from_error_evtt; uart_send_evtt = djy_evtt_regist(true,false,cn_prio_real, 1,uart_send_service,20,NULL); if(uart_send_evtt == cn_invalid_evtt_id) goto exit_from_send_evtt; dev_ctrl(pg_uart0_rhdl,cn_uart_connect_send_evtt,uart_send_evtt,0); int_isr_connect(cn_int_line_uart0,uart0_int); int_setto_asyn_signal(cn_int_line_uart0); tg_uart0_CB.my_reg->UINTP = cn_uartint_msk_error + cn_uartint_msk_modem +cn_uartint_msk_rx + cn_uartint_msk_tx; int_echo_line(cn_int_line_uart0); //清掉初始化产生的发送fifo空的中断 int_restore_asyn_line(cn_int_line_uart0); return true; exit_from_send_evtt: djy_evtt_unregist(u16g_evtt_uart0_error); exit_from_error_evtt: dev_delete_device(uart_dev); exit_from_add_device: semp_delete(right_semp); exit_from_right_semp: semp_delete(left_semp); exit_from_left_semp: semp_delete(tg_uart0_CB.recv_buf_semp); exit_from_right_buf_semp: semp_delete(tg_uart0_CB.send_buf_semp); exit_from_left_buf_semp: return false; } bool_t module_init_uart1(void) { struct semaphore_LCB *left_semp,*right_semp; struct pan_device *uart_dev; uint16_t uart_send_evtt; uint32_t temp; tg_uart1_CB.send_buf_semp = semp_create(1,0,"uart1 tx buf"); if(tg_uart1_CB.send_buf_semp == NULL) goto exit_from_left_buf_semp; tg_uart1_CB.recv_buf_semp = semp_create(1,0,"uart1 rx buf"); if(tg_uart1_CB.recv_buf_semp == NULL) goto exit_from_right_buf_semp; left_semp = semp_create(1,1,"uart1 device left"); if(left_semp == NULL) goto exit_from_left_semp; right_semp = semp_create(1,1,"uart1 device right"); if(right_semp == NULL) goto exit_from_right_semp; //初始化IO端口位uart功能 //Ports : GPA10 GPA9 GPA8 GPA7 GPA6 GPA5 GPA4 GPA3 GPA2 GPA1 GPA0 //Signal : xx xx xx xx xx TXD1 RXD1 xx xx xx xx //Binary : xx xx xx xx xx 0010 0010 xx xx xx xx temp = pg_gpio_reg->GPACON; temp &= ~0xff00; temp |= 0x2200; pg_gpio_reg->GPACON = temp; pg_gpio_reg->GPAUP &= ~0xf00; // The pull u/d function is disabled GPA[1:0] pg_gpio_reg->GPACONSLP |= 0xf00; // keep GPA[1:0] Previous state when sleep pg_gpio_reg->GPAUPSLP &= ~0xf00; // disabled pull u/d GPA[1:0] when sleep //select mclk as clk source of uartclk ,但不知这个时钟是用来干什么的,肯定 //不是用来产生baud,手册也没讲 pg_syscon_reg->CLK_SRC |= 0x2000; temp = pg_syscon_reg->CLK_DIV2; temp &= 0xfff0ffff; temp |= 0x00010000; pg_syscon_reg->CLK_DIV2 = temp; //uartclk = mclk/2 //初始化uart硬件控制数据结构 tg_uart1_CB.my_reg = (struct uart_reg *)0x7f005000; tg_uart1_CB.my_reg->ULCON = 0x3; tg_uart1_CB.my_reg->UCON = 0x8c5; tg_uart1_CB.my_reg->UFCON = 0x57; //bit0=1使能fifo. tg_uart1_CB.my_reg->UMCON = 0x0; tg_uart1_CB.my_reg->UBRDIV = cn_pclk/(115200*16) -1; temp = cn_pclk%(115200*16)/115200; tg_uart1_CB.my_reg->UDIVSLOT = u32_SlotTable[temp]; //精确微调baud temp = tg_uart1_CB.my_reg->UERSTAT; //读一下清除错误状态 tg_uart1_CB.baud = 115200; //初始化通用串口数据结构 tg_uart1_CB.recv_trigger_level = 0; //缓冲接收触发水平为0 tg_uart1_CB.send_trigger_level = uart1_buf_len>>4; //缓冲发送触发水平为1/16 tg_uart1_CB.timeout = 500; //超时时间=500 tg_uart1_CB.serial_no = 1; //串口号是1 ring_init( &tg_uart1_CB.send_ring_buf, uart1_ptcl_send_buf, uart1_buf_len); ring_init( &tg_uart1_CB.recv_ring_buf, uart1_ptcl_recv_buf, uart1_buf_len); tg_uart1_CB.status = cn_ser_rxbuf_empty; //以下建立uart1设备 uart_dev = dev_add_root_device("uart1", right_semp,left_semp, (dev_write_func) uart_right_write, (dev_read_func ) uart_right_read, (dev_ctrl_func ) uart_ctrl, (dev_write_func ) uart_left_write, (dev_read_func ) uart_left_read, (dev_ctrl_func ) uart_ctrl ); //"uart1"是一个根设备 if(uart_dev == NULL) goto exit_from_add_device; //tg_serial_uart1是uart1设备的私有数据 uart_dev->private_tag = (ptu32_t)(&tg_uart1_CB); pg_uart1_rhdl = dev_open_right("uart1",0); //打开右手句柄 u16g_evtt_uart1_error = djy_evtt_regist( true,false,110,10,uart_error_service,1024,NULL); if(u16g_evtt_uart1_error == cn_invalid_evtt_id) goto exit_from_error_evtt; uart_send_evtt = djy_evtt_regist(true,false,cn_prio_real, 1,uart_send_service,20,NULL); if(uart_send_evtt == cn_invalid_evtt_id) goto exit_from_send_evtt; dev_ctrl(pg_uart1_rhdl,cn_uart_connect_send_evtt,uart_send_evtt,0); int_isr_connect(cn_int_line_uart1,uart1_int); int_setto_asyn_signal(cn_int_line_uart1); tg_uart1_CB.my_reg->UINTP = cn_uartint_msk_error + cn_uartint_msk_modem +cn_uartint_msk_rx + cn_uartint_msk_tx; int_echo_line(cn_int_line_uart1); //清掉初始化产生的发送fifo空的中断 int_restore_asyn_line(cn_int_line_uart1); return true; exit_from_send_evtt: djy_evtt_unregist(u16g_evtt_uart1_error); exit_from_error_evtt: dev_delete_device(uart_dev); exit_from_add_device: semp_delete(right_semp); exit_from_right_semp: semp_delete(left_semp); exit_from_left_semp: semp_delete(tg_uart1_CB.recv_buf_semp); exit_from_right_buf_semp: semp_delete(tg_uart1_CB.send_buf_semp); exit_from_left_buf_semp: return false; } bool_t module_init_uart2(void) { struct semaphore_LCB *left_semp,*right_semp; struct pan_device *uart_dev; uint16_t uart_send_evtt; uint32_t temp; tg_uart2_CB.send_buf_semp = semp_create(1,0,"uart2 tx buf"); if(tg_uart2_CB.send_buf_semp == NULL) goto exit_from_left_buf_semp; tg_uart2_CB.recv_buf_semp = semp_create(1,0,"uart2 rx buf"); if(tg_uart2_CB.recv_buf_semp == NULL) goto exit_from_right_buf_semp; left_semp = semp_create(1,1,"uart2 device left"); if(left_semp == NULL) goto exit_from_left_semp; right_semp = semp_create(1,1,"uart2 device right"); if(right_semp == NULL) goto exit_from_right_semp; //初始化IO端口位uart功能 //Ports : GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0 //Signal : xx xx xx xx xx xx xx xx xx TXD2 RXD2 //Binary : xx xx xx xx xx xx xx xx xx 0010 0010 temp = pg_gpio_reg->GPBCON; temp &= ~0xff; temp |= 0x22; pg_gpio_reg->GPBCON = temp; pg_gpio_reg->GPBUP &= ~0xf; // The pull u/d function is disabled GPB[1:0] pg_gpio_reg->GPBCONSLP |= 0xf; // keep GPB[1:0] Previous state when sleep pg_gpio_reg->GPBUPSLP &= ~0xf; // disabled pull u/d GPB[1:0] when sleep //select mclk as clk source of uartclk ,但不知这个时钟是用来干什么的,肯定 //不是用来产生baud,手册也没讲 pg_syscon_reg->CLK_SRC |= 0x2000; temp = pg_syscon_reg->CLK_DIV2; temp &= 0xfff0ffff; temp |= 0x00010000; pg_syscon_reg->CLK_DIV2 = temp; //uartclk = mclk/2 //初始化uart硬件控制数据结构 tg_uart2_CB.my_reg = (struct uart_reg *)0x7f005000; tg_uart2_CB.my_reg->ULCON = 0x3; tg_uart2_CB.my_reg->UCON = 0x8c5; tg_uart2_CB.my_reg->UFCON = 0x57; //bit0=1使能fifo. tg_uart2_CB.my_reg->UMCON = 0x0; tg_uart2_CB.my_reg->UBRDIV = cn_pclk/(115200*16) -1; temp = cn_pclk%(115200*16)/115200; tg_uart1_CB.my_reg->UDIVSLOT = u32_SlotTable[temp]; //精确微调baud temp = tg_uart1_CB.my_reg->UERSTAT; //读一下清除错误状态 tg_uart1_CB.baud = 115200; //初始化通用串口数据结构 tg_uart2_CB.recv_trigger_level = 0; //缓冲接收触发水平为0 tg_uart2_CB.send_trigger_level = uart2_buf_len>>4; //缓冲发送触发水平为1/16 tg_uart2_CB.timeout = 500; //超时时间=500 tg_uart2_CB.serial_no = 2; //串口号是2 ring_init( &tg_uart2_CB.send_ring_buf, uart2_ptcl_send_buf, uart2_buf_len); ring_init( &tg_uart2_CB.recv_ring_buf, uart2_ptcl_recv_buf, uart2_buf_len); tg_uart2_CB.status = cn_ser_rxbuf_empty; //以下建立uart2设备 uart_dev = dev_add_root_device("uart2", right_semp,left_semp, (dev_write_func) uart_right_write, (dev_read_func ) uart_right_read, (dev_ctrl_func ) uart_ctrl, (dev_write_func ) uart_left_write, (dev_read_func ) uart_left_read, (dev_ctrl_func ) uart_ctrl ); //"uart2"是一个根设备 if(uart_dev == NULL) goto exit_from_add_device; //tg_serial_uart2是uart2设备的私有数据 uart_dev->private_tag = (ptu32_t)(&tg_uart2_CB); pg_uart2_rhdl = dev_open_right("uart2",0); //打开右手句柄 u16g_evtt_uart2_error = djy_evtt_regist( true,false,110,10,uart_error_service,1024,NULL); if(u16g_evtt_uart2_error == cn_invalid_evtt_id) goto exit_from_error_evtt; uart_send_evtt = djy_evtt_regist(true,false,cn_prio_real, 1,uart_send_service,20,NULL); if(uart_send_evtt == cn_invalid_evtt_id) goto exit_from_send_evtt; dev_ctrl(pg_uart2_rhdl,cn_uart_connect_send_evtt,uart_send_evtt,0); int_isr_connect(cn_int_line_uart2,uart2_int); int_setto_asyn_signal(cn_int_line_uart2); tg_uart2_CB.my_reg->UINTP = cn_uartint_msk_error + cn_uartint_msk_modem +cn_uartint_msk_rx + cn_uartint_msk_tx; int_echo_line(cn_int_line_uart2); //清掉初始化产生的发送fifo空的中断 int_restore_asyn_line(cn_int_line_uart2); return true; exit_from_send_evtt: djy_evtt_unregist(u16g_evtt_uart2_error); exit_from_error_evtt: dev_delete_device(uart_dev); exit_from_add_device: semp_delete(right_semp); exit_from_right_semp: semp_delete(left_semp); exit_from_left_semp: semp_delete(tg_uart2_CB.recv_buf_semp); exit_from_right_buf_semp: semp_delete(tg_uart2_CB.send_buf_semp); exit_from_left_buf_semp: return false; } bool_t module_init_uart3(void) { struct semaphore_LCB *left_semp,*right_semp; struct pan_device *uart_dev; uint16_t uart_send_evtt; uint32_t temp; tg_uart3_CB.send_buf_semp = semp_create(1,0,"uart3 tx buf"); if(tg_uart3_CB.send_buf_semp == NULL) goto exit_from_left_buf_semp; tg_uart3_CB.recv_buf_semp = semp_create(1,0,"uart3 rx buf"); if(tg_uart3_CB.recv_buf_semp == NULL) goto exit_from_right_buf_semp; left_semp = semp_create(1,1,"uart3 device left"); if(left_semp == NULL) goto exit_from_left_semp; right_semp = semp_create(1,1,"uart3 device right"); if(right_semp == NULL) goto exit_from_right_semp; //初始化IO端口位uart功能 //Ports : GPB10 GPB9 GPB8 GPB7 GPB6 GPB5 GPB4 GPB3 GPB2 GPB1 GPB0 //Signal : xx xx xx xx xx xx xx TXD3 RXD3 xx xx //Binary : xx xx xx xx xx xx xx 0010 0010 xx xx temp = pg_gpio_reg->GPBCON; temp &= ~0xff00; temp |= 0x2200; pg_gpio_reg->GPBCON = temp; pg_gpio_reg->GPBUP &= ~0xf0; // The pull u/d function is disabled GPB[1:0] pg_gpio_reg->GPBCONSLP |= 0xf0; // keep GPB[1:0] Previous state when sleep pg_gpio_reg->GPBUPSLP &= ~0xf0; // disabled pull u/d GPB[1:0] when sleep //select mclk as clk source of uartclk ,但不知这个时钟是用来干什么的,肯定 //不是用来产生baud,手册也没讲 pg_syscon_reg->CLK_SRC |= 0x2000; temp = pg_syscon_reg->CLK_DIV2; temp &= 0xfff0ffff; temp |= 0x00010000; pg_syscon_reg->CLK_DIV2 = temp; //uartclk = mclk/2 //初始化uart硬件控制数据结构 tg_uart3_CB.my_reg = (struct uart_reg *)0x7f005000; tg_uart3_CB.my_reg->ULCON = 0x3; tg_uart3_CB.my_reg->UCON = 0x8c5; tg_uart3_CB.my_reg->UFCON = 0x57; //bit0=1使能fifo. tg_uart3_CB.my_reg->UMCON = 0x0; tg_uart3_CB.my_reg->UBRDIV = cn_pclk/(115200*16) -1; temp = cn_pclk%(115200*16)/115200; tg_uart1_CB.my_reg->UDIVSLOT = u32_SlotTable[temp]; //精确微调baud temp = tg_uart1_CB.my_reg->UERSTAT; //读一下清除错误状态 tg_uart1_CB.baud = 115200; //初始化通用串口数据结构 tg_uart3_CB.recv_trigger_level = 0; //缓冲接收触发水平为0 tg_uart3_CB.send_trigger_level = uart3_buf_len>>4; //缓冲发送触发水平为1/16 tg_uart3_CB.timeout = 500; //超时时间=500 tg_uart3_CB.serial_no = 2; //串口号是2 ring_init( &tg_uart3_CB.send_ring_buf, uart3_ptcl_send_buf, uart3_buf_len); ring_init( &tg_uart3_CB.recv_ring_buf, uart3_ptcl_recv_buf, uart3_buf_len); tg_uart3_CB.status = cn_ser_rxbuf_empty; //以下建立uart3设备 uart_dev = dev_add_root_device("uart3", right_semp,left_semp, (dev_write_func) uart_right_write, (dev_read_func ) uart_right_read, (dev_ctrl_func ) uart_ctrl, (dev_write_func ) uart_left_write, (dev_read_func ) uart_left_read, (dev_ctrl_func ) uart_ctrl ); //"uart3"是一个根设备 if(uart_dev == NULL) goto exit_from_add_device; //tg_serial_uart3是uart3设备的私有数据 uart_dev->private_tag = (ptu32_t)(&tg_uart3_CB); pg_uart3_rhdl = dev_open_right("uart3",0); //打开右手句柄 u16g_evtt_uart3_error = djy_evtt_regist( true,false,110,10,uart_error_service,1024,NULL); if(u16g_evtt_uart3_error == cn_invalid_evtt_id) goto exit_from_error_evtt; uart_send_evtt = djy_evtt_regist(true,false,cn_prio_real, 1,uart_send_service,20,NULL); if(uart_send_evtt == cn_invalid_evtt_id) goto exit_from_send_evtt; dev_ctrl(pg_uart3_rhdl,cn_uart_connect_send_evtt,uart_send_evtt,0); int_isr_connect(cn_int_line_uart3,uart3_int); int_setto_asyn_signal(cn_int_line_uart3); tg_uart3_CB.my_reg->UINTP = cn_uartint_msk_error + cn_uartint_msk_modem +cn_uartint_msk_rx + cn_uartint_msk_tx; int_echo_line(cn_int_line_uart3); //清掉初始化产生的发送fifo空的中断 int_restore_asyn_line(cn_int_line_uart3); return true; exit_from_send_evtt: djy_evtt_unregist(u16g_evtt_uart3_error); exit_from_error_evtt: dev_delete_device(uart_dev); exit_from_add_device: semp_delete(right_semp); exit_from_right_semp: semp_delete(left_semp); exit_from_left_semp: semp_delete(tg_uart3_CB.recv_buf_semp); exit_from_right_buf_semp: semp_delete(tg_uart3_CB.send_buf_semp); exit_from_left_buf_semp: return false; } void uart_error_service(struct event_script *my_event) { uint32_t temp; djy_clear_mark(); if(my_event->parameter1 == 0) temp = tg_uart0_CB.my_reg->UERSTAT; else if(my_event->parameter1 == 1) temp = tg_uart1_CB.my_reg->UERSTAT; else if(my_event->parameter1 == 2) temp = tg_uart2_CB.my_reg->UERSTAT; else if(my_event->parameter1 == 3) temp = tg_uart3_CB.my_reg->UERSTAT; } //----uart0中断--------------------------------------------------------------- //功能: 如果是接收信号触发的中断: // 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中. // 2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件. // 3.发送串口接收事件.两个事件都是状态量事件 // 如果是发送信号引发的中断: // 1.检查发送fifo有多少空位 // 2.从设备右手接口读出适量数据, // 3.把读出的数据写入发送fifo // 如果是出错信号引发中断:弹出串口出错事件 //参数: 中断函数没有参数. //返回: 中断函数没有返回值. //----------------------------------------------------------------------------- uint32_t uart0_int(ufast_t uart_int_line) { uint32_t recv_trans,num; uint32_t fifo_reg; uint8_t ch[64]; if(tg_uart0_CB.my_reg->UINTP & cn_uartint_msk_rx) { tg_uart0_CB.my_reg->UINTP = cn_uartint_msk_rx; fifo_reg = tg_uart0_CB.my_reg->UFSTAT; recv_trans = fifo_reg & 0x3f; for(num = 0; num < recv_trans; num++) //fifo缓冲区有数据,直到处理完成 ch[num] = tg_uart0_CB.my_reg->URXH; dev_write(pg_uart0_rhdl,(ptu32_t)ch,0,recv_trans); if( fifo_reg & cn_rx_over) { tg_uart0_CB.my_reg->UFCON |= cn_rx_fifo_reset; djy_event_pop(u16g_evtt_uart0_error,enum_recv_fifo_over,0,0); } } if(tg_uart0_CB.my_reg->UINTP & cn_uartint_msk_tx) { tg_uart0_CB.my_reg->UINTP = cn_uartint_msk_tx; fifo_reg = tg_uart0_CB.my_reg->UFSTAT; recv_trans = 64-((fifo_reg>>8) & 0x3f); recv_trans = dev_read(pg_uart0_rhdl,0,(ptu32_t)ch,recv_trans); for(num = 0; num < recv_trans; num++) { tg_uart0_CB.my_reg->UTXH = ch[num]; } } if(tg_uart0_CB.my_reg->UINTP & cn_uartint_msk_error) { tg_uart0_CB.my_reg->UINTP = cn_uartint_msk_error; djy_event_pop(u16g_evtt_uart0_error,0,0,0); } return 0; } //----uart1中断--------------------------------------------------------------- //功能: 如果是接收信号触发的中断: // 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中. // 2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件. // 3.发送串口接收事件.两个事件都是状态量事件 // 如果是发送信号引发的中断: // 1.检查发送fifo有多少空位 // 2.从设备右手接口读出适量数据, // 3.把读出的数据写入发送fifo // 如果是出错信号引发中断:弹出串口出错事件 //参数: 中断函数没有参数. //返回: 中断函数没有返回值. //----------------------------------------------------------------------------- uint32_t uart1_int(ufast_t uart_int_line) { uint32_t recv_trans,num; uint32_t fifo_reg; uint8_t ch[64]; if(tg_uart1_CB.my_reg->UINTP & cn_uartint_msk_rx) { tg_uart1_CB.my_reg->UINTP = cn_uartint_msk_rx; fifo_reg = tg_uart1_CB.my_reg->UFSTAT; recv_trans = fifo_reg & 0x3f; for(num = 0; num < recv_trans; num++) //fifo缓冲区有数据,直到处理完成 ch[num] = tg_uart1_CB.my_reg->URXH; dev_write(pg_uart1_rhdl,(ptu32_t)ch,0,recv_trans); if( fifo_reg & cn_rx_over) { tg_uart1_CB.my_reg->UFCON |= cn_rx_fifo_reset; djy_event_pop(u16g_evtt_uart1_error,enum_recv_fifo_over,1,0); } } if(tg_uart1_CB.my_reg->UINTP & cn_uartint_msk_tx) { tg_uart1_CB.my_reg->UINTP = cn_uartint_msk_tx; fifo_reg = tg_uart1_CB.my_reg->UFSTAT; recv_trans = 64-((fifo_reg>>8) & 0x3f); recv_trans = dev_read(pg_uart1_rhdl,0,(ptu32_t)ch,recv_trans); for(num = 0; num < recv_trans; num++) { tg_uart1_CB.my_reg->UTXH = ch[num]; } } if(tg_uart1_CB.my_reg->UINTP & cn_uartint_msk_error) { tg_uart1_CB.my_reg->UINTP = cn_uartint_msk_error; djy_event_pop(u16g_evtt_uart1_error,0,1,0); } return 0; } //----uart2中断--------------------------------------------------------------- //功能: 如果是接收信号触发的中断: // 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中. // 2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件. // 3.发送串口接收事件.两个事件都是状态量事件 // 如果是发送信号引发的中断: // 1.检查发送fifo有多少空位 // 2.从设备右手接口读出适量数据, // 3.把读出的数据写入发送fifo // 如果是出错信号引发中断:弹出串口出错事件 //参数: 中断函数没有参数. //返回: 中断函数没有返回值. //----------------------------------------------------------------------------- uint32_t uart2_int(ufast_t uart_int_line) { uint32_t recv_trans,num; uint32_t fifo_reg; uint8_t ch[64]; if(tg_uart2_CB.my_reg->UINTP & cn_uartint_msk_rx) { tg_uart2_CB.my_reg->UINTP = cn_uartint_msk_rx; fifo_reg = tg_uart2_CB.my_reg->UFSTAT; recv_trans = fifo_reg & 0x3f; for(num = 0; num < recv_trans; num++) //fifo缓冲区有数据,直到处理完成 ch[num] = tg_uart2_CB.my_reg->URXH; dev_write(pg_uart2_rhdl,(ptu32_t)ch,0,recv_trans); if( fifo_reg & cn_rx_over) { tg_uart2_CB.my_reg->UFCON |= cn_rx_fifo_reset; djy_event_pop(u16g_evtt_uart2_error,enum_recv_fifo_over,2,0); } } if(tg_uart2_CB.my_reg->UINTP & cn_uartint_msk_tx) { tg_uart2_CB.my_reg->UINTP = cn_uartint_msk_tx; fifo_reg = tg_uart2_CB.my_reg->UFSTAT; recv_trans = 64-((fifo_reg>>8) & 0x3f); recv_trans = dev_read(pg_uart2_rhdl,0,(ptu32_t)ch,recv_trans); for(num = 0; num < recv_trans; num++) { tg_uart2_CB.my_reg->UTXH = ch[num]; } } if(tg_uart2_CB.my_reg->UINTP & cn_uartint_msk_error) { tg_uart2_CB.my_reg->UINTP = cn_uartint_msk_error; djy_event_pop(u16g_evtt_uart2_error,0,2,0); } return 0; } //----uart3中断--------------------------------------------------------------- //功能: 如果是接收信号触发的中断: // 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中. // 2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件. // 3.发送串口接收事件.两个事件都是状态量事件 // 如果是发送信号引发的中断: // 1.检查发送fifo有多少空位 // 2.从设备右手接口读出适量数据, // 3.把读出的数据写入发送fifo // 如果是出错信号引发中断:弹出串口出错事件 //参数: 中断函数没有参数. //返回: 中断函数没有返回值. //----------------------------------------------------------------------------- uint32_t uart3_int(ufast_t uart_int_line) { uint32_t recv_trans,num; uint32_t fifo_reg; uint8_t ch[64]; if(tg_uart3_CB.my_reg->UINTP & cn_uartint_msk_rx) { tg_uart3_CB.my_reg->UINTP = cn_uartint_msk_rx; fifo_reg = tg_uart3_CB.my_reg->UFSTAT; recv_trans = fifo_reg & 0x3f; for(num = 0; num < recv_trans; num++) //fifo缓冲区有数据,直到处理完成 ch[num] = tg_uart3_CB.my_reg->URXH; dev_write(pg_uart3_rhdl,(ptu32_t)ch,0,recv_trans); if( fifo_reg & cn_rx_over) { tg_uart3_CB.my_reg->UFCON |= cn_rx_fifo_reset; djy_event_pop(u16g_evtt_uart3_error,enum_recv_fifo_over,2,0); } } if(tg_uart3_CB.my_reg->UINTP & cn_uartint_msk_tx) { tg_uart3_CB.my_reg->UINTP = cn_uartint_msk_tx; fifo_reg = tg_uart3_CB.my_reg->UFSTAT; recv_trans = 64-((fifo_reg>>8) & 0x3f); recv_trans = dev_read(pg_uart3_rhdl,0,(ptu32_t)ch,recv_trans); for(num = 0; num < recv_trans; num++) { tg_uart3_CB.my_reg->UTXH = ch[num]; } } if(tg_uart3_CB.my_reg->UINTP & cn_uartint_msk_error) { tg_uart3_CB.my_reg->UINTP = cn_uartint_msk_error; djy_event_pop(u16g_evtt_uart3_error,0,2,0); } return 0; } //----uart设备右手写函数------------------------------------------------------- //功能: 从右手写入uart设备,由uart设备连接的串口模块调用. // 1.把数据写入串口serial_DCB_t的环形发送缓冲区中. // 2.如果写入设备的数据未达到触发水平,则继续收集数据 // 3.达到出发水平后,按设定的方式把数据传递给上层设备 //参数: uart_rdev,被操作的设备的右手指针. // buf,数据源指针。 // len,数据量(bytes) //返回: 实际写入环形缓冲区的字符数 //----------------------------------------------------------------------------- ptu32_t uart_right_write(struct dev_handle *uart_rdev,ptu32_t buf, ptu32_t res2,ptu32_t len) { struct uart_UCB *uart_port; struct pan_device *uart_dev; uint16_t recv_bytes,valid_bytes; uart_dev = uart_rdev->dev_interfase; uart_port = (struct uart_UCB*)(uart_dev->private_tag); //copy整个硬件缓冲区到协议缓冲区 recv_bytes = ring_write(&uart_port->recv_ring_buf, (uint8_t*)buf,len); if(recv_bytes != len) djy_event_pop(u16g_evtt_uart0_error,enum_recv_buf_over,0,0); valid_bytes = ring_check(&uart_port->recv_ring_buf); if(valid_bytes >= uart_port->recv_trigger_level) { //如果不登记右手写事件,就只能查询方式从设备读取数据了。 djy_event_pop(uart_port->evtt_right_write,(uint32_t)uart_rdev,valid_bytes,0); } return (ptu32_t)recv_bytes; } //----uart设备左手写函数------------------------------------------------------- //功能: 从左手写入uart设备,一般由uart的使用者调用. // 1.把数据写入串口serial_DCB_t的环形发送缓冲区中. // 2.如果串口硬件空闲,便把数据写入硬件发送缓冲区,并启动发送,否则不操作 //参数: uart_ldev,被操作的设备的左手指针. // src_buf,数据源指针 // len,要发送的序列长度 //返回: 实际写入环形缓冲区的字符数 //----------------------------------------------------------------------------- ptu32_t uart_left_write(struct dev_handle *uart_ldev,ptu32_t src_buf, ptu32_t res,ptu32_t len) { uint32_t result; struct uart_UCB *uart_port; struct pan_device *uart_dev; uint32_t completed = 0; uart_dev = uart_ldev->dev_interfase; if(len == 0) return 0; uart_port = (struct uart_UCB*)(uart_dev->private_tag); while(1) { __uart_tx_int_disable(uart_port); result = ring_write(&uart_port->send_ring_buf, (uint8_t*)src_buf+completed,len-completed); __uart_tx_int_enable(uart_port); djy_event_pop(uart_port->evtt_left_write,(uint32_t)uart_dev,0,0); if(result != len-completed) //缓冲区满,没有送出全部数据 { completed += result; semp_pend(uart_port->send_buf_semp,cn_timeout_forever); }else break; } return result; } //----串口设备左手读函数------------------------------------------------------ //功能: 左手读用于上层设备,读取串口接收环形缓冲区的数据 //参数: uart_ldev,被操作的设备的左手指针. // des_buf,读缓冲区 // len,读入长度, //返回: 实际读出长度 //---------------------------------------------------------------------------- ptu32_t uart_left_read(struct dev_handle *uart_ldev,ptu32_t res, ptu32_t des_buf,ptu32_t len) { struct pan_device *uart_dev; struct uart_UCB *uart_port; uint32_t result; uart_dev = uart_ldev->dev_interfase; uart_port = (struct uart_UCB*)uart_dev->private_tag; __uart_rx_int_disable(uart_port); result = ring_read(&uart_port->recv_ring_buf,(uint8_t*)des_buf,len); __uart_rx_int_enable(uart_port); return result; } //----串口设备右手读函数------------------------------------------------------ //功能: 右手读用于硬件,硬件发送服务函数 ser_send_service从串口发送环形缓冲区 // 读取数据到串口硬件缓冲区并启动发送. //参数: uart_rdev,被操作的设备的右手指针. // des_buf,读缓冲区 // len,读入长度, //返回: 实际读出长度 //---------------------------------------------------------------------------- ptu32_t uart_right_read(struct dev_handle *uart_rdev,ptu32_t res1, ptu32_t des_buf,ptu32_t len) { struct pan_device *uart_dev; struct uart_UCB *uart_port; uint32_t result; uart_dev = uart_rdev->dev_interfase; uart_port = (struct uart_UCB*)uart_dev->private_tag; result = (ptu32_t)ring_read(&uart_port->send_ring_buf,(uint8_t *)des_buf,len); if(ring_check(&uart_port->send_ring_buf) <= uart_port->send_trigger_level) semp_post(uart_port->send_buf_semp); return result; } //----串口设备控制函数--------------------------------------------------------- //功能: 串口设备的控制函数 //参数: uart_handle,被操作的串口设备指针. // cmd,操作类型 // data,含义依cmd而定 //返回: 无意义. //----------------------------------------------------------------------------- ptu32_t uart_ctrl(struct dev_handle *uart_handle,uint32_t cmd, uint32_t data1,uint32_t data2) { struct pan_device *uart_dev; struct uart_UCB *uart_port; uart_dev = uart_handle->dev_interfase; uart_port = (struct uart_UCB*)uart_dev->private_tag; switch(cmd) { case cn_uart_connect_recv_evtt: uart_port->evtt_right_write = (uint16_t)data1; break; case cn_uart_disconnect_recv_evtt: uart_port->evtt_right_write = cn_invalid_evtt_id; break; case cn_uart_connect_send_evtt: uart_port->evtt_left_write = (uint16_t)data1; break; case cn_uart_disconnect_send_evtt: uart_port->evtt_left_write = cn_invalid_evtt_id; break; case cn_uart_start: __uart_tx_int_enable(uart_port); __uart_rx_int_enable(uart_port); break; case cn_uart_stop: __uart_tx_int_disable(uart_port); __uart_rx_int_disable(uart_port); break; case cn_uart_set_baud: //设置Baud if(uart_port->baud !=data1) { uart_port->baud = data1; uart_port->my_reg->UBRDIV = ((cn_pclk<<2)/data1 -32)>>6; // pg_uart1_reg->UBRDIV =((cn_pclk<<2)/data -32)>>6; } break; case cn_uart_send_data: //启动发送 //用IO控制半双工通信的发送使能的话,在此转换收发. break; case cn_uart_recv_data: //启动接收 //用IO控制半双工通信的发送使能的话,在此转换收发. break; case cn_uart_completed_send: //用IO控制半双工通信的发送使能的话,在此转换收发,注意要查询UTRSTAT寄存器 //的Transmit shifter empty位判断是否已经完成. break; case cn_uart_rx_pause: //暂停接收 __uart_rx_int_disable(uart_port); break; case cn_uart_rx_resume: //恢复接收 __uart_rx_int_enable(uart_port); break; case cn_uart_recv_soft_level: //设置接收软件缓冲区触发水平 uart_port->recv_trigger_level = (uint16_t)data1; break; case cn_uart_send_soft_level: //设置接收软件缓冲区触发水平 uart_port->send_trigger_level = (uint16_t)data1; break; case cn_uart_overtime: //data1为毫秒数 uart_port->timeout = (data1 + cn_tick_ms-1)/cn_tick_ms; break; case cn_uart_send_hard_level: //设置发送fifo触发水平 { uart_port->my_reg->UFCON &= 0x3f; switch (data1) { case 0: break; case 4: uart_port->my_reg->UFCON |= 0x40; break; case 8: uart_port->my_reg->UFCON |= 0x80; break; case 12: uart_port->my_reg->UFCON |= 0xc0; break; default :break; } break; } case cn_uart_recv_hard_level: //设置接收fifo触发水平 { uart_port->my_reg->UFCON &= 0xcf; switch (data1) { case 0: break; case 4: uart_port->my_reg->UFCON |= 0x10; break; case 8: uart_port->my_reg->UFCON |= 0x20; break; case 12: uart_port->my_reg->UFCON |= 0x30; break; default :break; } break; } default: break; } return 0; } //----串行发送服务------------------------------------------------------------- //功能: 事件服务函数,当串口发送硬件缓冲区空时,就会发送串行发送缓冲区空事件.该 // 事件以struct dev_handle 型指针为参数. //参数: 事件服务函数没有参数. //返回: 事件服务函数可以不返回,即使返回也没有返回值. //----------------------------------------------------------------------------- void uart_send_service(struct event_script *my_event) { struct uart_UCB *uart_port; struct pan_device *ser_dev; struct dev_handle *uart_rhdl; uint8_t ch[64]; ufast_t trans,num; while(1) { ser_dev = (struct pan_device *)my_event->parameter0; uart_port = (struct uart_UCB*)ser_dev->private_tag; if( uart_tx_tran_empty((struct uart_reg*)uart_port->my_reg)) { if(uart_port->serial_no == 0) uart_rhdl = pg_uart0_rhdl; else if(uart_port->serial_no == 1) uart_rhdl = pg_uart1_rhdl; else uart_rhdl = pg_uart2_rhdl; __uart_tx_int_disable(uart_port); trans = dev_read(uart_rhdl,0,(ptu32_t)ch,64); for(num = 0; num < trans; num++) { uart_port->my_reg->UTXH = ch[num]; } __uart_tx_int_enable(uart_port); } //等待自身类型的事件再次发生,由于本类型事件已经被设置成mark事件,且事件 //服务函数中一直不调用y_clear_mark,因此新弹出的事件只会触发本事件继续执 //行。新事件在uart_left_write函数中弹出。 djy_evtt_pop_sync(pg_event_running->evtt_id,1,cn_timeout_forever); } }