|
1 |
| -import MMIOVolatile |
| 1 | +import RP2040 |
2 | 2 |
|
3 | 3 | /// crt0.S calls this immediately before main.
|
4 | 4 | @_cdecl("runtime_init")
|
@@ -91,211 +91,3 @@ func delayByCounting(to limit: Int32) {
|
91 | 91 | }
|
92 | 92 | return
|
93 | 93 | }
|
94 |
| - |
95 |
| -func gpioInit(pin: Int) { |
96 |
| - gpioSetDirection(pin: pin, out: true) |
97 |
| - gpioSet(pin: pin, high: false) |
98 |
| - gpioSetFunction(pin: pin, .SIO) |
99 |
| -} |
100 |
| - |
101 |
| -enum GPIOFunction: Int { |
102 |
| - case XIP = 0 |
103 |
| - case SPI = 1 |
104 |
| - case UART = 2 |
105 |
| - case I2C = 3 |
106 |
| - case PWM = 4 |
107 |
| - case SIO = 5 |
108 |
| - case PIO0 = 6 |
109 |
| - case PIO1 = 7 |
110 |
| - case GPCK = 8 |
111 |
| - case USB = 9 |
112 |
| - case NULL = 0x1f |
113 |
| -}; |
114 |
| - |
115 |
| -// SIO = the RP2040’s single-cycle I/O block. |
116 |
| -// Reference documentation: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#tab-registerlist_sio |
117 |
| -let SIO_BASE: UInt32 = 0xd0000000 |
118 |
| -let SIO_GPIO_IN_OFFSET: UInt32 = 0x00000004 |
119 |
| -let SIO_GPIO_OUT_SET_OFFSET: UInt32 = 0x00000014 |
120 |
| -let SIO_GPIO_OUT_CLR_OFFSET: UInt32 = 0x00000018 |
121 |
| -let SIO_GPIO_OUT_ENABLE_SET_OFFSET: UInt32 = 0x00000024 |
122 |
| -let SIO_GPIO_OUT_ENABLE_CLR_OFFSET: UInt32 = 0x00000028 |
123 |
| - |
124 |
| -// Reference to datasheet: https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf#tab-registerlist_pads_bank0 |
125 |
| -let PADS_BANK0_BASE: UInt32 = 0x4001c000 |
126 |
| -let PADS_BANK0_GPIO0_OFFSET: UInt32 = 0x00000004 |
127 |
| -let PADS_BANK0_GPIO0_BITS: UInt32 = 0x000000ff |
128 |
| -let PADS_BANK0_GPIO0_RESET: UInt32 = 0x00000056 |
129 |
| -let PADS_BANK0_GPIO0_IE_BITS: UInt32 = 0x00000040 |
130 |
| -let PADS_BANK0_GPIO0_OD_BITS: UInt32 = 0x00000080 |
131 |
| -let PADS_BANK0_GPIO0_PUE_BITS: UInt32 = 0x00000008 |
132 |
| -let PADS_BANK0_GPIO0_PUE_LSB: UInt32 = 3 |
133 |
| -let PADS_BANK0_GPIO0_PDE_BITS: UInt32 = 0x00000004 |
134 |
| -let PADS_BANK0_GPIO0_PDE_LSB: UInt32 = 2 |
135 |
| - |
136 |
| -let IO_BANK0_BASE: UInt32 = 0x40014000 |
137 |
| -let IO_BANK0_GPIO0_CTRL_OFFSET: UInt32 = 0x00000004 |
138 |
| -let IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB = 0 |
139 |
| - |
140 |
| -/// Select function for this GPIO, and ensure input/output are enabled at the pad. |
141 |
| -/// This also clears the input/output/irq override bits. |
142 |
| -func gpioSetFunction(pin: Int, _ function: GPIOFunction) { |
143 |
| - // Set input enable on, output disable off |
144 |
| - let padsBank = UnsafeMutablePointer<UInt32>(bitPattern: UInt(PADS_BANK0_BASE) + UInt(PADS_BANK0_GPIO0_OFFSET) + (UInt(pin) * UInt(MemoryLayout<UInt32>.stride)))! |
145 |
| - hwWriteMasked( |
146 |
| - address: padsBank, |
147 |
| - values: PADS_BANK0_GPIO0_IE_BITS, |
148 |
| - mask: PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS |
149 |
| - ) |
150 |
| - // Zero all fields apart from fsel; we want this IO to do what the peripheral tells it. |
151 |
| - // This doesn't affect e.g. pullup/pulldown, as these are in pad controls. |
152 |
| - let controlReg = UnsafeMutablePointer<UInt32>(bitPattern: UInt(IO_BANK0_BASE) + UInt(pin * 2 * MemoryLayout<UInt32>.stride) + UInt(IO_BANK0_GPIO0_CTRL_OFFSET))! |
153 |
| - mmio_volatile_store_uint32_t(controlReg, UInt32(function.rawValue) << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) |
154 |
| -} |
155 |
| - |
156 |
| -func gpioSetDirection(pin: Int, out: Bool) { |
157 |
| - let mask: UInt32 = 1 << pin |
158 |
| - if out { |
159 |
| - gpioSetDirectionOutMasked(mask: mask) |
160 |
| - } else { |
161 |
| - gpioSetDirectionInMasked(mask: mask) |
162 |
| - } |
163 |
| -} |
164 |
| - |
165 |
| -func gpioSetDirectionOutMasked(mask: UInt32) { |
166 |
| - // sio_hw->gpio_oe_set = mask; |
167 |
| - let ptr = UnsafeMutablePointer<UInt32>(bitPattern: UInt(SIO_BASE + SIO_GPIO_OUT_ENABLE_SET_OFFSET))! |
168 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
169 |
| -} |
170 |
| - |
171 |
| -func gpioSetDirectionInMasked(mask: UInt32) { |
172 |
| - // sio_hw->gpio_oe_clr = mask; |
173 |
| - let ptr = UnsafeMutablePointer<UInt32>(bitPattern: UInt(SIO_BASE + SIO_GPIO_OUT_ENABLE_CLR_OFFSET))! |
174 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
175 |
| -} |
176 |
| - |
177 |
| -/// Set the specified GPIO to be pulled up. |
178 |
| -func gpioPullUp(pin: Int) { |
179 |
| - gpioSetPulls(pin: pin, up: true, down: false) |
180 |
| -} |
181 |
| - |
182 |
| -func gpioPullDown(pin: Int) { |
183 |
| - gpioSetPulls(pin: pin, up: false, down: true) |
184 |
| -} |
185 |
| - |
186 |
| -/// Select up and down pulls on specific GPIO. |
187 |
| -/// |
188 |
| -/// On RP2040, setting both pulls enables a "bus keep" function, |
189 |
| -/// i.e. weak pull to whatever is current high/low state of GPIO. |
190 |
| -func gpioSetPulls(pin: Int, up: Bool, down: Bool) { |
191 |
| - let padsBank = UnsafeMutablePointer<UInt32>(bitPattern: UInt(PADS_BANK0_BASE) + UInt(PADS_BANK0_GPIO0_OFFSET) + (UInt(pin) * UInt(MemoryLayout<UInt32>.stride)))! |
192 |
| - let value: UInt32 = (up ? 1 : 0) << PADS_BANK0_GPIO0_PUE_LSB |
193 |
| - | (down ? 1 : 0) << PADS_BANK0_GPIO0_PDE_LSB |
194 |
| - let mask = PADS_BANK0_GPIO0_PUE_BITS | PADS_BANK0_GPIO0_PDE_BITS |
195 |
| - hwWriteMasked(address: padsBank, values: value, mask: mask) |
196 |
| -} |
197 |
| - |
198 |
| -// Get the value of a single GPIO |
199 |
| -func gpioGet(pin: Int) -> Bool { |
200 |
| - let mask: UInt32 = 1 << pin |
201 |
| - // sio_hw->gpio_in |
202 |
| - let ptr = UnsafeMutablePointer<UInt32>(bitPattern: UInt(SIO_BASE + SIO_GPIO_IN_OFFSET))! |
203 |
| - let gpioIn = mmio_volatile_load_uint32_t(ptr) |
204 |
| - let isOn = (gpioIn & mask) != 0 |
205 |
| - return isOn |
206 |
| -} |
207 |
| - |
208 |
| -// bool gpio_get(uint gpio); |
209 |
| - |
210 |
| -func gpioSet(pin: Int, high: Bool) { |
211 |
| - let mask: UInt32 = 1 << pin |
212 |
| - if high { |
213 |
| - gpioSetMasked(mask: mask) |
214 |
| - } else { |
215 |
| - gpioClearMasked(mask: mask) |
216 |
| - } |
217 |
| -} |
218 |
| - |
219 |
| -func gpioSetMasked(mask: UInt32) { |
220 |
| - // sio_hw->gpio_set = mask; |
221 |
| - let ptr = UnsafeMutablePointer<UInt32>(bitPattern: UInt(SIO_BASE + SIO_GPIO_OUT_SET_OFFSET))! |
222 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
223 |
| -} |
224 |
| - |
225 |
| -func gpioClearMasked(mask: UInt32) { |
226 |
| - // sio_hw->gpio_clr = mask; |
227 |
| - let ptr = UnsafeMutablePointer<UInt32>(bitPattern: UInt(SIO_BASE + SIO_GPIO_OUT_CLR_OFFSET))! |
228 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
229 |
| -} |
230 |
| - |
231 |
| -let RESETS_BASE: UInt32 = 0x4000c000 |
232 |
| -let RESETS_RESET_OFFSET: UInt32 = 0x00000000 |
233 |
| -let RESETS_RESET_DONE_OFFSET: UInt32 = 0x00000008 |
234 |
| -let RESETS_RESET_BITS: UInt32 = 0x01ffffff |
235 |
| -let RESETS_RESET_ADC_BITS: UInt32 = 0x00000001 |
236 |
| -let RESETS_RESET_IO_QSPI_BITS: UInt32 = 0x00000040 |
237 |
| -let RESETS_RESET_PADS_QSPI_BITS: UInt32 = 0x00000200 |
238 |
| -let RESETS_RESET_PLL_SYS_BITS: UInt32 = 0x00001000 |
239 |
| -let RESETS_RESET_PLL_USB_BITS: UInt32 = 0x00002000 |
240 |
| -let RESETS_RESET_RTC_BITS: UInt32 = 0x00008000 |
241 |
| -let RESETS_RESET_SPI0_BITS: UInt32 = 0x00010000 |
242 |
| -let RESETS_RESET_SPI1_BITS: UInt32 = 0x00020000 |
243 |
| -let RESETS_RESET_SYSCFG_BITS: UInt32 = 0x00040000 |
244 |
| -let RESETS_RESET_UART0_BITS: UInt32 = 0x00400000 |
245 |
| -let RESETS_RESET_UART1_BITS: UInt32 = 0x00800000 |
246 |
| -let RESETS_RESET_USBCTRL_BITS: UInt32 = 0x01000000 |
247 |
| - |
248 |
| -/// Reset the specified HW blocks |
249 |
| -func resetBlock(bits: UInt32) { |
250 |
| - let resets = UnsafeMutablePointer<UInt32>(bitPattern: UInt(RESETS_BASE + RESETS_RESET_OFFSET))! |
251 |
| - hwSetBits(address: resets, mask: bits) |
252 |
| -} |
253 |
| - |
254 |
| -/// Bring the specified HW blocks out of reset |
255 |
| -func unresetBlock(bits: UInt32) { |
256 |
| - let resets = UnsafeMutablePointer<UInt32>(bitPattern: UInt(RESETS_BASE + RESETS_RESET_OFFSET))! |
257 |
| - hwClearBits(address: resets, mask: bits) |
258 |
| -} |
259 |
| - |
260 |
| -/// Bring the specified HW blocks out of reset and wait for completion |
261 |
| -func unresetBlockAndWait(bits: UInt32) { |
262 |
| - unresetBlock(bits: bits) |
263 |
| - let resetDone = UnsafeMutablePointer<UInt32>(bitPattern: UInt(RESETS_BASE + RESETS_RESET_DONE_OFFSET))! |
264 |
| - while true { |
265 |
| - let isResetDone = ~mmio_volatile_load_uint32_t(resetDone) & bits == 0 |
266 |
| - if isResetDone { |
267 |
| - break |
268 |
| - } |
269 |
| - } |
270 |
| -} |
271 |
| - |
272 |
| -/// Set new values for a sub-set of the bits in a HW register. |
273 |
| -/// |
274 |
| -/// Sets destination bits to values specified in \p values, if and only if corresponding bit in \p write_mask is set. |
275 |
| -func hwWriteMasked(address: UnsafeMutablePointer<UInt32>, values: UInt32, mask writeMask: UInt32) { |
276 |
| - hwXORBits(address: address, mask: (address.pointee ^ values) & writeMask) |
277 |
| -} |
278 |
| - |
279 |
| -// Register address offsets for atomic RMW aliases |
280 |
| -let REG_ALIAS_RW_BITS: UInt32 = 0x0000 |
281 |
| -let REG_ALIAS_XOR_BITS: UInt32 = 0x1000 |
282 |
| -let REG_ALIAS_SET_BITS: UInt32 = 0x2000 |
283 |
| -let REG_ALIAS_CLR_BITS: UInt32 = 0x3000 |
284 |
| - |
285 |
| -func hwXORBits(address: UnsafeMutablePointer<UInt32>, mask: UInt32) { |
286 |
| - let rawPtr = UnsafeMutableRawPointer(address).advanced(by: Int(REG_ALIAS_XOR_BITS)) |
287 |
| - let ptr = rawPtr.assumingMemoryBound(to: UInt32.self) |
288 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
289 |
| -} |
290 |
| - |
291 |
| -func hwSetBits(address: UnsafeMutablePointer<UInt32>, mask: UInt32) { |
292 |
| - let rawPtr = UnsafeMutableRawPointer(address).advanced(by: Int(REG_ALIAS_SET_BITS)) |
293 |
| - let ptr = rawPtr.assumingMemoryBound(to: UInt32.self) |
294 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
295 |
| -} |
296 |
| - |
297 |
| -func hwClearBits(address: UnsafeMutablePointer<UInt32>, mask: UInt32) { |
298 |
| - let rawPtr = UnsafeMutableRawPointer(address).advanced(by: Int(REG_ALIAS_CLR_BITS)) |
299 |
| - let ptr = rawPtr.assumingMemoryBound(to: UInt32.self) |
300 |
| - mmio_volatile_store_uint32_t(ptr, mask) |
301 |
| -} |
0 commit comments