4141#include <tiam1808/armv5/am1808/edma_event.h>
4242#include <tiam1808/armv5/am1808/evmAM1808.h>
4343#include <tiam1808/armv5/am1808/interrupt.h>
44+ #include <tiam1808/armv5/cp15.h>
4445#include <tiam1808/edma.h>
4546#include <tiam1808/hw/hw_edma3cc.h>
4647#include <tiam1808/hw/hw_syscfg0_AM1808.h>
5455
5556#include <umm_malloc.h>
5657
58+ #include <pbdrv/compiler.h>
5759#include <pbdrv/ioport.h>
5860#include <pbio/port_interface.h>
5961
@@ -483,6 +485,13 @@ void ev3_panic_handler(int except_type, ev3_panic_ctx *except_data) {
483485 panic_puts ("\r\nSPSR: 0x" );
484486 panic_putu32 (except_data -> spsr );
485487
488+ panic_puts ("\r\nDFSR: 0x" );
489+ panic_putu32 (CP15GetDFSR ());
490+ panic_puts ("\r\nIFSR: 0x" );
491+ panic_putu32 (CP15GetIFSR ());
492+ panic_puts ("\r\nFAR: 0x" );
493+ panic_putu32 (CP15GetFAR ());
494+
486495 panic_puts ("\r\nSystem will now reboot...\r\n" );
487496
488497 // Poke the watchdog timer with a bad value to immediately trigger it
@@ -627,6 +636,73 @@ static void Edma3CCErrHandlerIsr(void) {
627636 }
628637}
629638
639+ #define MMU_SECTION_SHIFT 20
640+ #define MMU_SECTION_SZ (1 << MMU_SECTION_SHIFT)
641+ #define MMU_L1_ENTS (1 << (32 - 20))
642+ #define MMU_L1_ALIGN (16 * 1024)
643+ #define MMU_L1_SECTION (addr , ap , domain , c , b ) ( \
644+ ((addr) & ~(MMU_SECTION_SZ - 1)) | \
645+ (((ap) & 3) << 10) | \
646+ (((domain) & 0xf) << 5) | \
647+ (1 << 4) | \
648+ ((!!(c)) << 3) | \
649+ ((!!(b)) << 2) | \
650+ (1 << 1) \
651+ )
652+ static uint32_t l1_page_table [MMU_L1_ENTS ] __attribute__((aligned (MMU_L1_ALIGN )));
653+ #define SYSTEM_RAM_SZ_MB 64
654+
655+ static void mmu_init (void ) {
656+ // Invalidate TLB
657+ CP15InvTLB ();
658+
659+ // Program domain D0 = no access, D1 = manager (no permission checks)
660+ // We generally don't bother with permission checks, anything valid is RWX
661+ CP15DomainAccessSet (0b1100 );
662+
663+ // For simplicity, everything is mapped as sections (1 MiB chunks)
664+ // This potentially fails to catch certain out-of-bounds accesses,
665+ // but as a tradeoff we do not need any L2 sections.
666+
667+ // MMIO register ranges
668+ l1_page_table [0x01C00000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0x01C00000 , 0 , 1 , 0 , 0 );
669+ l1_page_table [0x01D00000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0x01D00000 , 0 , 1 , 0 , 0 );
670+ l1_page_table [0x01E00000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0x01E00000 , 0 , 1 , 0 , 0 );
671+ l1_page_table [0x01F00000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0x01F00000 , 0 , 1 , 0 , 0 );
672+
673+ // On-chip RAM, which is used to share control structures with the PRUs
674+ l1_page_table [0x80000000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0x80000000 , 0 , 1 , 0 , 0 );
675+
676+ // Off-chip main DDR RAM
677+ for (unsigned int i = 0 ; i < SYSTEM_RAM_SZ_MB ; i ++ ) {
678+ uint32_t addr = 0xC0000000 + i * MMU_SECTION_SZ ;
679+ // TODO: Enable caching once DMA code is upgraded to handle cache
680+ l1_page_table [addr >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (addr , 0 , 1 , 0 , 0 );
681+ }
682+ // Off-chip main DDR RAM, uncacheable mirror @ 0xD0000000
683+ for (unsigned int i = 0 ; i < SYSTEM_RAM_SZ_MB ; i ++ ) {
684+ uint32_t addr_phys = 0xC0000000 + i * MMU_SECTION_SZ ;
685+ uint32_t addr_virt = 0xD0000000 + i * MMU_SECTION_SZ ;
686+ l1_page_table [addr_virt >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (addr_phys , 0 , 1 , 0 , 0 );
687+ }
688+
689+ // ARM local RAM, interrupt controller
690+ l1_page_table [0xFFF00000 >> MMU_SECTION_SHIFT ] = MMU_L1_SECTION (0xFFF00000 , 0 , 1 , 0 , 0 );
691+
692+ // Make sure this all makes its way into memory
693+ pbdrv_compiler_memory_barrier ();
694+
695+ // Set TTBR
696+ CP15TtbSet ((uint32_t )l1_page_table );
697+
698+ uint32_t c15_control = CP15ControlGet ();
699+ // Clear R and S protection bits (even though we don't use them)
700+ c15_control &= ~((1 << 9 ) | (1 << 8 ));
701+ // Enable I-cache, D-cache, alignment faults, and MMU
702+ c15_control |= (1 << 12 ) | (1 << 2 ) | (1 << 1 ) | (1 << 0 );
703+ CP15ControlSet (c15_control );
704+ }
705+
630706enum {
631707 BOOT_EEPROM_I2C_ADDRESS = 0x50 ,
632708};
@@ -637,6 +713,7 @@ uint8_t pbdrv_ev3_bluetooth_mac_address[6];
637713// initialization (low level in pbdrv, high level in pbio), and system level
638714// functions for running user code (currently a hardcoded MicroPython script).
639715void SystemInit (void ) {
716+ mmu_init ();
640717
641718 SysCfgRegistersUnlock ();
642719
0 commit comments