Unit PlatformARMv6

From Ultibo.org
Jump to: navigation, search

Return to Unit Reference


Description


Ultibo Platform Interface unit for ARMv6

The ARMv6 (ARM11) does not support WFI, WFE, DMB, DSB or ISB instructions, these must be done using MCR operations on the system control processor registers.

The ARMv6 supports the LDREX/STREX instructions for syncronisation (Lock/Mutex/Semaphore etc) but only if the MMU is enabled.

Constants



ARMv6 page tables shift ARMV6_PAGE_TABLES_*
ARMV6_PAGE_TABLES_SHIFT = 10;  


ARMv6 CP15 C0 main Id ARMV6_CP15_C0_MAINID_*
ARMV6_CP15_C0_MAINID_IMPLEMENTOR_MASK = ($FF shl 24);  
ARMV6_CP15_C0_MAINID_VARIANT_MASK = ($F shl 20);  
ARMV6_CP15_C0_MAINID_ARCHITECTURE_MASK = ($F shl 16);  
ARMV6_CP15_C0_MAINID_PARTNUMBER_MASK = ($FFF shl 4);  
ARMV6_CP15_C0_MAINID_REVISION_MASK = ($F shl 0);  
 
ARMV6_CP15_C0_MAINID_IMPLEMENTOR_ARM = ($41 shl 24);  
ARMV6_CP15_C0_MAINID_ARCHITECTURE_CPUID = ($F shl 16);  
ARMV6_CP15_C0_MAINID_PARTNUMBER_1176JZSF = ($B76 shl 4);  


ARMv6 CP15 C0 cache type ARMV6_CP15_C0_CTR_*
ARMV6_CP15_C0_CTR_CTYPE_MASK = ($F shl 25); The Cache type bits provide information about the cache architecture (b1110 in the ARM1176JZF-S processor)
ARMV6_CP15_C0_CTR_S = (1 shl 24); S = 1, indicates that the processor has separate instruction and data caches and not a unified cache
 
ARMV6_CP15_C0_CTR_DP = (1 shl 23); The P, Page, bit indicates restrictions on page allocation for bits [13:12] of the VA For ARM1176JZF-S processors, the P bit is set if the cache size is greater than 16KB.
ARMV6_CP15_C0_CTR_DSIZE_MASK = ($F shl 18); The Size field indicates the cache size in conjunction with the M bit
ARMV6_CP15_C0_CTR_DSIZE_128K = (8 shl 18); 128KB cache, not supported
ARMV6_CP15_C0_CTR_DSIZE_64K = (7 shl 18); 64KB cache
ARMV6_CP15_C0_CTR_DSIZE_32K = (6 shl 18); 32KB cache
ARMV6_CP15_C0_CTR_DSIZE_16K = (5 shl 18); 16KB cache
ARMV6_CP15_C0_CTR_DSIZE_8K = (4 shl 18); 8KB cache
ARMV6_CP15_C0_CTR_DSIZE_4K = (3 shl 18); 4KB cache
ARMV6_CP15_C0_CTR_DSIZE_2K = (2 shl 18); 2KB cache, not supported
ARMV6_CP15_C0_CTR_DSIZE_1K = (1 shl 18); 1KB cache, not supported
ARMV6_CP15_C0_CTR_DSIZE_05K = (0 shl 18); 0.5KB cache, not supported
ARMV6_CP15_C0_CTR_DASSOC_MASK = (7 shl 15); b010, indicates that the ARM1176JZF-S processor has 4-way associativity
ARMV6_CP15_C0_CTR_DM = (1 shl 14); Indicates the cache size and cache associativity values in conjunction with the Size and Assoc fields (In the ARM1176JZF-S processor the M bit is set to 0).
ARMV6_CP15_C0_CTR_DLEN_MASK = (3 shl 12); b10, indicates that ARM1176JZF-S processor has a cache line length of 8 words, that is 32 byte.
ARMV6_CP15_C0_CTR_DLEN_32 = (2 shl 12);  
 
ARMV6_CP15_C0_CTR_IP = (1 shl 11); The P, Page, bit indicates restrictions on page allocation for bits [13:12] of the VA For ARM1176JZF-S processors, the P bit is set if the cache size is greater than 16KB.
ARMV6_CP15_C0_CTR_ISIZE_MASK = ($F shl 6); The Size field indicates the cache size in conjunction with the M bit
ARMV6_CP15_C0_CTR_ISIZE_128K = (8 shl 6); 128KB cache, not supported
ARMV6_CP15_C0_CTR_ISIZE_64K = (7 shl 6); 64KB cache
ARMV6_CP15_C0_CTR_ISIZE_32K = (6 shl 6); 32KB cache
ARMV6_CP15_C0_CTR_ISIZE_16K = (5 shl 6); 16KB cache
ARMV6_CP15_C0_CTR_ISIZE_8K = (4 shl 6); 8KB cache
ARMV6_CP15_C0_CTR_ISIZE_4K = (3 shl 6); 4KB cache
ARMV6_CP15_C0_CTR_ISIZE_2K = (2 shl 6); 2KB cache, not supported
ARMV6_CP15_C0_CTR_ISIZE_1K = (1 shl 6); 1KB cache, not supported
ARMV6_CP15_C0_CTR_ISIZE_05K = (0 shl 6); 0.5KB cache, not supported
ARMV6_CP15_C0_CTR_IASSOC_MASK = (7 shl 3); b010, indicates that the ARM1176JZF-S processor has 4-way associativity
ARMV6_CP15_C0_CTR_IM = (1 shl 2); Indicates the cache size and cache associativity values in conjunction with the Size and Assoc fields (In the ARM1176JZF-S processor the M bit is set to 0).
ARMV6_CP15_C0_CTR_ILEN_MASK = (3 shl 0); b10, indicates that ARM1176JZF-S processor has a cache line length of 8 words, that is 32 bytes.
ARMV6_CP15_C0_CTR_ILEN_32 = (2 shl 0);  


ARMv6 CP15 C1 control ARMV6_CP15_C1_*
ARMV6_CP15_C1_FA_BIT = (1 shl 29); Force AP functionality in the MMU is enabled when set to 1 (Default 0)
ARMV6_CP15_C1_TR_BIT = (1 shl 28); TEX remap enabled when set to 1 (TEX[2:1] become page table bits for OS) (Default 0)
ARMV6_CP15_C1_EE_BIT = (1 shl 25); CPSR E bit is set to 1 on an exception when set to 1 (Default 0)
ARMV6_CP15_C1_VE_BIT = (1 shl 24); Interrupt vectors are defined by the VIC interface when set to 1 (Default 0)
ARMV6_CP15_C1_XP_BIT = (1 shl 23); Subpage AP bits disabled when set to 1 (Default 0)
ARMV6_CP15_C1_U_BIT = (1 shl 22); Unaligned data access support enabled when set to 1 (Default 0). The processor permits unaligned loads and stores and support for mixed endian data is enabled.
ARMV6_CP15_C1_FI_BIT = (1 shl 21); Low interrupt latency configuration enabled when set to 1 (Default 0)
ARMV6_CP15_C1_L4_BIT = (1 shl 15); Loads to PC do not set the T bit when set to 1 (ARMv4 behavior) (Default 0)
ARMV6_CP15_C1_RR_BIT = (1 shl 14); Predictable cache replacement strategy by round-robin replacement when set to 1 (Default 0)
ARMV6_CP15_C1_V_BIT = (1 shl 13); High exception vectors selected when set to 1, address range = 0xFFFF0000-0xFFFF001C (Default 0)
ARMV6_CP15_C1_I_BIT = (1 shl 12); L1 Instruction Cache enabled when set to 1 (Default 0)
ARMV6_CP15_C1_Z_BIT = (1 shl 11); Branch prediction enabled when set to 1 (Default 0)
ARMV6_CP15_C1_B_BIT = (1 shl 7); Big-endian word-invariant memory system when set to 1 (Default 0)
ARMV6_CP15_C1_C_BIT = (1 shl 2); L1 Data cache enabled when set to 1 (Default 0)
ARMV6_CP15_C1_A_BIT = (1 shl 1); Strict alignment fault checking enabled when set to 1 (Default 0)
ARMV6_CP15_C1_M_BIT = (1 shl 0); MMU enabled when set to 1 (Default 0)


ARMv6 CP15 C1 auxiliary control ARMV6_CP15_C1_AUX_*
ARMV6_CP15_C1_AUX_CZ = (1 shl 6); Controls the restriction of cache size to 16KB


ARMv6 CP15 C1 coprocessor access control ARMV6_CP15_C1_CP*
ARMV6_CP15_C1_CP0_NONE = (0 shl 0); Access denied (Default)
ARMV6_CP15_C1_CP0_SYS = (1 shl 0); Privileged mode access only
ARMV6_CP15_C1_CP0_USER = (3 shl 0); Privileged and User mode access
 
ARMV6_CP15_C1_CP1_NONE = (0 shl 2); Access denied (Default)
ARMV6_CP15_C1_CP1_SYS = (1 shl 2); Privileged mode access only
ARMV6_CP15_C1_CP1_USER = (3 shl 2); Privileged and User mode access
 
ARMV6_CP15_C1_CP2_NONE = (0 shl 4); Access denied (Default)
ARMV6_CP15_C1_CP2_SYS = (1 shl 4); Privileged mode access only
ARMV6_CP15_C1_CP2_USER = (3 shl 4); Privileged and User mode access
 
ARMV6_CP15_C1_CP3_NONE = (0 shl 6); Access denied (Default)
ARMV6_CP15_C1_CP3_SYS = (1 shl 6); Privileged mode access only
ARMV6_CP15_C1_CP3_USER = (3 shl 6); Privileged and User mode access
 
ARMV6_CP15_C1_CP4_NONE = (0 shl 8); Access denied (Default)
ARMV6_CP15_C1_CP4_SYS = (1 shl 8); Privileged mode access only
ARMV6_CP15_C1_CP4_USER = (3 shl 8); Privileged and User mode access
 
ARMV6_CP15_C1_CP5_NONE = (0 shl 10); Access denied (Default)
ARMV6_CP15_C1_CP5_SYS = (1 shl 10); Privileged mode access only
ARMV6_CP15_C1_CP5_USER = (3 shl 10); Privileged and User mode access
 
ARMV6_CP15_C1_CP6_NONE = (0 shl 12); Access denied (Default)
ARMV6_CP15_C1_CP6_SYS = (1 shl 12); Privileged mode access only
ARMV6_CP15_C1_CP6_USER = (3 shl 12); Privileged and User mode access
 
ARMV6_CP15_C1_CP7_NONE = (0 shl 14); Access denied (Default)
ARMV6_CP15_C1_CP7_SYS = (1 shl 14); Privileged mode access only
ARMV6_CP15_C1_CP7_USER = (3 shl 14); Privileged and User mode access
 
ARMV6_CP15_C1_CP8_NONE = (0 shl 16); Access denied (Default)
ARMV6_CP15_C1_CP8_SYS = (1 shl 16); Privileged mode access only
ARMV6_CP15_C1_CP8_USER = (3 shl 16); Privileged and User mode access
 
ARMV6_CP15_C1_CP9_NONE = (0 shl 18); Access denied (Default)
ARMV6_CP15_C1_CP9_SYS = (1 shl 18); Privileged mode access only
ARMV6_CP15_C1_CP9_USER = (3 shl 18); Privileged and User mode access
 
ARMV6_CP15_C1_CP10_NONE = (0 shl 20); Access denied (Default)
ARMV6_CP15_C1_CP10_SYS = (1 shl 20); Privileged mode access only
ARMV6_CP15_C1_CP10_USER = (3 shl 20); Privileged and User mode access
 
ARMV6_CP15_C1_CP11_NONE = (0 shl 22); Access denied (Default)
ARMV6_CP15_C1_CP11_SYS = (1 shl 22); Privileged mode access only
ARMV6_CP15_C1_CP11_USER = (3 shl 22); Privileged and User mode access
 
ARMV6_CP15_C1_CP12_NONE = (0 shl 24); Access denied (Default)
ARMV6_CP15_C1_CP12_SYS = (1 shl 24); Privileged mode access only
ARMV6_CP15_C1_CP12_USER = (3 shl 24); Privileged and User mode access
 
ARMV6_CP15_C1_CP13_NONE = (0 shl 26); Access denied (Default)
ARMV6_CP15_C1_CP13_SYS = (1 shl 26); Privileged mode access only
ARMV6_CP15_C1_CP13_USER = (3 shl 26); Privileged and User mode access
Coprocessors CP14 (Debug Control) and CP15 (System Control) are not affected by the Coprocessor Access Control Register


ARMv6 CP15 C2 translation table base ARMV6_CP15_C2_TTBR_*
ARMV6_CP15_C2_TTBR_BASE_MASK = $FFFFC000;  
ARMV6_CP15_C2_TTBR_RGN_OUTER_NONCACHED = (0 shl 3); Outer Noncacheable (Default)
ARMV6_CP15_C2_TTBR_RGN_OUTER_WRITE_ALLOCATE = (1 shl 3); Outer Write-back, Write Allocate
ARMV6_CP15_C2_TTBR_RGN_OUTER_WRITE_THROUGH = (2 shl 3); Outer Write-through, No Allocate on Write
ARMV6_CP15_C2_TTBR_RGN_OUTER_WRITE_BACK = (3 shl 3); Outer Write-back, No Allocate on Write
ARMV6_CP15_C2_TTBR_P = (1 shl 2); If the processor supports ECC, it indicates to the memory controller it is enabled or disabled. For ARM1176JZF-S processors this is 0.
ARMV6_CP15_C2_TTBR_S = (1 shl 1); Indicates the page table walk is to Shared memory if set to 1 (Default 0)
ARMV6_CP15_C2_TTBR_C_INNER_CACHED = (1 shl 0); Indicates the page table walk is Inner Cacheable if set to 1 (Default 0)


ARMv6 CP15 C3 domain access control ARMV6_CP15_C3_DOMAIN*
ARMV6_CP15_C3_DOMAIN0_NONE = (0 shl 0); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN0_CLIENT = (1 shl 0); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN0_MANAGER = (3 shl 0); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN1_NONE = (0 shl 2); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN1_CLIENT = (1 shl 2); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN1_MANAGER = (3 shl 2); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN2_NONE = (0 shl 4); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN2_CLIENT = (1 shl 4); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN2_MANAGER = (3 shl 4); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN3_NONE = (0 shl 6); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN3_CLIENT = (1 shl 6); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN3_MANAGER = (3 shl 6); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN4_NONE = (0 shl 8); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN4_CLIENT = (1 shl 8); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN4_MANAGER = (3 shl 8); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN5_NONE = (0 shl 10); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN5_CLIENT = (1 shl 10); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN5_MANAGER = (3 shl 10); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN6_NONE = (0 shl 12); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN6_CLIENT = (1 shl 12); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN6_MANAGER = (3 shl 12); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN7_NONE = (0 shl 14); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN7_CLIENT = (1 shl 14); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN7_MANAGER = (3 shl 14); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN8_NONE = (0 shl 16); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN8_CLIENT = (1 shl 16); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN8_MANAGER = (3 shl 16); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN9_NONE = (0 shl 18); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN9_CLIENT = (1 shl 18); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN9_MANAGER = (3 shl 18); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN10_NONE = (0 shl 20); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN10_CLIENT = (1 shl 20); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN10_MANAGER = (3 shl 20); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN11_NONE = (0 shl 22); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN11_CLIENT = (1 shl 22); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN11_MANAGER = (3 shl 22); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN12_NONE = (0 shl 24); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN12_CLIENT = (1 shl 24); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN12_MANAGER = (3 shl 24); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN13_NONE = (0 shl 26); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN13_CLIENT = (1 shl 26); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN13_MANAGER = (3 shl 26); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN14_NONE = (0 shl 28); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN14_CLIENT = (1 shl 28); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN14_MANAGER = (3 shl 28); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated
 
ARMV6_CP15_C3_DOMAIN15_NONE = (0 shl 30); No access, Any access generates a domain fault (Default)
ARMV6_CP15_C3_DOMAIN15_CLIENT = (1 shl 30); Client, Accesses are checked against the access permission bits in the TLB entry
ARMV6_CP15_C3_DOMAIN15_MANAGER = (3 shl 30); Manager, Accesses are not checked against the access permission bits in the TLB entry, so a permission fault cannot be generated


ARMv6 floating-point exception ARMV6_FPEXC_*
ARMV6_FPEXC_EN = (1 shl 30); Floating-point system is enabled and operates normally if set to 1 (Default 0)
ARMV6_FPEXC_EX = (1 shl 31); If EX is set to 0 then only FPSCR and FPEXC need to be preseved on a context switch (Default 0)


ARMv6 level one descriptor type ARMV6_L1D_TYPE_*
See page 6-36 of the ARM1176JZF-S Technical Reference Manual
These formats assume that the XP bit in the C1 control register is set to one to enable the ARMv6 format Page Tables
See page 6-39 of the ARM1176JZF-S Technical Reference Manual
Level One Page Table contains 4096 32bit (4 byte) entries for a total size of 16KB
 
ARMV6_L1D_TYPE_COARSE = 1; The entry points to a 1MB second-level page table. See page 6-40.
ARMV6_L1D_TYPE_SECTION = 2; The entry points to a either a 1MB Section of memory or a 16MB Supersection of memory
ARMV6_L1D_TYPE_SUPERSECTION = 2; Bit[18] of the descriptor selects between a Section and a Supersection


ARMv6 level one descriptor flag ARMV6_L1D_FLAG_*
See page 6-39 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L1D_FLAG_COARSE_NS = (1 shl 3); NS (Non Secure) Attribute bit to enable the support of TrustZone
ARMV6_L1D_FLAG_SECTION_NS = (1 shl 19); NS (Non Secure) Attribute bit to enable the support of TrustZone
ARMV6_L1D_FLAG_SUPERSECTION = (1 shl 18); The descriptor is a 16MB Supersection instead of a 1MB Section (Section Only)
ARMV6_L1D_FLAG_NOT_GLOBAL = (1 shl 17); The Not-Global (nG) bit, determines if the translation is marked as global (0), or process-specific (1) (Section Only)
ARMV6_L1D_FLAG_SHARED = (1 shl 16); The Shared (S) bit, determines if the translation is for Non-Shared (0), or Shared (1) memory. This only applies to Normal memory regions.

Device memory can be Shared or Non-Shared as determined by the TEX bits and the C and B bits (Section Only).

ARMV6_L1D_FLAG_APX = (1 shl 15); The access permissions extension (APX) bit, provides an extra access permission bit (Section Only)
ARMV6_L1D_FLAG_P = (1 shl 9); If the P bit is supported and set for the memory region, it indicates to the system memory controller that this memory region has ECC enabled. ARM1176JZF-S processors do not support the P bit.
ARMV6_L1D_FLAG_XN = (1 shl 4); The Execute-Never (XN) bit, determines if the region is Executable (0) or Not-executable(1) (Section Only)
ARMV6_L1D_FLAG_C = (1 shl 3); Cacheable (C) bit (Section Only)
ARMV6_L1D_FLAG_B = (1 shl 2); Bufferable (B) bit (Section Only)


ARMv6 level one descriptor mask ARMV6_L1D_*_MASK
See page 6-39 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L1D_COARSE_BASE_MASK = $FFFFFC00;  
ARMV6_L1D_SECTION_BASE_MASK = $FFF00000;  
ARMV6_L1D_SUPERSECTION_BASE_MASK = $FF000000;  
ARMV6_L1D_DOMAIN_MASK = ($F shl 5); Security Domain of the Descriptor
ARMV6_L1D_TEX_MASK = (7 shl 12); Type extension field bits (Section Only)
ARMV6_L1D_AP_MASK = (3 shl 10); Access permission bits (Section Only)


ARMv6 level one descriptor TEX value ARMV6_L1D_TEX*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual (Section Only)
 
ARMV6_L1D_TEX0 = (0 shl 12);  
ARMV6_L1D_TEX1 = (1 shl 12);  
ARMV6_L1D_TEX2 = (2 shl 12);  
ARMV6_L1D_TEX4 = (4 shl 12); Only used for Cacheable memory values
ARMV6_L1D_TEX5 = (5 shl 12); Only used for Cacheable memory values
ARMV6_L1D_TEX6 = (6 shl 12); Only used for Cacheable memory values
ARMV6_L1D_TEX7 = (7 shl 12); Only used for Cacheable memory values


ARMv6 level one descriptor AP value ARMV6_L1D_AP*
See page 6-12 of the ARM1176JZF-S Technical Reference Manual (Section Only)
 
ARMV6_L1D_AP0 = (0 shl 10);  
ARMV6_L1D_AP1 = (1 shl 10);  
ARMV6_L1D_AP2 = (2 shl 10);  
ARMV6_L1D_AP3 = (3 shl 10);  


ARMv6 level one descriptor permission value ARMV6_L1D_ACCESS_*
See page 6-12 of the ARM1176JZF-S Technical Reference Manual
This is not the full set of permissions as Ultibo always runs in priviledged mode
The XN bit can also be applied to control whether memory regions are executable or not
 
ARMV6_L1D_ACCESS_NONE = ARMV6_L1D_AP0; No Access for both Privileged and Unprivileged code
ARMV6_L1D_ACCESS_READONLY = ARMV6_L1D_FLAG_APX or ARMV6_L1D_AP3; Read-Only for both Privileged and Unprivileged code
ARMV6_L1D_ACCESS_READWRITE = ARMV6_L1D_AP3; Read-Write for both Privileged and Unprivileged code


ARMv6 level one descriptor cache value ARMV6_L1D_CACHE_*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L1D_CACHE_STRONGLY_ORDERED = ARMV6_L1D_TEX0; Strongly Ordered. (Always Shared)
ARMV6_L1D_CACHE_SHARED_DEVICE = ARMV6_L1D_TEX0 or ARMV6_L1D_FLAG_B; Device. (Always Shared)
ARMV6_L1D_CACHE_NORMAL_WRITE_THROUGH = ARMV6_L1D_TEX0 or ARMV6_L1D_FLAG_C; Normal. Write Through (Shared if S bit set)
ARMV6_L1D_CACHE_NORMAL_WRITE_BACK = ARMV6_L1D_TEX0 or ARMV6_L1D_FLAG_C or ARMV6_L1D_FLAG_B; Normal. Write Back (Shared if S bit set)
ARMV6_L1D_CACHE_NORMAL_NONCACHED = ARMV6_L1D_TEX1; Normal. Noncacheable (Shared if S bit set)
ARMV6_L1D_CACHE_NONSHARED_DEVICE = ARMV6_L1D_TEX2; Device. (Not Shared)


ARMv6 level two descriptor type ARMV6_L2D_TYPE_*
See page 6-40 of the ARM1176JZF-S Technical Reference Manual
Level Two Page Table contains 256 32bit (4 byte) entries for a total size of 1KB
 
ARMV6_L2D_TYPE_LARGE = 1; The entry points to a 64KB Large page in memory
ARMV6_L2D_TYPE_SMALL = 2; The entry points to a 4KB Extended small page in memory. Bit[0] of the entry is the XN (Execute Never) bit for the entry.


ARMv6 level two descriptor flag ARMV6_L2D_FLAG_*
See page 6-40 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_FLAG_LARGE_XN = (1 shl 15); The Execute-Never (XN) bit, determines if the region is Executable (0) or Not-executable(1)
ARMV6_L2D_FLAG_SMALL_XN = (1 shl 0); The Execute-Never (XN) bit, determines if the region is Executable (0) or Not-executable(1)
ARMV6_L2D_FLAG_NOT_GLOBAL = (1 shl 11); The Not-Global (nG) bit, determines if the translation is marked as global (0), or process-specific (1)
ARMV6_L2D_FLAG_SHARED = (1 shl 10); The Shared (S) bit, determines if the translation is for Non-Shared (0), or Shared (1) memory. This only applies to Normal memory regions.

Device memory can be Shared or Non-Shared as determined by the TEX bits and the C and B bits

ARMV6_L2D_FLAG_APX = (1 shl 9); The access permissions extension (APX) bit, provides an extra access permission bit.
ARMV6_L2D_FLAG_C = (1 shl 3); Cacheable (C) bit
ARMV6_L2D_FLAG_B = (1 shl 2); Bufferable (B) bit


ARMv6 level two descriptor mask ARMV6_L2D_*_MASK
See page 6-40 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_LARGE_BASE_MASK = $FFFF0000;  
ARMV6_L2D_SMALL_BASE_MASK = $FFFFF000;  
ARMV6_L2D_LARGE_TEX_MASK = (7 shl 12); Type extension field bits
ARMV6_L2D_SMALL_TEX_MASK = (7 shl 6); Type extension field bits
ARMV6_L2D_AP_MASK = (3 shl 4); Access permission bits


ARMv6 level two descriptor large TEX value ARMV6_L2D_LARGE_TEX*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_LARGE_TEX0 = (0 shl 12);  
ARMV6_L2D_LARGE_TEX1 = (1 shl 12);  
ARMV6_L2D_LARGE_TEX2 = (2 shl 12);  
ARMV6_L2D_LARGE_TEX4 = (4 shl 12);  
ARMV6_L2D_LARGE_TEX5 = (5 shl 12); Only used for Cacheable memory values
ARMV6_L2D_LARGE_TEX6 = (6 shl 12); Only used for Cacheable memory values
ARMV6_L2D_LARGE_TEX7 = (7 shl 12); Only used for Cacheable memory values


ARMv6 level two descriptor small TEX value ARMV6_L2D_SMALL_TEX*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_SMALL_TEX0 = (0 shl 6);  
ARMV6_L2D_SMALL_TEX1 = (1 shl 6);  
ARMV6_L2D_SMALL_TEX2 = (2 shl 6);  
ARMV6_L2D_SMALL_TEX4 = (4 shl 6);  
ARMV6_L2D_SMALL_TEX5 = (5 shl 6); Only used for Cacheable memory values
ARMV6_L2D_SMALL_TEX6 = (6 shl 6); Only used for Cacheable memory values
ARMV6_L2D_SMALL_TEX7 = (7 shl 6); Only used for Cacheable memory values


ARMv6 level two descriptor AP value ARMV6_L2D_AP*
See page 6-12 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_AP0 = (0 shl 4);  
ARMV6_L2D_AP1 = (1 shl 4);  
ARMV6_L2D_AP2 = (2 shl 4);  
ARMV6_L2D_AP3 = (3 shl 4);  


ARMv6 level two descriptor permission value ARMV6_L2D_ACCESS_*
See page 6-12 of the ARM1176JZF-S Technical Reference Manual)
This is not the full set of permissions as Ultibo always runs in priviledged mode
The XN bit can also be applied to control whether memory regions are executable or not
 
ARMV6_L2D_ACCESS_NONE = ARMV6_L2D_AP0; No Access for both Privileged and Unprivileged code
ARMV6_L2D_ACCESS_READONLY = ARMV6_L2D_FLAG_APX or ARMV6_L2D_AP3; Read-Only for both Privileged and Unprivileged code
ARMV6_L2D_ACCESS_READWRITE = ARMV6_L2D_AP3; Read-Write for both Privileged and Unprivileged code


ARMv6 level two descriptor large cache value ARMV6_L2D_LARGE_CACHE_*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_LARGE_CACHE_STRONGLY_ORDERED = ARMV6_L2D_LARGE_TEX0; Strongly Ordered. (Always Shared)
ARMV6_L2D_LARGE_CACHE_SHARED_DEVICE = ARMV6_L2D_LARGE_TEX0 or ARMV6_L2D_FLAG_B; Device. (Always Shared)
ARMV6_L2D_LARGE_CACHE_NORMAL_WRITE_THROUGH = ARMV6_L2D_LARGE_TEX0 or ARMV6_L2D_FLAG_C; Normal. Write Through (Shared if S bit set)
ARMV6_L2D_LARGE_CACHE_NORMAL_WRITE_BACK = ARMV6_L2D_LARGE_TEX0 or ARMV6_L2D_FLAG_C or ARMV6_L2D_FLAG_B; Normal. Write Back (Shared if S bit set)
ARMV6_L2D_LARGE_CACHE_NORMAL_NONCACHED = ARMV6_L2D_LARGE_TEX1; Normal. Noncacheable (Shared if S bit set)
ARMV6_L2D_LARGE_CACHE_NONSHARED_DEVICE = ARMV6_L2D_LARGE_TEX2; Device. (Not Shared)


ARMv6 level two descriptor small cache value ARMV6_L2D_SMALL_CACHE_*
See page 6-15 of the ARM1176JZF-S Technical Reference Manual
 
ARMV6_L2D_SMALL_CACHE_STRONGLY_ORDERED = ARMV6_L2D_SMALL_TEX0; Strongly Ordered. (Always Shared)
ARMV6_L2D_SMALL_CACHE_SHARED_DEVICE = ARMV6_L2D_SMALL_TEX0 or ARMV6_L2D_FLAG_B; Device. (Always Shared)
ARMV6_L2D_SMALL_CACHE_NORMAL_WRITE_THROUGH = ARMV6_L2D_SMALL_TEX0 or ARMV6_L2D_FLAG_C; Normal. Write Through (Shared if S bit set)
ARMV6_L2D_SMALL_CACHE_NORMAL_WRITE_BACK = ARMV6_L2D_SMALL_TEX0 or ARMV6_L2D_FLAG_C or ARMV6_L2D_FLAG_B; Normal. Write Back (Shared if S bit set)
ARMV6_L2D_SMALL_CACHE_NORMAL_NONCACHED = ARMV6_L2D_SMALL_TEX1; Normal. Noncacheable (Shared if S bit set)
ARMV6_L2D_SMALL_CACHE_NONSHARED_DEVICE = ARMV6_L2D_SMALL_TEX2; Device. (Not Shared)


ARMv6 specific constants ARMV6_*
ARMV6_CONTEXT_LENGTH = 50; Length of ARM context switch record in 32 bit words (includes fpexc, fpscr, d0-d15, r0-r12, lr, pc, cpsr)


Type definitions



ARMv6 page table initialization

TARMv6PageTableInit = procedure;

ARMv6 dispatch IRQ

TARMv6DispatchIRQ = function(CPUID:LongWord; Thread:TThreadHandle):TThreadHandle;

ARMv6 dispatch FIQ

TARMv6DispatchFIQ = function(CPUID:LongWord; Thread:TThreadHandle):TThreadHandle;

ARMv6 dispatch SWI

TARMv6DispatchSWI = function(CPUID:LongWord; Thread:TThreadHandle; Request:PSystemCallRequest):TThreadHandle;


Public variables



ARMv6 specific variables

ARMv6Initialized:Boolean;
ARMv6DummySTREX:LongWord; Variable to allow a dummy STREX operation to be performed after each context switch as required by ARM documentation

Page table handlers

ARMv6PageTableInitHandler:TARMv6PageTableInit;

IRQ handlers

ARMv6DispatchIRQHandler:TARMv6DispatchIRQ;

FIQ handlers

ARMv6DispatchFIQHandler:TARMv6DispatchFIQ;

SWI handlers

ARMv6DispatchSWIHandler:TARMv6DispatchSWI;


Function declarations



Initialization functions

procedure ARMv6Init;
Description: To be documented
Note None documented


ARMv6 platform functions

procedure ARMv6CPUInit; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6FPUInit; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6MMUInit;
Description: To be documented
Note None documented


procedure ARMv6CacheInit; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6PageTableInit;
Description: Initialize the Hardware Page Tables before enabling the MMU
Note See page 6-36 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6SystemCall(Number:LongWord; Param1,Param2,Param3:PtrUInt); assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6CPUGetMode:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6CPUGetState:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6CPUGetMainID:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6CPUGetModel:LongWord;
Description: To be documented
Note None documented


function ARMv6CPUGetRevision:LongWord;
Description: To be documented
Note None documented


function ARMv6CPUGetDescription:String;
Description: To be documented
Note None documented


function ARMv6FPUGetState:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6L1CacheGetType:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6L1DataCacheGetSize:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6L1DataCacheGetLineSize:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6L1InstructionCacheGetSize:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6L1InstructionCacheGetLineSize:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6Halt; assembler; nostackframe; public name '_haltproc';
Description: The purpose of the Wait For Interrupt operation is to put the processor in to a low power state
Note See Standby mode on page 10-3 of the ARM1176JZF-S Revision: r0p7 Technical Reference Manual


procedure ARMv6Pause; assembler; nostackframe;
Description: The purpose of the Wait For Interrupt operation is to put the processor in to a low power state
Note See Standby mode on page 10-3 of the ARM1176JZF-S Revision: r0p7 Technical Reference Manual


procedure ARMv6WaitForEvent; assembler; nostackframe;
Description: Wait For Event not available in ARMv6, do a Wait For Interrupt instead
Note None documented


procedure ARMv6WaitForInterrupt; assembler; nostackframe;
Description: The purpose of the Wait For Interrupt operation is to put the processor in to a low power state
Note See Standby mode on page 10-3 of the ARM1176JZF-S Revision: r0p7 Technical Reference Manual


procedure ARMv6DataMemoryBarrier; assembler; nostackframe;
Description: Perform a data memory barrier operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual

Note that this is also available in the FPC RTL as ReadBarrier/WriteBarrier See: \source\rtl\arm\arm.inc
Implementation is exactly the same for either


procedure ARMv6DataSynchronizationBarrier; assembler; nostackframe;
Description: Perform a data synchronization barrier operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InstructionMemoryBarrier; assembler; nostackframe;
Description: Perform a Flush Prefetch Buffer operation
Note The ARM1176JZF-S Technical Reference Manual states on page 5-10 (section 5.5) that a Flush Prefetch Buffer operation also acts as an IMB

See page 3-79 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateTLB; assembler; nostackframe;
Description: Perform an invalidate entire TLB (Unlocked/Unified) operation using the c8 (TLB Operations) register of system control coprocessor CP15
Note See page 3-86 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateDataTLB; assembler; nostackframe;
Description: Perform an invalidate data TLB (Unlocked/Data) operation using the c8 (TLB Operations) register of system control coprocessor CP15
Note See page 3-86 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateInstructionTLB; assembler; nostackframe;
Description: Perform an invalidate instruction TLB (Unlocked/Instruction) operation using the c8 (TLB Operations) register of system control coprocessor CP15
Note See page 3-86 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateCache; assembler; nostackframe;
Description: Perform an invalidate both caches operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanDataCache; assembler; nostackframe;
Description: Perform a clean entire data cache operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateDataCache; assembler; nostackframe;
Description: Perform an invalidate entire data cache operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanAndInvalidateDataCache; assembler; nostackframe;
Description: Perform a clean and invalidate entire data cache operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateInstructionCache; assembler; nostackframe;
Description: Perform an invalidate entire instruction cache operation using the c7 (Cache Operations) register of system control coprocessor CP15
Note See page 3-74 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanDataCacheRangeInternal(Address:PtrUInt; Size:LongWord); assembler; nostackframe;
Description: Perform a clean data cache range operation
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanDataCacheRange(Address:PtrUInt; Size:LongWord);
Description: Perform a clean data cache range, limiting the size for each operation to 4MB because some processors fail to correctly operate with larger ranges
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateDataCacheRangeInternal(Address:PtrUInt; Size:LongWord); assembler; nostackframe;
Description: Perform an invalidate data cache range operation
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateDataCacheRange(Address:PtrUInt; Size:LongWord);
Description: Perform an invalidate data cache range, limiting the size for each operation to 4MB because some processors fail to correctly operate with larger ranges
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanAndInvalidateDataCacheRangeInternal(Address:PtrUInt; Size:LongWord); assembler; nostackframe;
Description: Perform a clean and invalidate data cache range operation
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6CleanAndInvalidateDataCacheRange(Address:PtrUInt; Size:LongWord);
Description: Perform a clean and invalidate data cache range, limiting the size for each operation to 4MB because some processors fail to correctly operate with larger ranges
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateInstructionCacheRangeInternal(Address:PtrUInt; Size:LongWord); assembler; nostackframe;
Description: Perform an invalidate instruction cache range operation
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6InvalidateInstructionCacheRange(Address:PtrUInt; Size:LongWord);
Description: Perform an invalidate instruction cache range operation, limiting the size for each operation to 4MB because some processors fail to correctly operate with larger ranges
Note See page 3-71/3-76 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6FlushPrefetchBuffer; assembler; nostackframe;
Description: Perform a Flush Prefetch Buffer operation
Note See page 3-79 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6FlushBranchTargetCache; assembler; nostackframe;
Description: Perform a Flush Entire Branch Target Cache
Note See page 3-79 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6ContextSwitch(OldStack,NewStack:Pointer; NewThread:TThreadHandle); assembler; nostackframe;
Description: Perform a context switch from one thread to another as a result of a thread yielding, sleeping or waiting
OldStack The address to save the stack pointer to for the current thread (Passed in r0)
NewThread The address to restore the stack pointer from for the new thread (Passed in r1)
NewThread The handle of the new thread to switch to (Passed in r2)
Note At the point of the actual context switch (str sp/ldr sp) the thread stacks will look like this:


(See: ARMv6ThreadSetupStack for additional information)

(Base "Highest Address" of Stack)
.
.
.
.
cpsr <- The current program status register value to load on return from the context switch
lr/pc <- The address to return to from the context switch
lr <- The lr value prior to the context switch
r12 <-
r11 <-
r10 <-
r9 <-
r8 <-
r7 <-
r6 <- The value of these registers prior to the context switch
r5 <-
r4 <-
r3 <-
r2 <-
r1 <-
r0 <-

d15 <-
d14 <-
d13 <-
d12 <-
d11 <-
d10 <-
d9 <-
d8 <- The value of these floating point registers prior to the context switch
d7 <-
d6 <-
d5 <-
d4 <-
d3 <-
d2 <-
d1 <-
d0 <-

fpscr <- The floating point FPSCR register
fpexc <- The floating point FPEXC register (Current StackPointer points to here)
.
.
.
.
(Top "Lowest Address" of Stack)

This form of context switch uses r12 to save the cpsr value (and RFE to restore it). Because this context switch is called from a routine which will have saved the value of r12 (which is caller save in the ARM ABI) then we do not need to save the original value of r12.

The context switch will be performed from SYS mode to SYS mode, the cpsr value will include the control bits (Mode and IRQ/FIQ state) but not the flags values. Again the ARM ABI does not require that the flags be saved by the callee and so the caller would have accounted for any needed flags before calling. If the thread to be resumed was interrupted by an IRQ or FIQ then the cpsr will also contain the flags etc as they were at the point of interrupt. We do not need to account for the state bits in the cpsr since all operations are performed in ARM mode at present.

The main requirement of this routine is to ensure that the context record on the stack matches exactly that which is created on an interrupt and also that created by ThreadSetupStack for a new thread. If this is correct then the next context switch for any given thread can be either by a call to reschedule or by an interrupt. Equally a new thread can be first run from a context switch that resulted from either a call to reschedule or an interrupt.

Note that this routine could use:

pop (lr)
pop (r12)
msr cpsr_c, r12
mov pc, lr

To return but that would mess up the value of r12, lr and the cpsr flags etc if the thread being resumed was interrupted by an IRQ, FIQ or SWI. The use of RFE here allows for exactly the same behaviour no matter which way the context record is saved and restored.


procedure ARMv6ContextSwitchIRQ(OldStack,NewStack:Pointer; NewThread:TThreadHandle); assembler; nostackframe;
Description: Perform a context switch from one thread to another as a result of an interrupt request (IRQ)
OldStack The address to save the stack pointer to for the current thread (Passed in r0)
NewStack The address to restore the stack pointer from for the new thread (Passed in r1)
NewThread The handle of the new thread to switch to (Passed in r2)
Note At the point of the actual context switch (str sp/ldr sp) the thread stacks will look like this:


(See: ARMv6ThreadSetupStack for additional information)

(Base "Highest Address" of Stack)
.
.
.
.
cpsr <- The current program status register value to load on return from the context switch
lr/pc <- The address to return to from the context switch
lr <- The lr value prior to the context switch
r12 <-
r11 <-
r10 <-
r9 <-
r8 <-
r7 <-
r6 <- The value of these registers prior to the context switch
r5 <-
r4 <-
r3 <-
r2 <-
r1 <-
r0 <-

d15 <-
d14 <-
d13 <-
d12 <-
d11 <-
d10 <-
d9 <-
d8 <- The value of these floating point registers prior to the context switch
d7 <-
d6 <-
d5 <-
d4 <-
d3 <-
d2 <-
d1 <-
d0 <-

fpscr <- The floating point FPSCR register
fpexc <- The floating point FPEXC register (Current StackPointer points to here)
.
.
.
.
(Top "Lowest Address" of Stack)

This form of context switch relies on the IRQ handler to save the necessary registers including the lr, cpsr and other general registers from the point at which the thread was interrupted. The thread to be resumed may have been saved by a previous IRQ or by a call to the standard context switch from SchedulerReschule or it may be a new thread to be run for the first time. All of these result in the same context record on the stack and therefore can be resumed the same way.

The context switch will be performed by switching to SYS mode, exchanging the stack pointers and then returning to IRQ mode.


procedure ARMv6ContextSwitchFIQ(OldStack,NewStack:Pointer; NewThread:TThreadHandle); assembler; nostackframe;
Description: Perform a context switch from one thread to another as a result of a fast interrupt request (FIQ)
OldStack The address to save the stack pointer to for the current thread (Passed in r0)
NewStack The address to restore the stack pointer from for the new thread (Passed in r1)
NewThread The handle of the new thread to switch to (Passed in r2)
Note At the point of the actual context switch (str sp/ldr sp) the thread stacks will look like this:


(See: ARMv6ThreadSetupStack for additional information)

(Base "Highest Address" of Stack)
.
.
.
.
cpsr <- The current program status register value to load on return from the context switch
lr/pc <- The address to return to from the context switch
lr <- The lr value prior to the context switch
r12 <-
r11 <-
r10 <-
r9 <-
r8 <-
r7 <-
r6 <- The value of these registers prior to the context switch
r5 <-
r4 <-
r3 <-
r2 <-
r1 <-
r0 <-

d15 <-
d14 <-
d13 <-
d12 <-
d11 <-
d10 <-
d9 <-
d8 <- The value of these floating point registers prior to the context switch
d7 <-
d6 <-
d5 <-
d4 <-
d3 <-
d2 <-
d1 <-
d0 <-

fpscr <- The floating point FPSCR register
fpexc <- The floating point FPEXC register (Current StackPointer points to here)
.
.
.
.
(Top "Lowest Address" of Stack)

This form of context switch relies on the FIQ handler to save the necessary registers including the lr, cpsr and other general registers from the point at which the thread was interrupted. The thread to be resumed may have been saved by a previous FIQ or by a call to the standard context switch from SchedulerReschule or it may be a new thread to be run for the first time. All of these result in the same context record on the stack and therefore can be resumed the same way.

The context switch will be performed by switching to SYS mode, exchanging the stack pointers and then returning to FIQ mode.


procedure ARMv6ContextSwitchSWI(OldStack,NewStack:Pointer; NewThread:TThreadHandle);
Description: Perform a context switch from one thread to another as a result of a software interrupt (SWI)
OldStack The address to save the stack pointer to for the current thread (Passed in r0)
NewStack The address to restore the stack pointer from for the new thread (Passed in r1)
NewThread The handle of the new thread to switch to (Passed in r2)
Note At the point of the actual context switch (str sp/ldr sp) the thread stacks will look like this:


(See: ARMv6ThreadSetupStack for additional information)

(Base "Highest Address" of Stack)
.
.
.
.
cpsr <- The current program status register value to load on return from the context switch
lr/pc <- The address to return to from the context switch
lr <- The lr value prior to the context switch
r12 <-
r11 <-
r10 <-
r9 <-
r8 <-
r7 <-
r6 <- The value of these registers prior to the context switch
r5 <-
r4 <-
r3 <-
r2 <-
r1 <-
r0 <-

d15 <-
d14 <-
d13 <-
d12 <-
d11 <-
d10 <-
d9 <-
d8 <- The value of these floating point registers prior to the context switch
d7 <-
d6 <-
d5 <-
d4 <-
d3 <-
d2 <-
d1 <-
d0 <-

fpscr <- The floating point FPSCR register
fpexc <- The floating point FPEXC register (Current StackPointer points to here)
.
.
.
.
(Top "Lowest Address" of Stack)

This form of context switch relies on the SWI handler to save the necessary registers including the lr, cpsr and other general registers from the point at which the thread was interrupted. The thread to be resumed may have been saved by a previous SWI or by a call to the standard context switch from SchedulerReschule or it may be a new thread to be run for the first time. All of these result in the same context record on the stack and therefore can be resumed the same way.

The context switch will be performed by switching to SYS mode, exchanging the stack pointers and then returning to SWI (SVC) mode.


function ARMv6InterlockedOr(var Target:LongInt; Value:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic OR operation using LDREX/STREX
Note See page ??? of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedXor(var Target:LongInt; Value:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic XOR operation using LDREX/STREX
Note See page ??? of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedAnd(var Target:LongInt; Value:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic AND operation using LDREX/STREX
Note See page ??? of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedDecrement(var Target:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic decrement operation using LDREX/STREX
Note See page 8-6 of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedIncrement(var Target:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic increment operation using LDREX/STREX
Note See page 8-6 of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedExchange(var Target:LongInt; Source:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic exchange operation using LDREX/STREX
Note See page 8-6 of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedAddExchange(var Target:LongInt; Source:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic add and exchange operation using LDREX/STREX
Note See page 8-6 of the ARM1176JZF-S Technical Reference Manual


function ARMv6InterlockedCompareExchange(var Target:LongInt; Source,Compare:LongInt):LongInt; assembler; nostackframe;
Description: Perform an atomic compare and exchange operation using LDREX/STREX
Note See page 8-6 of the ARM1176JZF-S Technical Reference Manual


procedure ARMv6PageTableGetEntry(Address:PtrUInt; var Entry:TPageTableEntry);
Description: Get and Decode the entry in the Page Table that corresponds to the supplied virtual address
Note None documented


function ARMv6PageTableSetEntry(const Entry:TPageTableEntry):LongWord;
Description: Encode and Set an entry in the Page Table that corresponds to the supplied virtual address
Note None documented


function ARMv6VectorTableGetEntry(Number:LongWord):PtrUInt;
Description: Return the address of the specified vector table entry number
Note None documented


function ARMv6VectorTableSetEntry(Number:LongWord; Address:PtrUInt):LongWord;
Description: Set the supplied address as the value of the specified vector table entry number
Note None documented


function ARMv6FirstBitSet(Value:LongWord):LongWord; assembler; nostackframe;
Description: To be documented
Note ARM arm states that CLZ is supported for ARMv5 and above


function ARMv6CountLeadingZeros(Value:LongWord):LongWord; assembler; nostackframe;
Description: Equivalent of the GCC Builtin function __builtin_clz
Note ARM arm states that CLZ is supported for ARMv5 and above


ARMv6 thread functions

procedure ARMv6PrimaryInit; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6SpinLock(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Lock an existing Spin entry
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinUnlock(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Unlock an existing Spin entry
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinLockIRQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Lock an existing Spin entry, disable IRQ and save the previous IRQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinUnlockIRQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Unlock an existing Spin entry and restore the previous IRQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinLockFIQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Lock an existing Spin entry, disable FIQ and save the previous FIQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinUnlockFIQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Unlock an existing Spin entry and restore the previous FIQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinLockIRQFIQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Lock an existing Spin entry, disable IRQ and FIQ and save the previous IRQ/FIQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinUnlockIRQFIQ(Spin:PSpinEntry):LongWord; assembler; nostackframe;
Description: Unlock an existing Spin entry and restore the previous IRQ/FIQ state
Spin Pointer to the Spin entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6SpinCheckIRQ(Spin:PSpinEntry):Boolean;
Description: To be documented
Return True if the mask would enable IRQ on restore, False if it would not.


function ARMv6SpinCheckFIQ(Spin:PSpinEntry):Boolean;
Description: To be documented
Return True if the mask would enable FIQ on restore, False if it would not.


function ARMv6SpinExchangeIRQ(Spin1,Spin2:PSpinEntry):LongWord;
Description: To be documented
Note None documented


function ARMv6SpinExchangeFIQ(Spin1,Spin2:PSpinEntry):LongWord;
Description: To be documented
Note None documented


function ARMv6MutexLock(Mutex:PMutexEntry):LongWord; assembler; nostackframe;
Description: Lock an existing Mutex entry
Mutex Pointer to the Mutex entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6MutexUnlock(Mutex:PMutexEntry):LongWord; assembler; nostackframe;
Description: Unlock an existing Mutex entry
Mutex Pointer to the Mutex entry to lock (Passed in R0)
Return ERROR_SUCCESS if completed or another error code on failure (Returned in R0)


function ARMv6MutexTryLock(Mutex:PMutexEntry):LongWord; assembler; nostackframe;
Description: Try to lock an existing Mutex entry
Mutex Pointer to the Mutex entry to try to lock (Passed in R0)
Return ERROR_SUCCESS if completed, ERROR_LOCKED if already locked or another error code on failure (Returned in R0).


function ARMv6ThreadGetCurrent:TThreadHandle; assembler; nostackframe;
Description: Get the current thread Id from the c13 (Thread and process ID) register of system control coprocessor CP15
Note See page 3-129 of the ARM1176JZF-S Technical Reference Manual


function ARMv6ThreadSetCurrent(Thread:TThreadHandle):LongWord; assembler; nostackframe;
Description: To be documented
Note Set the current thread Id in the c13 (Thread and process ID) register of system control coprocessor CP15

See page 3-129 of the ARM1176JZF-S Technical Reference Manual


function ARMv6ThreadSetupStack(StackBase:Pointer; StartProc:TThreadStart; ReturnProc:TThreadEnd; Parameter:Pointer):Pointer;
Description: Set up the context record and arguments on the stack for a new thread
StackBase Pointer to the base (highest address) of the allocated stack (as returned by ThreadAllocateStack
StartProc The procedure the thread will start executing when resumed
ReturnProc The procedure the thread will return to on exit
Return Pointer to the starting address of the stack, which will be the Stack Pointer on the first context switch.
Note At the point of a context switch the thread stack will look like this:


(Base "Highest Address" of Stack)
.
.
.
.
cpsr <- The current program status register value to load on return from the context switch
(On Interrupt: Includes the flags and control bits for the interrupted thread)
(On Yield: Includes the control bits only for the yielded thread)
(On Create: Includes the control bits only for the new thread)
lr/pc <- The address to return to from the context switch
(On Interrupt: The location the thread was at before interrupt)
(On Yield: The location to return to in SchedulerReschedule)
(On Create: The location of StartProc for the new thread)

lr <- The lr value prior to the context switch
(On Interrupt: The value of lr before the thread was interrupted)
(On Yield: The location to return to in SchedulerReschedule)
(On Create: The location of ReturnProc for the new thread)

r12 <-
r11 <-
r10 <-
r9 <-
r8 <-
r7 <-
r6 <- The value of these registers prior to the context switch
r5 <- (On Interrupt: The values before the thread was interrupted)
r4 <- (On Yield: The values on return to SchedulerReschedule)
r3 <- (On Create: The values on entry to StartProc as set by ThreadSetupStack)
r2 <-
r1 <-
r0 <-

d15 <-
d14 <-
d13 <-
d12 <-
d11 <-
d10 <-
d9 <-
d8 <- The value of these floating point registers prior to the context switch
d7 <- (On Interrupt: The values before the thread was interrupted)
d6 <- (On Yield: The values on return to SchedulerReschedule)
d5 <- (On Create: The values on entry to StartProc as set by ThreadSetupStack)
d4 <-
d3 <-
d2 <-
d1 <-
d0 <-

fpscr <- The floating point FPSCR register
fpexc <- The floating point FPEXC register (Current StackPointer points to here)
.
.
.
.
(Top "Lowest Address" of Stack)

On exit from a standard context switch as performed by SchedulerReschedule the first value (Highest Address) of lr is used by the RFE (Return From Exception) instruction to load the pc which also loads the saved cpsr value.

On exit from an IRQ or FIQ context switch as performed by SchedulerSwitch the first value (Highest Address) of lr is used by the interrupt handler to return from the interrupt.

A standard context switch uses r12 to save the cpsr value (and RFE to restore it). Because the standard context switch is called from a routine which will have saved the value of r12 (which is caller save in the ARM ABI) then we do not need to save the original value of r12.

An IRQ or FIQ context switch uses the SRS (Store Return State) and RFE (Return From Exception) instructions to save and restore the cpsr value from the spsr value of either IRQ or FIQ mode.


ARMv6 IRQ functions

function ARMv6DispatchIRQ(CPUID:LongWord; Thread:TThreadHandle):TThreadHandle; inline;
Description: To be documented
Note None documented


ARMv6 FIQ functions

function ARMv6DispatchFIQ(CPUID:LongWord; Thread:TThreadHandle):TThreadHandle; inline;
Description: To be documented
Note None documented


ARMv6 SWI functions

function ARMv6DispatchSWI(CPUID:LongWord; Thread:TThreadHandle; Request:PSystemCallRequest):TThreadHandle; inline;
Description: To be documented
Note None documented


ARMv6 interrupt functions

procedure ARMv6ResetHandler; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6UndefinedInstructionHandler; assembler; nostackframe;
Description: Handle an undefined instruction exception
Note This routine is registered as the vector for undefined instruction exception in the vector table loaded during startup


procedure ARMv6SoftwareInterruptHandler; assembler; nostackframe;
Description: Handle a software interrupt (SWI) from a system call (SVC)
Note This routine is registered as the vector for SWI requests in the vector table loaded during startup. When the processor executes an SVC it switches to SWI mode, stores the address of the next instruction in the SWI mode link register (lr_svc) and saves the current program status register into the SWI mode saved program status register (spsr_svc).


The SWI handler first saves the SWI mode lr and spsr (which represent the location and state to return to) onto the SYS mode stack using the srsdb (Store Return State Decrement Before) instruction.

The SWI handler then switches to SYS mode and saves all the neccessary registers for the return to the interrupted thread before switching back to SWI mode in order to process the software interrupt. Because we arrive here from an interrupt the thread that was executing has no opportunity to save registers and will be unaware on return that it was interrupted. For this reason we must save all of the general purpose registers (r0 to r12) as well as the SYS mode link register (lr). We do not save the stack pointer (r13) because we use it to store the other registers and will return it to the correct value before we return from the SWI handler. The program counter (r15) does not need to be saved as it now points to this code.

The SystemCall function should pass the parameters of the call as follows:
R0 - System Call Number (eg SYSTEM_CALL_CONTEXT_SWITCH)
R1 - Parameter 1
R2 - Parameter 2
R3 - Parameter 3

To process the software interrupt
??????
To return from the software interrupt
??????


procedure ARMv6PrefetchAbortHandler; assembler; nostackframe;
Description: Handle a prefetch abort exception
Note This routine is registered as the vector for prefetch abort exception in the vector table loaded during startup


procedure ARMv6DataAbortHandler; assembler; nostackframe;
Description: Handle a data abort exception
Note This routine is registered as the vector for data abort exception in the vector table loaded during startup


procedure ARMv6ReservedHandler; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6IRQHandler; assembler; nostackframe;
Description: Handle an interrupt request IRQ from an interrupt source
Note This routine is registered as the vector for IRQ requests in the vector table loaded during startup.


At the end of each instruction the processor checks the IRQ line and if triggered it will lookup the vector in the vector table and jump to the routine listed.

When the processor receives an IRQ it switches to IRQ mode, stores the address of the next instruction in the IRQ mode link register (lr_irq) and saves the current program status register into the IRQ mode saved program status register (spsr_irq).

The IRQ handler first saves the IRQ mode lr and spsr (which represent the location and state to return to) onto the SYS mode stack using the srsdb (Store Return State Decrement Before) instruction.

The IRQ handler then switches to SYS mode and saves all the neccessary registers for the return to the interrupted thread before switching back to IRQ mode in order to process the interrupt request. Because we arrive here from an interrupt the thread that was executing has no opportunity to save registers and will be unaware on return that it was interrupted. For this reason we must save all of the general purpose registers (r0 to r12) as well as the SYS mode link register (lr). We do not save the stack pointer (r13) because we use it to store the other registers and will return it to the correct value before we return from the IRQ handler. The program counter (r15) does not need to be saved as it now points to this code.

To process the interrupt request the handler calls the DispatchIRQ function which will dispatch the interrupt to a registered handler for processing. The handler must clear the interrupt source before it returns or the interrupt will simply occur again immediately once reenabled.

To return from the interrupt request the handler uses the rfeia (Return From Exception Increment After) instruction which will load the pc and cpsr from the SYS mode stack.


procedure ARMv6FIQHandler; assembler; nostackframe;
Description: Handle a fast interrupt request FIQ from an interrupt source
Note This routine is registered as the vector for FIQ requests in the vector table loaded during startup.


At the end of each instruction the processor checks the FIQ line and if triggered it will lookup the vector in the vector table and jump to the routine listed.

When the processor receives an FIQ it switches to FIQ mode, stores the address of the next instruction in the FIQ mode link register (lr_fiq) and saves the current program status register into the FIQ mode saved program status register (spsr_fiq).

The FIQ handler first checks the spsr to determine if the task being interrupted is a normal thread or an exception or interrupt handler.

The FIQ handler then saves the FIQ mode lr and spsr (which represent the location and state to return to) onto eihter the SYS mode or SVC mode stack using the srsdb (Store Return State Decrement Before) instruction depending on the value of spsr.

The FIQ handler switches to SYS or SVC mode and saves all the neccessary registers for the return to the interrupted task before switching back to FIQ mode in order to process the interrupt request. Because we arrive here from an interrupt the task that was executing has no opportunity to save registers and will be unaware on return that it was interrupted. For this reason we must save all of the general purpose registers (r0 to r12) as well as the SYS mode link register (lr). We do not save the stack pointer (r13) because we use it to store the other registers and will return it to the correct value before we return from the FIQ handler. The program counter (r15) does not need to be saved as it now points to this code.

To process the fast interrupt request the handler calls the DispatchFIQ function which will dispatch the interrupt to a registered handler for processing. The handler must clear the interrupt source before it returns or the fast interrupt will simply occur again immediately once reenabled.

To return from the fast interrupt request the handler uses the rfeia (Return From Exception Increment After) instruction which will load the pc and cpsr from the stack of the current mode (SYS or SVC).


ARMv6 helper functions

function ARMv6GetFPEXC:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6GetFPSCR:LongWord; assembler; nostackframe;
Description: To be documented
Note None documented


procedure ARMv6StartMMU; assembler; nostackframe;
Description: To be documented
Note None documented


function ARMv6GetPageTableCoarse(Address:PtrUInt):LongWord;
Description: Get the descriptor for a Coarse Page Table entry (1MB)
Note See page 6-39 of the ARM1176JZF-S Technical Reference Manual


function ARMv6SetPageTableCoarse(Address,CoarseAddress:PtrUInt; Flags:Word):Boolean;
Description: Set the descriptor for a Coarse Page Table entry (1MB)
Note See page 6-39 of the ARM1176JZF-S Technical Reference Manual

Caller must call ARMv6InvalidateTLB after changes if MMU is enabled


function ARMv6GetPageTableLarge(Address:PtrUInt):LongWord;
Description: Get the descriptor for a Large Page Table entry (64KB)
Note See page 6-40 of the ARM1176JZF-S Technical Reference Manual


function ARMv6SetPageTableLarge(Address,PhysicalAddress:PtrUInt; Flags:Word):Boolean;
Description: Set the descriptor for a Large Page Table entry (64KB)
Note Large Page Table descriptors must begin on a 16 longword (64 byte) boundary and be repeated for 16 consecutive longwords

See page 6-40 of the ARM1176JZF-S Technical Reference Manual
Caller must call ARMv6InvalidateTLB after changes if MMU is enabled


function ARMv6GetPageTableSmall(Address:PtrUInt):LongWord;
Description: Get the descriptor for a Small Page Table entry (4KB)
Note See page 6-40 of the ARM1176JZF-S Technical Reference Manual


function ARMv6SetPageTableSmall(Address,PhysicalAddress:PtrUInt; Flags:Word):Boolean;
Description: Set the descriptor for a Small Page Table entry (4KB)
Note See page 6-40 of the ARM1176JZF-S Technical Reference Manual

Caller must call ARMv6InvalidateTLB after changes if MMU is enabled


function ARMv6GetPageTableSection(Address:PtrUInt):LongWord;
Description: Get the descriptor for a Page Table Section (1MB) or Supersection (16MB)
Note See page 6-39 of the ARM1176JZF-S Technical Reference Manual


function ARMv6SetPageTableSection(Address,PhysicalAddress:PtrUInt; Flags:LongWord):Boolean;
Description: Set the descriptor for a Page Table Section (1MB)
Note See page 6-39 of the ARM1176JZF-S Technical Reference Manual

Caller must call ARMv6InvalidateTLB after changes if MMU is enabled


function ARMv6SetPageTableSupersection(Address,PhysicalAddress:PtrUInt; Flags:LongWord):Boolean;
Description: Set the descriptor for a Page Table Supersection (16MB)
Note Supersection Page Table descriptors must begin on a 16 longword (64 byte) boundary and be repeated for 16 consecutive longwords

See page 6-39 of the ARM1176JZF-S Technical Reference Manual
Caller must call ARMv6InvalidateTLB after changes if MMU is enabled


Return to Unit Reference