mem.zig (2560B)
1 pub const BASE_ADDRESS: usize = 0x2000_0000; 2 3 // Forces all outstanding explicit memory transactions to complete before executing 4 // another **instruction**. Other instructions can execute out of order 5 inline fn dsb() void { 6 asm volatile ("mcr p15, 0, %[reg], c7, c10, 4" 7 : 8 : [reg] "r" (0), 9 ); 10 } 11 // Forces all outstanding explicit memory transactions to complete before executing 12 // another **memory transaction**. No instruction can execute until this is complete 13 inline fn dmb() void { 14 asm volatile ("mcr p15, 0, %[reg], c7, c10, 5" 15 : 16 : [reg] "r" (0), 17 ); 18 } 19 // Flush Prefetch Buffer 20 inline fn imb() void { 21 asm volatile ("mcr p15, 0, %[reg], c7, c5, 4" 22 : 23 : [reg] "r" (0), 24 ); 25 } 26 27 // Prevents the compiler reordering statements 28 inline fn compiler_barrier() void { 29 asm volatile ("" ::: .{ .memory = true }); 30 } 31 32 const BarrierKind = enum { 33 Strict, 34 Weak, 35 }; 36 37 const Operation = enum { 38 Read, 39 Write, 40 Instruction, 41 Compiler, 42 }; 43 44 pub inline fn barrier(comptime op: Operation) void { 45 switch (op) { 46 .Write => dsb(), 47 .Read => dmb(), 48 .Instruction => imb(), 49 .Compiler => compiler_barrier(), 50 } 51 } 52 53 pub inline fn put_u32(address: *allowzero u32, value: u32) void { 54 asm volatile ("str %[value], [%[address]]" 55 : 56 : [value] "r" (value), 57 [address] "r" (address), 58 ); 59 } 60 61 pub inline fn put_u32_barrier( 62 address: *allowzero u32, 63 value: u32, 64 ) void { 65 put_u32(address, value); 66 barrier(.Write); 67 } 68 69 pub inline fn get_u32(address: *allowzero u32) u32 { 70 return asm volatile ("ldr %[result], [%[address]]" 71 : [result] "=r" (-> u32), 72 : [address] "r" (address), 73 ); 74 } 75 76 pub inline fn get_u32_barrier(address: *allowzero u32) u32 { 77 barrier(.Read); 78 return get_u32(address); 79 } 80 81 pub const CriticalSection = struct { 82 const Self = @This(); 83 84 saved_cpsr: u32, 85 86 // TODO; barrier? 87 pub inline fn enter() Self { 88 var cpsr: u32 = undefined; 89 90 asm volatile ( 91 \\ mrs %[cpsr], cpsr 92 \\ cpsid i 93 : [cpsr] "=r" (cpsr), 94 : 95 : .{ .memory = true }); 96 97 return .{ .saved_cpsr = cpsr }; 98 } 99 100 pub inline fn exit(self: Self) void { 101 asm volatile ( 102 \\ msr cpsr_c, %[cpsr] 103 : 104 : [cpsr] "r" (self.saved_cpsr), 105 : .{ 106 .cpsr = true, 107 .memory = true, 108 }); 109 } 110 }; 111 112 pub const enter_critical_section = CriticalSection.enter;