- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个微 Controller 和一个嵌入式 PC。这两个通过串行连接进行通信,并且都在相互接收和发送数据。两者之间的波特率为38400。微 Controller 和PC具有相同的配置以确保通信(8个数据位,1个停止位,偶校验)。
在微 Controller 开始大约每 10 毫秒发送一次消息之前,通信工作正常。此时,微 Controller 的发送队列已满并溢出。然后他向 PC 发送一条错误消息(这就是我所知道的,微 Controller 的发送队列超限,而不是 PC 的发送队列。
在嵌入式 Linux 版本的 PC 程序之前,微 Controller 可以使用 DOS 版本的 PC 程序运行而不会导致错误。在 DOS 中,单个字节直接从串行端口读取和写入(没有像 Linux 中那样的内核缓冲区)由于大多数 C 代码都可以移植到 Linux,所以我尝试在 Linux 中复制串行端口读取和写入的 DOS 行为以保持其余部分处理这些单个字节。
我在PC上打开并初始化串口如下。
fd_mc = open("/dev/ttyS1", O_NOCTTY | O_RDWR /*| O_NONBLOCK*/ /*| O_SYNC*/);
if(fd_mc == -1)
{
perror("Could not open µc port.");
}
else
{
struct termios tty;
memset(&tty, 0, sizeof(tty));
if ( tcgetattr ( fd_mc, &tty ) != 0 )
{
perror("Error getting termios attributes");
}
cfsetospeed (&tty, B38400);
cfsetispeed (&tty, B38400);
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); //raw input
tty.c_oflag &= ~OPOST; //raw output
tty.c_cflag |= PARENB; //even parity
tty.c_cflag &= ~PARODD;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag |= (CLOCAL | CREAD);
tcsetattr(fd_mc, TCSANOW, &tty);
}
上面的代码是一个函数的片段,它初始化了两个串行端口(其中一个是微 Controller 的一个)。
编辑:这里是流量控制的设置,没有。
tty.c_cflag &= ~CRTSCTS; //No hardware based flow control
tty.i_cflag &= ~(IXON | IXOFF | IXANY); //no software based flow control
在环形缓冲区和 pollin 的帮助下,从串行端口读取发生在线程内。该线程在主循环中被调用。代码如下:
void *thread_read()
{
struct sched_param param;
param.sched_priority = 97;
int ret_par = 0;
ret_par = sched_setscheduler(3, SCHED_FIFO, ¶m);
if (ret_par == -1) {
perror("sched_setscheduler");
return 0;
}
struct pollfd poll_fd[2];
int ret;
extern struct fifo mc_fifo, serial_fifo;
ssize_t t;
char c;
poll_fd[0].fd = fd_mc;
poll_fd[0].events = POLLIN;
poll_fd[1].fd = fd_serial;
poll_fd[1].events = POLLIN;
while(1) {
ret = poll(poll_fd, 2, 10000);
if(ret == -1) {
perror("poll");
}
if(poll_fd[0].revents & POLLIN) {
t = read(fd_mc, &c, 1);
if(t>0) {
fifo_in(&mc_fifo, c);
}
}
if(poll_fd[1].revents & POLLIN) {
t = read(fd_serial, &c, 1);
if(t>0) {
fifo_in(&serial_fifo, c);
}
}
}
pthread_exit(NULL);
}
在主循环中调用。
pthread_t read;
pthread_create(&read, NULL, thread_read, NULL);
写入缓冲区(fifo_in)的函数是
int fifo_in(struct fifo *f, char data)
{
if( (f->write + 1 == f->read) || (f->read == 0 && f->write + 1 == FIFO_SIZE) ) //checks if write one before read or at the end
{
printf("fifo in overflow\n");
return 0; //fifo full
}
else {
f->data[f->write] = data;
f->write++;
// printf("Byte in: Containing %4d\tData:\t%4d\n", BytesInReceiveBuffer(1), data); //Bytes contained in fifo of mc
if(f->write >= FIFO_SIZE) {
f->write = 0;
}
return 1; //success
}
}
这个函数基本上做的是检查读取和写入的位置,如果两个位置不重叠且大于+1
,则将data
写入缓冲区> 彼此远离。
当另一个函数需要环形缓冲区中的字节时,它调用 GetByte
从环形缓冲区中读取字节。
获取字节
int GetByte(int port)
{
char c;
switch(port) {
case 0: //COM1
fifo_out(&serial_fifo,&c);
break;
case 1: //COM2
fifo_out(&mc_fifo,&c);
break;
}
return (int)c;
}
fifo_out
int fifo_out(struct fifo *f, char *data) {
if(f->read == f->write) {
printf("fifo in overfwrite\n");
*data = 0;
return 0;
}
else {
*data = f->data[f->read];
f->read++;
// printf("Byte out: Containing %4d\tData:\t%4d\n", BytesInReceiveBuffer(1), *data);
if(f->read >= FIFO_SIZE) {
f->read = 0;
}
return 1;
}
}
在 Linux 移植之前,DOS 版本中的一切都是顺序的。
吃了那一刻,我最好的猜测是,read()
会减慢速度,并且在某个时候开始减慢缓冲区的读取速度,这再次阻止了线程的调用。也许我错了。目前我有点不知道这个错误到底是什么,甚至不知道如何解决这个问题。
感谢每一个好的建议。
最佳答案
您确定在应用程序中需要 fifo 吗?您的串行驱动程序很可能已经在内核中有相当大的缓冲区(通常是一页,通常为 4kB)。如果这就足够了,您可以通过让 GetByte
对串行设备执行非阻塞读取来从根本上简化实现。
如果您想坚持这种设计,请考虑修改您的读取循环以一次读取多个字节。现在,您需要为每个字节读取两次系统调用。
您总是在更改 PID 3 的调度类。这可能不是您想要的。此外,这仅意味着您的线程将在字节到达内核内部缓冲区后运行(即当 poll
返回时)。如果通过在工作队列上运行作业将字节从硬件 FIFO 传输到缓冲区,并且该工作队列在 SCHED_OTHER
中运行(大多数情况下都是如此),更改线程的调度程序将不会想要的效果。经典的优先级倒置问题。您可能想要审核您的特定板使用的内核驱动程序。不过,如果您在每次 read
时清空整个缓冲区,这应该不是什么问题。
如果此代码曾经在 SMP 系统上使用过,您最想用锁来保护 read
和 write
指针,因为它们不是原子更新。线程很难正确处理,您是否考虑过使用事件循环来代替?类似于 libev .
关于c - 嵌入式 Linux : Reading bytes from serial port too slow for quicker transfer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50930661/
这个问题困扰了我几天。 这是我的相关 Storyboard布局: 我已经将阳光下的每个布局都设置为所有三个 View Controller ,并且仍然得到一个在横幅 View 上方有一个“间隙”的结果
我正在我的 C++ 程序中嵌入一个网页。我遇到的问题是,在嵌入式页面的 javascript 中,我可以捕获 onkeypress,但不会触发 onkeydown 和 onkeyup。 如果我在非嵌入
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
我有一个 java web 应用程序。我想创建一个嵌入式 LDAP 服务器,当 web 应用程序运行时,我将向 LDAP 插入一些记录,并且有另一个 web 应用程序将访问此 LDAP 以获取信息。可
我正在尝试通过 tomcat maven 插件将 war 部署到嵌入式 tomcat 服务器。控制台显示服务器启动正常。 看来 war 还没有展开。当我访问 http://localhost:9090
假设我有如下函数: bigrams=[(k,v) for (k,v) in dict_bigrams.items() if k[:pos_qu]==selection[:pos_qu
我读过一些关于 python 嵌入式 C++ 的教程。我曾引用过 python 对象。 https://docs.python.org/3/c-api/function.html Python 脚本:
我正在使用嵌入式应用程序,在调试期间,调试器无法解析宏符号(我的理论:因为宏在预处理中丢失了)。我最终不得不先在源代码中找到宏,然后使用定义来监视变量。 我的问题是:有没有办法将宏定义合并到 elf
首先我要说的是我开发的是基于cortex m4的嵌入式设备应用。 我有引导加载程序和主应用程序通用的功能。现在我为引导加载程序和应用程序编译源文件 2 次。但是我的双库 dfu 空间不足,我想在 RO
作为嵌入式 C 编程的初学者,我很好奇每个(根据我的经验)程序执行是如何从 main() 函数开始的?这就像链接器识别 main() 并将那个“特殊” 函数的地址放入重置 vector 指向的地址。
在我的实时嵌入式处理器固件中,我需要十进制数字的格式化打印。标准 printf/sprintf 在工具链中不可用,所以我需要自己实现它。 我使用了除以十并取余的天真方法。但是我的目标处理器本身不支持除
我有编程经验,但在软件开发方面了解不多。我目前正在为我工作的公司编写一个软件,我开始挑战自己代码的可读性。 我想知道这是否是嵌入式 if 语句的“有效”替代方案,或者我是否可以使用更好的方法。 假
我有一个运行嵌入式 Linux 的嵌入式目标,我想计算以下时间: 1) 高速缓存读/写时序2) uncache 内存读/写时序 Linux 中是否有任何标准测试来计算上述时间? 我已经编写了自己的测试
大多数嵌入式设备都是为了在通常资源受限或低规格的设备上执行特定任务而构建的。 因此,大多数嵌入式开发人员需要去除不必要的库和模块,并为其特定设备和用例创建自定义分发。我们先来了解一下嵌入式 Linu
我正在嵌入式处理器上编写一个简单的裸机应用程序。作为此应用程序的一部分,它必须使用 malloc 在大约 256kB 的堆上分配一些内存。注意:最初这是在 main 中静态分配的,但在一定的大小限制下
我正在尝试为我 friend 的婚礼建立一个网站。我使用的是 Bootstrap 5,嵌入的视频没有填满屏幕大小。这是一个 live test page HTML: 您还需要代码吗?我想让视频的全宽
我有一个项目,我尝试为微 Controller 构建固件并尝试更好地控制所使用的优化标志。我想,而不是使用 -O flag 分别指定不同的优化标志。不幸的是,-O 似乎发生了一些优化魔法。我无法使用单
我正在使用双核设备,并且要求核心 A 创建一个数据结构,其中包含在核心 B 上运行的函数列表的参数,定期更新它并通知核心 B。参数和类型的数量可以改变在运行期间。 我的计划如下.. 创建一个 Para
我们有一个 Microsoft.Phone.Controls.WebBrowser内嵌控件 StackPanel , 在 PivotItem 内在 Windows Phone 8 上。以简化的形式,它
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 2 年前。 Improve this ques
我是一名优秀的程序员,十分优秀!