Hello everyone,
I am currently working on a Pandaboard ES, on which a Genode 18.02 runs using a L4 Kernel and I would like to use the Co-Processor of the Pandaboard (namely Cortex M3). I used an example like [1] in order to write my application for the M3, which works perfectly when loaded by the program suggested in [1]. [1] https://github.com/apopple/Pandaboard-FreeRTOS
In order to get things working, when a Genode system is running on the main Processor (Cortex A9) I wrote a "driver" similar to the gpio driver, which should set-up the MMU for the M3 and start it, but absolutely nothing happens. The driver compiles and runs without any warnings or errors. Reads and writes to physical addresses look good to me, but the M3 does not seem to start (it should blink an LED for now).
I triple checked all physical addresses, which I added to 'repos/base/include/drivers/defs/panda.h': /*M3 */ CM_MPU_M3_CLKSTCTRL_BASE = 0x4a008900, CM_MPU_M3_CLKSTCTRL_SIZE = 0x40, RM_MPU_M3_RSTCTRL_BASE = 0x4a306900, RM_MPU_M3_RSTCTRL_SIZE = 0x20, M3_L2MMU_BASE = 0x55082040, M3_L2MMU_SIZE = 0x40
I used these bases, in order to create my Registers like:
struct M3_CM_MPU_reg : Genode::Attached_io_mem_dataspace, Genode::Mmio { M3_CM_MPU_reg(Genode::Env &env, Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : Genode::Attached_io_mem_dataspace(env, mmio_base, mmio_size), Genode::Mmio((Genode::addr_t)local_addr<void>()) { }
struct Clkstctrl : Register<0x00, 32> {}; struct Clkctrl : Register<0x20, 32> {}; };
struct M3_RM_MPU_reg : Genode::Attached_io_mem_dataspace, Genode::Mmio { M3_RM_MPU_reg(Genode::Env &env, Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : Genode::Attached_io_mem_dataspace(env, mmio_base, mmio_size), Genode::Mmio((Genode::addr_t)local_addr<void>()) { }
struct Rstctrl : Register<0x10, 32> {}; };
struct M3_L2MMU_reg : Genode::Attached_io_mem_dataspace, Genode::Mmio { M3_L2MMU_reg(Genode::Env &env, Genode::addr_t const mmio_base, Genode::size_t const mmio_size) : Genode::Attached_io_mem_dataspace(env, mmio_base, mmio_size), Genode::Mmio((Genode::addr_t)local_addr<void>()) { }
struct Cntl : Register<0x4, 8> {}; struct Ttb : Register<0xc, 32> {};
};
The registers are then written and read in my driver like below:
class Omap4_driver : public M3::Driver { private:
Genode::Env &_env; M3_CM_MPU_reg _m3_cm_mpu; M3_RM_MPU_reg _m3_rm_mpu; M3_L2MMU_reg _m3_l2mmu;
Omap4_driver(Genode::Env &env) : _env(env), // see repos/base/include/drivers/defs/panda.h _m3_cm_mpu(_env, Panda::CM_MPU_M3_CLKSTCTRL_BASE, Panda::CM_MPU_M3_CLKSTCTRL_SIZE), _m3_rm_mpu(_env, Panda::RM_MPU_M3_RSTCTRL_BASE, Panda::RM_MPU_M3_RSTCTRL_SIZE), _m3_l2mmu(_env, Panda::M3_L2MMU_BASE, Panda::M3_L2MMU_SIZE) { }
public:
static Omap4_driver& factory(Genode::Env &env);
/****************************** ** M3::Driver interface ** ******************************/
void setup_l2mmu(Genode::addr_t ds_phys_addr, Genode::Ram_dataspace_capability ttb_cap, Genode::addr_t ttb_phys_addr) { Genode::addr_t ttb_addr = _env.rm().attach(ttb_cap); Genode::log("L2: attached dataspace");
/* Brings the L2 MMU out of reset and sets up virtual addresses */ unsigned clkctrl = _m3_cm_mpu.read<M3_CM_MPU_reg::Clkctrl>(); clkctrl = 0x01; _m3_cm_mpu.write<M3_CM_MPU_reg::Clkctrl>(clkctrl); unsigned clkstctrl = _m3_cm_mpu.read<M3_CM_MPU_reg::Clkstctrl>(); clkstctrl = 0x02; _m3_cm_mpu.write<M3_CM_MPU_reg::Clkstctrl>(clkstctrl); unsigned rstctrl = _m3_rm_mpu.read<M3_RM_MPU_reg::Rstctrl>(); rstctrl &= ~0x4; _m3_rm_mpu.write<M3_RM_MPU_reg::Rstctrl>(rstctrl); int *TTB = ((int*) ttb_addr);
/* Initialise address translation table */ /* Every address will be mapped to M3_LOAD_ADDRESS */ for(int i = 0; i < 4096; i++) { TTB[i] = (((ds_phys_addr) & 0xfff00000) | 0x00c02); }
/* Set the last entry to point to the GPIO1 peripheral to flash a light */ /* ie. Virtual address of GPIO1_DATAOUT is 0xfff1013c */ TTB[4095] = 0x4a300c02;
/* Set the base address */ Genode::log("physAddr: ", Genode::Hex(ttb_phys_addr)); _m3_l2mmu.write<M3_L2MMU_reg::Ttb>(ttb_phys_addr);
/* Enable MMU */ _m3_l2mmu.write<M3_L2MMU_reg::Cntl>(0x6); Genode::log("L2 enabled"); }
void start_m3() { /* Release Cortex-M3 from reset */ unsigned rstctrl = _m3_rm_mpu.read<M3_RM_MPU_reg::Rstctrl>(); rstctrl &= ~1; _m3_rm_mpu.write<M3_RM_MPU_reg::Rstctrl>(rstctrl); } };
Any idea on how to get things working or on how to further debug would be great!
Thanks, Matthias