Skip to content

Commit 8a320e7

Browse files
committed
Create separate target for RP2040 "SDK"
This separates app code and library code, as it should be.
1 parent badb2cf commit 8a320e7

File tree

3 files changed

+228
-210
lines changed

3 files changed

+228
-210
lines changed

Package.swift

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,24 @@ let package = Package(
1212
targets: [
1313
.target(
1414
name: "App",
15-
dependencies: ["MMIOVolatile", "RP2040Support"],
15+
dependencies: ["RP2040", "RP2040Support"],
16+
cSettings: [
17+
.unsafeFlags([
18+
"-mfloat-abi=soft",
19+
"-march=armv6m",
20+
]),
21+
],
22+
swiftSettings: [
23+
.enableExperimentalFeature("Embedded"),
24+
.unsafeFlags([
25+
"-whole-module-optimization",
26+
"-Xfrontend", "-function-sections",
27+
]),
28+
]
29+
),
30+
.target(
31+
name: "RP2040",
32+
dependencies: ["MMIOVolatile"],
1633
cSettings: [
1734
.unsafeFlags([
1835
"-mfloat-abi=soft",

Sources/App/App.swift

Lines changed: 1 addition & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import MMIOVolatile
1+
import RP2040
22

33
/// crt0.S calls this immediately before main.
44
@_cdecl("runtime_init")
@@ -91,211 +91,3 @@ func delayByCounting(to limit: Int32) {
9191
}
9292
return
9393
}
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

Comments
 (0)