use libregister::{ register_bit, register_bits, RegisterR, RegisterW, RegisterRW, }; use libcortex_a9::{def_reg_r, def_reg_w, wrap_reg}; pub use libcortex_a9::regs::{SP, LR}; /// Multiprocessor Affinity Register pub struct MPIDR; wrap_reg!(mpidr); def_reg_r!(MPIDR, mpidr::Read, "mrc p15, 0, $0, c0, c0, 5"); // CPU ID register_bits!(mpidr, cpu_id, u8, 0, 7); // group ID register_bits!(mpidr, group_id, u8, 8, 15); // 0b11 if part of uniprocessor system register_bits!(mpidr, u, u8, 30, 31); /// System Control Register pub struct SCTLR; wrap_reg!(sctlr); def_reg_r!(SCTLR, sctlr::Read, "mrc p15, 0, $0, c1, c0, 0"); def_reg_w!(SCTLR, sctlr::Write, "mrc p15, 0, $0, c1, c0, 0"); // MPU enable register_bit!(sctlr, m, 0); // strict alignment register_bit!(sctlr, a, 1); // L1 data cache enable register_bit!(sctlr, c, 2); // enable SWP and SWPB instructions register_bit!(sctlr, sw, 10); // enable branch prediction (SBO) register_bit!(sctlr, z, 11); // L1 instruction cache enable register_bit!(sctlr, i, 12); // Determines the location of exception vectors: // 0 = normal exception vectors selected, address range = 0x00000000-0x0000001C // 1 = high exception vectors (HIVECS) selected, address range = 0xFFFF0000-0xFFFF001C. // The primary input VINITHIm defines the reset value. register_bit!(sctlr, v, 13); // Round-robin bit, controls replacement strategy for instruction and data caches: // 0 = random replacement strategy // 1 = round-robin replacement strategy. // The reset value of this bit is 0. The processor always uses a random replacement strategy, regardless of the state // of this bit. register_bit!(sctlr, rr, 14); // MPU background region enable register_bit!(sctlr, br, 17); // Divide by zero: // 0 = do not generate an Undefined Instruction exception // 1 = generate an Undefined Instruction exception. // The reset value of this bit is 0 register_bit!(sctlr, dz, 19); // Fast Interrupts enable. // On the processor Fast Interrupts are always enabled. This bit is SBO register_bit!(sctlr, fi, 21); // Configures vectored interrupt: // 0 = exception vector address for IRQ is 0x00000018 or 0xFFFF0018. See V bit. // 1 = VIC controller provides handler address for IRQ. // The reset value of this bit is 0. register_bit!(sctlr, ve, 24); // Determines how the E bit in the CPSR is set on an exception: // 0 = CPSR E bit is set to 0 on an exception // 1 = CPSR E bit is set to 1 on an exception. // The primary input CFGEE defines the reset value. register_bit!(sctlr, ee, 25); // NMFI, non-maskable fast interrupt enable: // 0 = Software can disable FIQs // 1 = Software cannot disable FIQs. // This bit is read-only. The configuration input CFGNMFIm defines its value. register_bit!(sctlr, nmfi, 27); // TEX Remap Enable. On the processor this bit is SBZ. register_bit!(sctlr, tre, 28); // Access Flag Enable. On the processor this bit is SBZ. register_bit!(sctlr, afe, 29); // Thumb exception enable: // 0 = enable ARM exception generation // 1 = enable Thumb exception generation. // The primary input TEINIT defines the reset value register_bit!(sctlr, te, 30); // Identifies little or big instruction endianness in use: // 0 = little-endianness // 1 = big-endianness. // The primary input CFGIE defines the value. This bit is read-only register_bit!(sctlr, ie, 31); /// Auxiliary Control Register pub struct ACTLR; wrap_reg!(actlr); def_reg_r!(ACTLR, actlr::Read, "mrc p15, 0, $0, c1, c0, 1"); def_reg_w!(ACTLR, actlr::Write, "mcr p15, 0, $0, c1, c0, 1"); // A(B0/1)TCM external error enable: // 0 = Disabled // 1 = Enabled. // The primary input ERRENRAMm[0] defines the reset value. register_bit!(actlr, atcmecen, 0); register_bit!(actlr, b0tcmecen, 1); register_bit!(actlr, b1tcmecen, 2); // Cache error control for cache parity and ECC errors register_bits!(actlr, cec, u8, 3, 5); // Disable low interrupt latency on all load/store instructions register_bit!(actlr, dils, 6); // sMOV of a divide does not complete out of order. // No other instruction is issued until the divide is finished register_bit!(actlr, smov, 7); // Force D-side to not-shared when MPU is off: // 0 = Normal operation. This is the reset value. // 1 = D-side normal Non-cacheable forced to Non-shared when MPU is off. register_bit!(actlr, fdsns, 8); // Force write-through (WT) for write-back (WB) regions: // 0 = No forcing of WT. This is the reset value. // 1 = WT forced for WB regions register_bit!(actlr, fwt, 9); // Force outer read allocate (ORA) for outer write allocate (OWA) regions: // 0 = No forcing of ORA. This is the reset value. // 1 = ORA forced for OWA regions register_bit!(actlr, fora, 10); // Disable data forwarding for Non-cacheable accesses in the AXI master: // 0 = Normal operation. This is the reset value. // 1 = Disable data forwarding for Non-cacheable accesses register_bit!(actlr, dnch, 11); // Enable random parity error generation: // 0 = Random parity error generation disabled. This is the reset value. // 1 = Enable random parity error generation in the cache RAMs. register_bit!(actlr, erpeg, 12); // Disable linefill optimization in the AXI master: // 0 = Normal operation. This is the reset value. // 1 = Limits the number of outstanding data linefills to two register_bit!(actlr, dlfo, 13); // Disable write burst in the AXI master: // 0 = Normal operation. This is the reset value. // 1 = Disable write burst optimization register_bit!(actlr, dbwr, 14); // This field controls the branch prediction policy: // b00 = Normal operation. This is the reset value. // b01 = Branch always taken and history table updates disabled. // b10 = Branch always not taken and history table updates disabled. // b11 = Reserved. Behavior is Unpredictable if this field is set to b11 register_bits!(actlr, bp, u8, 15, 16); // Return stack disable: // 0 = Normal return stack operation. This is the reset value. // 1 = Return stack disabled. register_bit!(actlr, rsdis, 17); // Fetch rate control disable: // 0 = Normal fetch rate control operation. This is the reset value. // 1 = Fetch rate control disabled. register_bit!(actlr, frcdis, 19); // Disable Branch History (BH) extension: // 0 = Enable the extension. This is the reset value. // 1 = Disable the extension register_bit!(actlr, dbhe, 20); // Disable end of loop prediction: // 0 = Enable loop prediction. This is the reset value. // 1 = Disable loop prediction. register_bit!(actlr, deolp, 21); // Disable Low Interrupt Latency (LIL) on load/store multiples: // 0 = Enable LIL on load/store multiples. This is the reset value. // 1 = Disable LIL on all load/store multiples. register_bit!(actlr, dilsm, 22); // AXI slave cache RAM non-privileged access enable: // 0 = Disabled. This is the reset value. // 1 = Enabled register_bit!(actlr, axiscuen, 23); // AXI slave cache RAM access enable: // 0 = Disabled. This is the reset value. // 1 = Enabled register_bit!(actlr, axiscen, 24); // A(B0/1)TCM ECC check enable: // 0 = Disabled // 1 = Enabled // The primary input PARECCENRAMm[0] defines the reset value register_bit!(actlr, atcmpcen, 25); register_bit!(actlr, b0tcmpcen, 26); register_bit!(actlr, b1tcmpcen, 27); // Case A(B1, B2, C) dual issue control: // 0 = Enabled. This is the reset value. // 1 = Disabled. register_bit!(actlr, diadi, 28); register_bit!(actlr, dib1di, 29); register_bit!(actlr, dib2di, 30); register_bit!(actlr, dicdi, 31); /// Secondary Auxiliary Control Register pub struct SACTLR; wrap_reg!(sactlr); def_reg_r!(SACTLR, sactlr::Read, "mrc p15, 0, $0, c15, c0, 0"); def_reg_w!(SACTLR, sactlr::Write, "mcr p15, 0, $0, c15, c0, 0"); // Enables 64-bit stores for the ATCM. When enabled, the processor uses read-modify-write to ensure that all // reads and writes presented on the ATCM port are 64 bits wide. // 0 = Disabled // 1 = Enabled. // The primary input RMWENRAMm[0] defines the reset value. register_bit!(sactlr, atcmrmw, 0); register_bit!(sactlr, btcmrmw, 1); // Correction for internal ECC logic on ATCM port. // 0 = Enabled. This is the reset value. // 1 = Disabled register_bit!(sactlr, atcmecc, 2); register_bit!(sactlr, btcmecc, 3); // Floating-point input denormal exception output mask. // 0 = Mask floating-point input denormal exception output. The output FPIDCm is forced to zero. This is // the reset value. // 1 = Propagate floating-point input denormal exception flag FPSCR.IDC to output FPIDCm register_bit!(sactlr, idc, 8); // Floating-point divide-by-zero exception output mask. // 0 = Mask floating-point divide-by-zero exception output. The output FPDZCm is forced to zero. This is // the reset value. // 1 = Propagate floating-point divide-by-zero exception flag FPSCR.DZC to output FPDZCm register_bit!(sactlr, dzc, 9); // Floating-point invalid operation exception output mask. // 0 = Mask floating-point invalid operation exception output. The output FPIOCm is forced to zero. This is // the reset value. // 1 = Propagate floating-point invalid operation exception flag FPSCR.IOC to output FPIOCm. register_bit!(sactlr, ioc, 10); // Floating-point underflow exception output mask. // 0 = Mask floating-point underflow exception output. The output FPUFCm is forced to zero. This is the // reset value. // 1 = Propagate floating-point underflow exception flag FPSCR.UFC to output FPUFCm register_bit!(sactlr, ufc, 11); // Floating-point overflow exception output mask. // 0 = Mask floating-point overflow exception output. The output FPOFCm is forced to zero. This is the reset // value. // 1 = Propagate floating-point overflow exception flag FPSCR.OFC to output FPOFCm register_bit!(sactlr, ofc, 12); // Floating-point inexact exception output mask. // 0 = Mask floating-point inexact exception output. The output FPIXCm is forced to zero. This is the reset // value. // 1 = Propagate floating point inexact exception flag FPSCR.IXC to output FPIXCm register_bit!(sactlr, ixc, 13); // Out-of-order FMACS control. // 0 = Enabled. This is the reset value. // 1 = Disabled register_bit!(sactlr, doofmacs, 16); // Out-of-order double-precision floating point instruction control. // 0 = Enabled. This is the reset value. // 1 = Disabled. register_bit!(sactlr, doodpfp, 17); // F1/F3/F4dual issue control. // 0 = Enabled. This is the reset value. // 1 = Disabled. register_bit!(sactlr, ddi, 18); // F2_Id/F2_st/F2D dual issue control. // 0 = Enabled. This is the reset value. // 1 = Disabled register_bit!(sactlr, df2di, 19); // F6 dual issue control. // 0 = Enabled. This is the reset value. // 1 = Disabled register_bit!(sactlr, df6di, 20); // Enable random 2-bit error generation in cache RAMs. This bit has no effect unless ECC is configured, see // Configurable options on page 1-6. // 0 = Disabled. This is the reset value. // 1 = Enabled. register_bit!(sactlr, dr2b, 21); // Disable hard-error support in the caches. // 0 = Enabled. The cache logic recovers from some hard errors. // 1 = Disabled. Most hard errors in the caches are fatal. This is the reset value register_bit!(sactlr, dche, 22); /// Data Fault Status Register pub struct DFSR; wrap_reg!(dfsr); def_reg_r!(DFSR, dfsr::Read, "mrc p15, 0, $0, c5, c0, 0"); // Indicates the type of fault generated. To determine the data fault, you must use bit [12] and bit [10] in // conjunction with bits [3:0]. register_bits!(dfsr, status, u8, 0, 3); register_bit!(dfsr, s, 10); // Indicates whether a read or write access caused an abort: // 0 = read access caused the abort // 1 = write access caused the abort. register_bit!(dfsr, rw, 11); // Distinguishes between an AXI Decode or Slave error on an external abort. This bit is only valid for external // aborts. For all other aborts types of abort, this bit is set to zero: // 0 = AXI Decode error (DECERR), or AHB error, caused the abort // 1 = AXI Slave error (SLVERR), or unsupported exclusive access, for example exclusive access using the AHB // peripheral port, caused the abort. register_bit!(dfsr, sd, 12); /// Data Fault Address Register pub struct DFAR; def_reg_r!(DFAR, u32, "mrc p15, 0, $0, c6, c0, 0"); /// MPU Type Register pub struct MPUIR; wrap_reg!(mpuir); def_reg_r!(MPUIR, mpuir::Read, "mrc p15, 0, $0, c0, c0, 4"); // number of unified MPU regions (0, 12, or 16) register_bits!(mpuir, d_region, u8, 8, 15); /// MPU Region Number Register pub struct RGNR; wrap_reg!(rgnr); def_reg_r!(RGNR, rgnr::Read, "mrc p15, 0, $0, c6, c2, 0"); def_reg_w!(RGNR, rgnr::Write, "mcr p15, 0, $0, c6, c2, 0"); register_bits!(rgnr, region, u8, 0, 3); /// MPU Region Access Control Registers pub struct RACTLR; wrap_reg!(ractlr); def_reg_r!(RACTLR, ractlr::Read, "mrc p15, 0, $0, c6, c1, 4"); def_reg_w!(RACTLR, ractlr::Write, "mcr p15, 0, $0, c6, c1, 4"); // bufferable register_bit!(ractlr, b, 0); // cacheable register_bit!(ractlr, c, 1); // shareable register_bit!(ractlr, s, 2); // type extension register_bits!(ractlr, tex, u8, 3, 5); // Access permission register_bits!(ractlr, ap, u8, 8, 10); // Execute Never. Determines if a region of memory is executable: // 0 = all instruction fetches enabled // 1 = no instruction fetches enabled. register_bit!(ractlr, xn, 12); /// MPU Region Size and Enable Registers pub struct RSER; wrap_reg!(rser); def_reg_r!(RSER, rser::Read, "mrc p15, 0, $0, c6, c1, 2"); def_reg_w!(RSER, rser::Write, "mcr p15, 0, $0, c6, c1, 2"); // enable region register_bit!(rser, enable, 0); // Defines the region size: // b00000 - b00011=Unpredictable // b00100 = 32 bytes // b00101 = 64 bytes // b00110 = 128 bytes // b00111 = 256 bytes // b01000 = 512 bytes // b01001 = 1KB // b01010 = 2KB // b01011 = 4KB // b01100 = 8KB // b01101 = 16KB // b01110 = 32KB // b01111 = 64KB // b10000 = 128KB // b10001 = 256KB // b10010 = 512KB // b10011 = 1MB // b10100 = 2MB // b10101 = 4MB // b10110 = 8MB // b10111 = 16MB // b11000 = 32MB // b11001 = 64MB // b11010 = 128MB // b11011 = 256MB // b11100 = 512MB // b11101 = 1GB // b11110 = 2GB // b11111 = 4GB register_bits!(rser, region_size, u8, 1, 5); // Each bit position represents a sub-region, 0-7. // Bit [8] corresponds to sub-region 0 // ... // Bit [15] corresponds to sub-region 7 // The meaning of each bit is: // 0 = address range is part of this region // 1 = address range is not part of this region register_bits!(rser, subregion_disable, u8, 8, 15); /// MPU Region Base Address Registers pub struct RBAR; wrap_reg!(rbar); def_reg_r!(RBAR, rbar::Read, "mrc p15, 0, $0, c6, c1, 0"); def_reg_w!(RBAR, rbar::Write, "mcr p15, 0, $0, c6, c1, 0"); // base address register_bits!(rbar, base_address, u32, 5, 31); // TODO: TCM registers (R5 TRM sec 4.3.23-25)