📄 uart.c
字号:
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 + -