如何轮询一个字节最多1ms?

问题描述

这是有问题的代码。

#define CSSPDR     SPI::Mem[2]  // Data Recieve / Data Transmit
#define CSSPSR     SPI::Mem[3] // SPI Status Register
#define SPI_BUSY            ((CSSPSR & 0x10) == 0x10)
#define SPI_READ_BUFF_EMPTY ((CSSPSR & 0x4) == 0)


ushort Comm(ushort value)
{
    ulong w1=1000000,w2=1000000;
    ulong ret;

    CSSPDR = value;
    while (SPI_BUSY && (w1>0)){--w1;};

    do {
        ret = CSSPDR;
    }
    while(!SPI_READ_BUFF_EMPTY && (--w2>0));

    return ret;
}

上面是SPI通信的一些问题代码-通过将其写入特殊寄存器来发送值,等待发送完成,然后读取答复,等待直到传输完成(如果以前有一些垃圾缓冲,只需覆盖它,最后到达的值就是一个好值)-但是等待状态实现为带有计数器的难看的while()循环。

远程设备需要不到1ms的时间来处理信息并将其发送回去,但是要传输的数据很多。只要通信畅通无阻,它就可以正常工作-通常在几百次迭代内就能获得答复,而很少会有噪音-几千次。很少有什么东西会因超时而丢失,而不是很大的问题,错误的读数将在几毫秒后被良好的错误修复,并且过滤功能可以解决故障。

但是,如果将CPU与远程设备连接的软带损坏,则通信将中断,并且超时变量每次都会开始计数到最大值。副作用是整个应用程序陷入停顿,浪费了大量CPU时间在这些循环中等待。这种情况很少发生,但结果却很丑陋,我更希望采用一种解决方案,以防万一发生故障,而该故障绝对不是关键部分。

如果我做了usleep(1),我将永远无法达到所需的吞吐量,因为它会在一段时间内将控制权交还给内核,时间通常长于1ms(它只要求不早于1µs唤醒,内核可以自由地延长时间,通常,如果其他任务很忙,它甚至可以延长100毫秒。同样,将任何“重量级”或其他耗时的内容放入循环中都会减慢通信速度,因为对“ BUSY”位消失的反应将被延迟。两次读取之间的延迟约为100µs,这大约是我所能承受的,或者可选地,在发送数据与开始轮询BUSY位之间有500µs的初始延迟(这将有零的机会被更早地清除。) / p>

实验发现超时1000000次迭代的值是“几乎永不失败”。我可以尝试将它们压低,但这并不能真正解决问题,只是可以减轻一些痛苦(并且可能会造成中断通信的副作用,这种通信可能需要一段时间才能解决。

解决方法

轮询通常是个坏主意。最好在内核端使用中断来完成这种工作。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...