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

📄 uart.c

📁 新一代基于事件的嵌入式操作系统dyos在三星的s3c44b0的arm芯片上的完整移植代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    rx = tg_uart1_CB.my_reg->UFSTAT;
    revs = rx & 0xf;
    for(num = 0; num < revs; num++)
    //fifo缓冲区有数据,直到处理完成
        ch[num] = tg_uart1_CB.my_reg->URXH;
    dev_write(pg_uart1_rhdl,(ptu32_t)ch,0,revs);
    if( rx & cn_rx_over)
    {
        tg_uart1_CB.my_reg->UFCON |= cn_rx_fifo_reset;
        y_event_pop(u16g_evtt_uart1_error,enum_recv_fifo_over,0,0);
    }
    return 0;
}

//----uart0发送中断------------------------------------------------------------
//功能: 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中.
//      2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件.
//      3.发送串口接收事件.两个事件都是状态量事件
//参数: 中断函数没有参数.
//返回: 中断函数没有返回值.
//备注: 如果是485且需要软件控制rts,则fifo触发level必须为0,否则不能得到
//      completed状态
//-----------------------------------------------------------------------------
uint32_t uart0_txint(ufast_t uart_int_line)
{
    uint16_t trans,num;
    uint16_t tx;
    uint8_t ch[16];
    tx = tg_uart0_CB.my_reg->UFSTAT;
    trans = 16-((tx>>4) & 0xf);
    trans = dev_read(pg_uart0_rhdl,0,(ptu32_t)ch,trans);
    for(num = 0; num < trans; num++)
    {
        tg_uart0_CB.my_reg->UTXH = ch[num];
    }
    return 0;
}

//----uart1发送中断------------------------------------------------------------
//功能: 1.检查接收fifo中的数据量.把数据从接收寄存器全部copy到物理层缓冲区中.
//      2.如果物理层缓冲区满.置串口控制块状态字的溢出位,并发出uart错误事件.
//      3.发送串口接收事件.两个事件都是状态量事件
//参数: 中断函数没有参数.
//返回: 中断函数没有返回值.
//备注: 如果是485且需要软件控制rts,则fifo触发level必须为0,否则不能得到
//      completed状态
//-----------------------------------------------------------------------------
uint32_t uart1_txint(ufast_t uart_int_line)
{
    uint16_t trans,num;
    uint16_t tx;
    uint8_t ch[16];
    tx = tg_uart1_CB.my_reg->UFSTAT;
    trans = 16-((tx>>4) & 0xf);
    trans = dev_read(pg_uart1_rhdl,0,(ptu32_t)ch,trans);
    for(num = 0; num < trans; num++)
    {
        tg_uart1_CB.my_reg->UTXH = ch[num];
    }
    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)
        y_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)
    {
        //如果不登记右手写事件,就只能查询方式从设备读取数据了。
        y_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)
    {
        int_save_line(uart_port->tx_int_line);
        result = ring_write(&uart_port->send_ring_buf,
                            (uint8_t*)src_buf+completed,len-completed);
        int_restore_line(uart_port->tx_int_line);
        y_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;
    int_save_line(uart_port->rx_int_line);
    result = ring_read(&uart_port->recv_ring_buf,(uint8_t*)des_buf,len);
    int_restore_line(uart_port->rx_int_line);
    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((enum uart_ctrl_no)cmd)
    {
        case enum_uart_connect_recv_evtt:
            uart_port->evtt_right_write = (uint16_t)data1;
            break;
        case enum_uart_disconnect_recv_evtt:
            uart_port->evtt_right_write = cn_invalid_evtt_id;
            break;
        case enum_uart_connect_send_evtt:
            uart_port->evtt_left_write = (uint16_t)data1;
            break;
        case enum_uart_disconnect_send_evtt:
            uart_port->evtt_left_write = cn_invalid_evtt_id;
            break;
        case enum_uart_start:
            int_enable_line(uart_port->tx_int_line);
            int_enable_line(uart_port->rx_int_line);
            break;
        case enum_uart_stop:
            int_disable_line(uart_port->tx_int_line);
            int_disable_line(uart_port->rx_int_line);
            break;
        case enum_uart_set_speed:  //设置Baud
            if(uart_port->baud !=data1)
            {
                uart_port->baud = data1;
                uart_port->my_reg->UBRDIV = ((cn_mclk<<2)/data1 -32)>>6;
//                pg_uart1_reg->UBRDIV =((cn_mclk<<2)/data -32)>>6;
            }
            break;
        case enum_uart_send_data:     //启动发送
        //用IO控制半双工通信的发送使能的话,在此转换收发.
            break;
        case enum_uart_recv_data:     //启动接收
        //用IO控制半双工通信的发送使能的话,在此转换收发.
            break;
        case enum_uart_completed_send:
        //用IO控制半双工通信的发送使能的话,在此转换收发,注意要查询UTRSTAT寄存器
        //的Transmit shifter empty位判断是否已经完成.
            break;
        case enum_uart_rx_pause:      //暂停接收
            int_disable_line(uart_port->rx_int_line);
            break;
        case enum_uart_rx_resume:      //恢复接收
            int_enable_line(uart_port->rx_int_line);
            break;
        case enum_uart_recv_soft_level:    //设置接收软件缓冲区触发水平
            uart_port->recv_trigger_level = (uint16_t)data1;
            break;
        case enum_uart_send_soft_level:    //设置接收软件缓冲区触发水平
            uart_port->send_trigger_level = (uint16_t)data1;
            break;
        case enum_uart_overtime:   //data1为毫秒数
            uart_port->timeout = (data1 + cn_tick_ms-1)/cn_tick_ms;
            break;
        case enum_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 enum_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;

    while(1)
    {
        ser_dev = (struct  pan_device *)my_event->parameter0;
        uart_port = (struct uart_UCB*)ser_dev->private_tag;
        if( uart_tx_fifo_empty(uart_port->my_reg))
            int_tap_line(uart_port->tx_int_line);
        //等待自身类型的事件再次发生,由于本类型事件已经被设置成mark事件,且事件
        //服务函数中一直不调用y_clear_mark,因此新弹出的事件只会触发本事件继续执
        //行。新事件在uart_left_write函数中弹出。
        y_evtt_pop_sync(pg_event_running->evtt_id,1,cn_timeout_forever);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -