我目前正在开发一个在经过大量修改的 Linux 版本上运行的项目,该版本已修补以能够访问 VMEbus。大多数总线处理已经完成,我有一个 VMEAccess 类,它使用 mmap 在 /dev/mem 的特定地址写入,因此驱动程序可以提取该数据并将其推送到总线上。
当程序启动时,它不知道它要寻找的从板在总线上的位置,所以它必须通过四处寻找它:它尝试一个一个地读取每个地址,如果一个设备连接在那里,则读取方法返回一些数据,但如果没有任何连接,则将向程序发送 SIGBUS 信号。
我尝试了几种解决方案(主要使用信号处理),但一段时间后,我决定使用跳转。第一个 longjmp() 调用工作正常,但对 VMEAccess::readWord() 的第二个调用给了我一个总线错误,即使我的处理程序应该防止程序崩溃。
这是我的代码:
#include <iostream>
#include <string>
#include <sstream>
#include <csignal>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#include "types.h"
#include "VME_access.h"
VMEAccess *busVME;
int main(int argc, char const *argv[]);
void catch_sigbus (int sig);
void exit_function(int sig);
volatile BOOL bus_error;
volatile UDWORD offset;
jmp_buf env;
int main(int argc, char const *argv[])
{
sigemptyset(&sigBusHandler.sa_mask);
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = exit_function;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
/* */
struct sigaction sigBusHandler;
sigBusHandler.sa_handler = catch_sigbus;
sigemptyset(&sigBusHandler.sa_mask);
sigBusHandler.sa_flags = 0;
sigaction(SIGBUS, &sigBusHandler, NULL);
busVME = new VMEAccess(VME_SHORT);
offset = 0x01FE;
setjmp(env);
printf("%d\n", sigismember(&sigBusHandler.sa_mask, SIGBUS));
busVME->readWord(offset);
sleep(1);
printf("%#08x\n", offset+0xC1000000);
return 0;
}
void catch_sigbus (int sig)
{
offset++;
printf("%#08x\n", offset);
longjmp(env, 1);
}
void exit_function(int sig)
{
delete busVME;
exit(0);
}