我需要直接写入串行端口(我正在尝试调试 irq 处理程序中的挂起,因此希望写入串行端口而不通过我假设使用中断的正常驱动程序)。
无论如何,我写了一小段代码来尝试测试写入串口。 我已经执行了
setserial /dev/ttyS0 uart none
从普通驱动程序中释放端口。
代码:
#define PORT 0x3f8
static int test_module_init(void) {
if(request_region(0x3f8, 5, "test_module") == NULL) {
printk("<1> Failed to request_region\n");
} else {
printk("<1> Request region success!\n");
outb(0x00, PORT + 1); // Disable all interrupts
outb(0x80, PORT + 3); // Enable DLAB (set baud rate divisor)
outb(0x01, PORT + 0); // Set divisor to 1 (lo byte) 115200 baud
outb(0x00, PORT + 1); // (hi byte)
outb(0x03, PORT + 3); // 8 bits, no parity, one stop bit
outb(0x00, PORT + 2); // Disable fifo
outb('a', PORT);
outb('\n', PORT);
printk("<1> Sent a\n");
}
return 0;
}
请求区域成功,但串口没有收到任何数据。有谁知道我做错了什么?我尝试过各种设置(fifo 启用/禁用等),但没有成功。
您的代码有两个问题,在对此发表评论之前,我想先指出原始源代码。
查看内核源代码,可以在以下位置找到 request_region 命令的一个很好的示例:
arch/arm/common/via82c505.c
在文件中,使用的命令如下:
if (!request_region(0xA8,2,"via config")) { printk(KERN_WARNING"VIA 82c505: Unable to request region 0xA8\n"); return; }
这意味着“request_region”命令如果成功则返回 0(或 NULL),而不是相反,因此:
问题 1:您的代码正在以相反的方式测试输出(即,当 NULL 正常时,它会说“如果它是 NULL,那么它就是错误的”)
问题 2:在更改之前必须保留芯片制造商提供的任何“保留”值,例如,如果您有一个 8 位长的参数,并且位 1-7 是“保留”,则尝试设置位 0对于带有 outb 的东西,如果不读取并保留现有的 1-7 位,就像用大锤敲击螺母一样。
在机器代码中,您应该执行以下操作(在我的示例中),考虑到您正在尝试禁用中断,您应该执行以下操作:
mov dx, 0x3f9
in al, dx
and al, 0xfe /* 0xfe is: 11111110, anding with this will clear bit-1 only and leave the rest */
out dx, al
问题 3:好吧,建议:尽量保持简单,不更改任何参数设置(中断、时钟、定时等),只需将任何内容输出到 0x3f8,然后在示波器上查看结果,我将首先使用 User-跳转前的代码不是内核代码,例如:
stty -F /dev/ttySx 9600 cs8 (where x is the port no, 9.6KBps, 8-bits)
echo -e -n "0x00" > /dev/ttySx
首先尝试这个,然后在上面逐渐构建你的程序,一旦全部工作,你就可以开始在内核端工作了。
祝你好运,希望一切顺利