Hi everyone,
I’m currently working on interfacing a custom APB peripheral with the processor on the BeagleV-Fire board, but I’m stuck trying to get any write to actually reach the memory-mapped register.
Here’s what I’ve done by now:
-
I followed this tutorial
https://www.youtube.com/watch?v=ZvXKUD36HSM&list=PLMQHM3yowLTuPqlwytGAeLyJ5eavtuSAJ&index=12&ab_channel=bustedwing
but instead of reading what I’ve written, I get 0x00.
-
I’ve also tried my own design:
module simple_add (
input pclk ,
input presetn ,
input [31:0] paddr ,
input [31:0] pwdata ,
input pwrite ,
input psel ,
input penable ,
output reg [31:0] prdata ,
output reg pready
);
reg [31:0] a;
reg [31:0] b;
reg [31:0] rezultat;
reg [1:0] cnt;
always @(posedge pclk or negedge presetn)
if (~presetn) pready <= 1'b0; else
if (pready) pready <= 1'b0; else
if (psel & ~penable) pready <= 1'b1;
always @(posedge pclk or negedge presetn)
if (~presetn) prdata <= 'd0; else
if (psel & ~penable & ~pwrite & (cnt == 'd2)) prdata <= rezultat;
always @(posedge pclk or negedge presetn)
if (~presetn) a <= 'd0; else
if (psel & ~penable & ~|cnt & pwrite) a <= pwdata;
always @(posedge pclk or negedge presetn)
if (~presetn) b <= 'd0; else
if (psel & ~penable & (cnt == 'd1) & pwrite) b <= pwdata;
always @(posedge pclk or negedge presetn)
if (~presetn) rezultat <= 'd0; else
if (pready & (cnt == 'd1)) rezultat <= a + b;
always @(posedge pclk or negedge presetn)
if (~presetn) cnt <= 'd0; else
if (pready) cnt <= cnt + 'd1;
endmodule
And instantiated in CAPE.v:
wire sel_apb_yuv_rgb = APB_SLAVE_SLAVE_PSEL & (APB_SLAVE_SLAVE_PADDR[31:20] == 12'h411);
simple_add simple_add_i(
.pclk (PCLK ),
.presetn (PRESETN),
.paddr (APB_SLAVE_SLAVE_PADDR),
.pwdata (APB_SLAVE_SLAVE_PWDATA),
.pwrite (APB_SLAVE_SLAVE_PWRITE),
.psel (sel_apb_yuv_rgb),
.penable (APB_SLAVE_SLAVE_PENABLE),
.prdata (APB_SLAVE_PRDATA),
.pready (pready)
);
Mapped it at address: 0x41100000
And added this to the device tree overlay under fabric bus:
simple_add@41100000 {
compatible = "generic-uio";
reg = <0x00 0x41100000 0x00 0x1000>;
};
And the C program:
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#define APB_BASE_ADDR 0x41100000
#define MAP_SIZE 4096
int main() {
int mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (mem_fd < 0) {
perror("open");
return 1;
}
void *map_base = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, APB_BASE_ADDR);
if (map_base == MAP_FAILED) {
perror("mmap");
close(mem_fd);
return 1;
}
volatile uint32_t *reg_a = (volatile uint32_t *)(map_base + 0x10);
volatile uint32_t *reg_b = (volatile uint32_t *)(map_base + 0x14);
volatile uint32_t *reg_result = (volatile uint32_t *)(map_base + 0x18);
*reg_a = 10;
*reg_b = 15;
// Delay
for (volatile int i = 0; i < 1000; ++i);
uint32_t result = *reg_result;
printf("Rezultat = %u\n", result);
munmap(map_base, MAP_SIZE);
close(mem_fd);
return 0;
}
And still nothing.
- Used devmem2 to test memory directly — no effect.
I don’t know what should I do to simply read / write from mapped memory using APB. Can someone explain?
Also this is my GitLab project: https://git.beagleboard.org/Luciana.lm11/testing-gateware