I have a Xilinx SoC, and have created a simple multiplier on the programmable logic via verilog. The multiplier takes two 16 bit input, multiplies them and returns a 32 bit output. The digital design have been packaged and linked to the processor system that is within the SoC via an AXI-Lite interface. The Xilinx tools have auto-generated a device tree entity for this digital design so that a custom linux device driver can be created to interact with the digital design (i.e the PS will treat it just like an external hardware device connected to the ARM processor).
The device tree generated looks like this:
/ { amba_pl: amba_pl@0 { #address-cells = <2>; #size-cells = <2>; compatible = "simple-bus"; ranges ; multi2_0: multi2@a0000000 { clock-names = "s00_axi_aclk"; clocks = <&zynqmp_clk 71>; compatible = "xlnx,multi2-1.0"; reg = <0x0 0xa0000000 0x0 0x10000>; xlnx,s00-axi-addr-width = <0x4>; xlnx,s00-axi-data-width = <0x20>; }; }; }; So from the device tree we can see that the multiplier ("multi2-1.0") has a physical memory address of 0xa0000000, with address width of 0x4 and data width of 32 bits.
So, from the device driver point of view, specifically in the write call-back function, I am writing a 32-bit number into the virtual memory address that was retrieved from "ioremap(.)" function.
A sanity check was done to see the virtual memory mapping to physical address, and it seems to be correctly done with no errors (some memory-related code snippets from the driver is shown below):
struct simpmod_local { int irq; unsigned long mem_start; unsigned long mem_end; void __iomem *base_addr; }; struct simpmod_local *lp = NULL; ......
static int simpmod_probe(struct platform_device *pdev) { ..... lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1); ... dev_info(dev,"simpmod at 0x%08x mapped to 0x%08x, irq=%d\n", (unsigned int __force)lp->mem_start, (unsigned int __force)lp->base_addr, lp->irq); .... } The write call-back function (as of now), is just taking a 32-bit number and placing it into memory. However, the read call-back function is just reading that exact same number even though I am reading from a base_address+0x20_offset. I have tried changing the offset value, but regardless, it keeps reading that same number.
My intuition tell me, that if reading from a different memory address the value should be either garbage value or zero, but its very unlikely to be reading the same value written to the base address. Any ideas to why the written data is copied across the entire allocated memory space?
Even doing a devmem command <devmem 0xa0000000 w 52> will produce the output 52 when executing <devmem 0xa0000020 w> or <devmem 0xa0000040 w> or ......
The write-callback function looks like this:
static ssize_t dev_write(struct file *fil, const char *buf, size_t len, loff_t *off){ sscanf (buf,"%d,%d",&operand_1,&operand_2); ker_buf[len] = 0 ; iowrite32((unsigned int) operand_1, lp->base_addr); return len; } The full project code (with minor changes) can be found on https://forums.xilinx.com/t5/Embedded-Linux/Memory-Replications-during-write-call-back-function-in-Linux/m-p/1212405
https://stackoverflow.com/questions/66464686/linux-kernel-device-driver-write-callback-is-writing-data-across-the-entire-allo March 04, 2021 at 04:46AM
没有评论:
发表评论