Activate Co-Processor for Bare-Metal via Genode

Matthias Adams adams at in.tum.de
Thu Dec 6 17:32:55 CET 2018


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



More information about the users mailing list