为什么每次加载内核模块时 membase 地址都不同?
Why is membase adress different each time kernel module is loaded?
我一直在使用 Linux 版本作为示例构建 RTDM UART 驱动程序。 UART 基地址应该是 0x80070000
,当使用 linux 驱动程序时没有问题,因为 dmesg 显示:
80070000.serial: ttyAPP3 at MMIO 0x80070000 (irq = 234, base_baud = 1500000) is a 80070000.serial
mxs-auart 80070000.serial: Found APPUART 3.1.0
但是,当我使用正在构建的驱动程序时,每次加载模块(例如 0xc8df6000
)时都会得到不同的地址,其中 none 是正确的.
这是我正在使用的探测函数:
static int rt_mxs_auart_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxs_auart_dt_ids, &pdev->dev);
int ret;
struct resource *r;
struct rtdm_device *dev;
struct rt_mxs_auart_port *s;
//allocate managed kernel memory
s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
if (!s)
return -ENOMEM;
ret = rt_serial_mxs_probe_dt(s, pdev);
if (ret < 0){
return ret;
}
if (of_id) {
pdev->id_entry = of_id->data;
s->devtype = pdev->id_entry->driver_data;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r)
return -ENXIO;
//get irq line
s->irq = platform_get_irq(pdev, 0);
if (s->irq < 0)
return -ENODEV;
//base memory
s->membase = ioremap(r->start, resource_size(r));
if (IS_ERR(s->membase))
return PTR_ERR(s->membase);
/*define the rtdm_device*/
dev = &s->rtdm_dev;
dev->driver = &ida_driver;
dev->label = "xeno_ida";
dev->device_data = s;
ret = mxs_get_clks(s, pdev); //activate clocks
if (ret)
return ret;
s->uartclk = clk_get_rate(s->clk);
s->fifosize = MXS_AUART_FIFO_SIZE;
mxs_init_regs(s);
ret = rtdm_dev_register(dev); //register driver in RTDM space
if (ret)
return ret;
platform_set_drvdata(pdev, s); //add device-related data to device struct
pr_info("Probe: Successful\n");
pr_info("%s on IMX UART%d: membase=0x%p irq=%d uartclk=%d\n",
dev->name, pdev->id, s->membase, s->irq, s->uartclk);
return 0;
}
基于mxs-auart.c
和rt_imx_uart.c
。
对于 membase
我使用与 mxs-auart.c
相同的代码,这就是为什么我不明白为什么我会遇到这个问题。当我尝试 rmmod
一段时间后,我的驱动程序也冻结了,所以我想知道它是否由此引起。
非常感谢任何帮助!
ioremap
的return值是虚拟地址,不是物理地址。它可以在虚拟地址 space.
中的任何位置
物理地址存储在r->start
(ioremap
的输入)。
我一直在使用 Linux 版本作为示例构建 RTDM UART 驱动程序。 UART 基地址应该是 0x80070000
,当使用 linux 驱动程序时没有问题,因为 dmesg 显示:
80070000.serial: ttyAPP3 at MMIO 0x80070000 (irq = 234, base_baud = 1500000) is a 80070000.serial
mxs-auart 80070000.serial: Found APPUART 3.1.0
但是,当我使用正在构建的驱动程序时,每次加载模块(例如 0xc8df6000
)时都会得到不同的地址,其中 none 是正确的.
这是我正在使用的探测函数:
static int rt_mxs_auart_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(mxs_auart_dt_ids, &pdev->dev);
int ret;
struct resource *r;
struct rtdm_device *dev;
struct rt_mxs_auart_port *s;
//allocate managed kernel memory
s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
if (!s)
return -ENOMEM;
ret = rt_serial_mxs_probe_dt(s, pdev);
if (ret < 0){
return ret;
}
if (of_id) {
pdev->id_entry = of_id->data;
s->devtype = pdev->id_entry->driver_data;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!r)
return -ENXIO;
//get irq line
s->irq = platform_get_irq(pdev, 0);
if (s->irq < 0)
return -ENODEV;
//base memory
s->membase = ioremap(r->start, resource_size(r));
if (IS_ERR(s->membase))
return PTR_ERR(s->membase);
/*define the rtdm_device*/
dev = &s->rtdm_dev;
dev->driver = &ida_driver;
dev->label = "xeno_ida";
dev->device_data = s;
ret = mxs_get_clks(s, pdev); //activate clocks
if (ret)
return ret;
s->uartclk = clk_get_rate(s->clk);
s->fifosize = MXS_AUART_FIFO_SIZE;
mxs_init_regs(s);
ret = rtdm_dev_register(dev); //register driver in RTDM space
if (ret)
return ret;
platform_set_drvdata(pdev, s); //add device-related data to device struct
pr_info("Probe: Successful\n");
pr_info("%s on IMX UART%d: membase=0x%p irq=%d uartclk=%d\n",
dev->name, pdev->id, s->membase, s->irq, s->uartclk);
return 0;
}
基于mxs-auart.c
和rt_imx_uart.c
。
对于 membase
我使用与 mxs-auart.c
相同的代码,这就是为什么我不明白为什么我会遇到这个问题。当我尝试 rmmod
一段时间后,我的驱动程序也冻结了,所以我想知道它是否由此引起。
非常感谢任何帮助!
ioremap
的return值是虚拟地址,不是物理地址。它可以在虚拟地址 space.
物理地址存储在r->start
(ioremap
的输入)。