Skip to content

Commit 9caac6c

Browse files
ArcaneNibblelaurensvalk
authored andcommitted
pbio/platform/ev3/platform.c: Initial MMU setup
This creates an identity mapping for only the valid bits of the address space. It also adds logic to the exception handler to print out fault addresses. This currently marks the entire address space as uncacheable. Drivers will need to be updated to take caches into account before we can mark RAM as cacheable.
1 parent 13a21d5 commit 9caac6c

3 files changed

Lines changed: 148 additions & 11 deletions

File tree

lib/pbio/platform/ev3/platform.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
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>
@@ -54,6 +55,7 @@
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+
630706
enum {
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).
639715
void SystemInit(void) {
716+
mmu_init();
640717

641718
SysCfgRegistersUnlock();
642719

lib/tiam1808/system_config/armv5/gcc/cp15.c

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3838
*/
3939

40+
#include <stdint.h>
41+
4042
/******************************************************************************
4143
** FUNCTION DEFINITIONS
4244
******************************************************************************/
@@ -218,21 +220,10 @@ void CP15DCacheCleanBuff(unsigned int bufPtr, unsigned int size)
218220
**/
219221
void CP15TtbSet(unsigned int ttb)
220222
{
221-
/* Invalidates all TLBs.Domain access is selected as
222-
* client by configuring domain access register,
223-
* in that case access controlled by permission value
224-
* set by page table entry
225-
*/
226-
__asm(" mov r1, #0\n\t"
227-
" mcr p15, #0, r1, c8, c7, #0\n\t"
228-
" ldr r1, =0x55555555\n\t"
229-
" mcr p15, #0, r1, c3, c0, #0\n\t");
230-
231223
/* sets translation table base resgister with page table
232224
* starting address.
233225
*/
234226
__asm(" mcr p15, #0, %[value], c2, c0, 0":: [value] "r" (ttb));
235-
236227
}
237228

238229
/**
@@ -268,4 +259,64 @@ void CP15MMUEnable(void)
268259
" mcr p15, #0, r0, c1, c0, #0\n\t");
269260
}
270261

262+
/**
263+
* \brief This function gets the data fault status register
264+
*/
265+
uint32_t CP15GetDFSR(void)
266+
{
267+
uint32_t ret;
268+
__asm("mrc p15, 0, %0, c5, c0, 0" : "=r" (ret));
269+
return ret;
270+
}
271+
272+
/**
273+
* \brief This function gets the instruction fault status register
274+
*/
275+
uint32_t CP15GetIFSR(void)
276+
{
277+
uint32_t ret;
278+
__asm("mrc p15, 0, %0, c5, c0, 1" : "=r" (ret));
279+
return ret;
280+
}
281+
282+
/**
283+
* \brief This function gets the fault address register
284+
*/
285+
uint32_t CP15GetFAR(void)
286+
{
287+
uint32_t ret;
288+
__asm("mrc p15, 0, %0, c6, c0, 0" : "=r" (ret));
289+
return ret;
290+
}
291+
292+
/**
293+
* \brief This function invalidates the TLB
294+
*/
295+
void CP15InvTLB(void)
296+
{
297+
__asm(" mov r0, #0\n\t"
298+
" mcr p15, #0, r0, c8, c7, #0"
299+
::: "r0");
300+
}
301+
302+
/**
303+
* \brief This function programs the domain access control register
304+
*/
305+
void CP15DomainAccessSet(uint32_t domains)
306+
{
307+
__asm("mcr p15, 0, %0, c3, c0, 0" :: "r"(domains));
308+
}
309+
310+
uint32_t CP15ControlGet(void)
311+
{
312+
uint32_t ret;
313+
__asm("mrc p15, 0, %0, c1, c0, 0" : "=r" (ret));
314+
return ret;
315+
}
316+
317+
void CP15ControlSet(uint32_t control)
318+
{
319+
__asm("mcr p15, 0, %0, c1, c0, 0" :: "r" (control));
320+
}
321+
271322
/********************************* End Of File *******************************/

lib/tiam1808/tiam1808/armv5/cp15.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#ifndef __CP15_H
4242
#define __CP15_H
4343

44+
#include <stdint.h>
45+
4446
#ifdef __cplusplus
4547
extern "C" {
4648
#endif
@@ -60,6 +62,13 @@ extern void CP15MMUDisable(void);
6062
extern void CP15MMUEnable(void);
6163
extern void CP15ICacheFlushBuff(unsigned int ptr, unsigned int size);
6264
extern void CP15DCacheCleanBuff(unsigned int bufPtr, unsigned int size);
65+
extern uint32_t CP15GetDFSR(void);
66+
extern uint32_t CP15GetIFSR(void);
67+
extern uint32_t CP15GetFAR(void);
68+
extern void CP15InvTLB(void);
69+
extern void CP15DomainAccessSet(uint32_t domains);
70+
extern uint32_t CP15ControlGet(void);
71+
extern void CP15ControlSet(uint32_t control);
6372

6473
#ifdef __cplusplus
6574
}

0 commit comments

Comments
 (0)