Skip to content

Commit e695e17

Browse files
andryblacksalkinium
authored andcommitted
[ext] Add PICO-SDK module
1 parent d017602 commit e695e17

File tree

6 files changed

+323
-0
lines changed

6 files changed

+323
-0
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@
3737
[submodule "ext/etlcpp/etl"]
3838
path = ext/etlcpp/etl
3939
url = https://github.com/modm-ext/etl-partial.git
40+
[submodule "ext/rp/pico-sdk"]
41+
path = ext/rp/pico-sdk
42+
url = https://github.com/modm-ext/pico-sdk-partial.git

ext/rp/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
## RP2040 device headers
2+
3+
This folder includes the CMSIS device headers for RP2040 devices.
4+
The files included here are part of the CMSIS libraries for the particular chip.
5+
Only the device header and system init header from the `inc` folder are copied.
6+
7+
## License
8+
9+
The Raspberry Pi header files in this directory are available under the BSD-3-Clause License:
10+
```
11+
Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
12+
13+
SPDX-License-Identifier: BSD-3-Clause
14+
```
15+
16+
The Raspberry Pi CMSIS header files in this directory are available under
17+
the Apache-2.0/BSD-3-Clause License:
18+
```
19+
Copyright (c) 2009-2021 Arm Limited. All rights reserved.
20+
Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
21+
22+
SPDX-License-Identifier: Apache-2.0
23+
24+
Licensed under the Apache License, Version 2.0 (the License); you may
25+
not use this file except in compliance with the License.
26+
You may obtain a copy of the License at
27+
28+
www.apache.org/licenses/LICENSE-2.0
29+
30+
Unless required by applicable law or agreed to in writing, software
31+
distributed under the License is distributed on an AS IS BASIS, WITHOUT
32+
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
33+
See the License for the specific language governing permissions and
34+
limitations under the License.
35+
36+
SPDX-License-Identifier: BSD-3-Clause
37+
38+
```
39+
40+
The Raspberry Pi bootloader files available under BSD-3-Clause License:
41+
```
42+
Second stage boot code
43+
Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
44+
SPDX-License-Identifier: BSD-3-Clause
45+
```

ext/rp/address_mapped.h

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#ifndef _HARDWARE_ADDRESS_MAPPED_H
8+
#define _HARDWARE_ADDRESS_MAPPED_H
9+
10+
#ifdef __cplusplus
11+
#include <modm/architecture/utils.hpp>
12+
#include <cstdint>
13+
#endif
14+
15+
#define invalid_params_if(x, test) \
16+
if (0) {}
17+
#define valid_params_if(x, test) \
18+
if (0) {}
19+
#define hard_assert_if(x, test) \
20+
if (0) {}
21+
22+
#include "hardware/regs/addressmap.h"
23+
24+
/** \file address_mapped.h
25+
* \defgroup hardware_base hardware_base
26+
*
27+
* Low-level types and (atomic) accessors for memory-mapped hardware registers
28+
*
29+
* `hardware_base` defines the low level types and access functions for memory mapped hardware
30+
registers. It is included
31+
* by default by all other hardware libraries.
32+
*
33+
* The following register access typedefs codify the access type (read/write) and the bus size
34+
(8/16/32) of the hardware register.
35+
* The register type names are formed by concatenating one from each of the 3 parts A, B, C
36+
37+
* A | B | C | Meaning
38+
* ------|---|---|--------
39+
* io_ | | | A Memory mapped IO register
40+
* &nbsp;|ro_| | read-only access
41+
* &nbsp;|rw_| | read-write access
42+
* &nbsp;|wo_| | write-only access (can't actually be enforced via C API)
43+
* &nbsp;| | 8| 8-bit wide access
44+
* &nbsp;| | 16| 16-bit wide access
45+
* &nbsp;| | 32| 32-bit wide access
46+
*
47+
* When dealing with these types, you will always use a pointer, i.e. `io_rw_32 *some_reg` is a
48+
pointer to a read/write
49+
* 32 bit register that you can write with `*some_reg = value`, or read with `value = *some_reg`.
50+
*
51+
* RP2040 hardware is also aliased to provide atomic setting, clear or flipping of a subset of the
52+
bits within
53+
* a hardware register so that concurrent access by two cores is always consistent with one atomic
54+
operation
55+
* being performed first, followed by the second.
56+
*
57+
* See hw_set_bits(), hw_clear_bits() and hw_xor_bits() provide for atomic access via a pointer to
58+
a 32 bit register
59+
*
60+
* Additionally given a pointer to a structure representing a piece of hardware (e.g. `dma_hw_t
61+
*dma_hw` for the DMA controller), you can
62+
* get an alias to the entire structure such that writing any member (register) within the
63+
structure is equivalent
64+
* to an atomic operation via hw_set_alias(), hw_clear_alias() or hw_xor_alias()...
65+
*
66+
* For example `hw_set_alias(dma_hw)->inte1 = 0x80;` will set bit 7 of the INTE1 register of the
67+
DMA controller,
68+
* leaving the other bits unchanged.
69+
*/
70+
71+
#ifdef __cplusplus
72+
extern "C" {
73+
#endif
74+
75+
#define check_hw_layout(type, member, offset) \
76+
static_assert(offsetof(type, member) == (offset), "hw offset mismatch")
77+
#define check_hw_size(type, size) static_assert(sizeof(type) == (size), "hw size mismatch")
78+
79+
typedef volatile uint32_t io_rw_32;
80+
typedef const volatile uint32_t io_ro_32;
81+
typedef volatile uint32_t io_wo_32;
82+
typedef volatile uint16_t io_rw_16;
83+
typedef const volatile uint16_t io_ro_16;
84+
typedef volatile uint16_t io_wo_16;
85+
typedef volatile uint8_t io_rw_8;
86+
typedef const volatile uint8_t io_ro_8;
87+
typedef volatile uint8_t io_wo_8;
88+
89+
typedef volatile uint8_t *const ioptr;
90+
typedef ioptr const const_ioptr;
91+
92+
// A non-functional (empty) helper macro to help IDEs follow links from the autogenerated
93+
// hardware struct headers in hardware/structs/xxx.h to the raw register definitions
94+
// in hardware/regs/xxx.h. A preprocessor define such as TIMER_TIMEHW_OFFSET (a timer register
95+
// offset) is not generally clickable (in an IDE) if placed in a C comment, so
96+
// _REG_(TIMER_TIMEHW_OFFSET) is included outside of a comment instead
97+
#define _REG_(x)
98+
99+
// Helper method used by hw_alias macros to optionally check input validity
100+
#define hw_alias_check_addr(addr) ((uintptr_t)(addr))
101+
// can't use the following impl as it breaks existing static declarations using hw_alias, so would
102+
// be a backwards incompatibility
103+
// static __force_inline uint32_t hw_alias_check_addr(volatile void *addr) {
104+
// uint32_t rc = (uintptr_t)addr;
105+
// invalid_params_if(ADDRESS_ALIAS, rc < 0x40000000); // catch likely non HW pointer types
106+
// return rc;
107+
//}
108+
109+
// Helper method used by xip_alias macros to optionally check input validity
110+
modm_always_inline static uint32_t
111+
xip_alias_check_addr(const void *addr)
112+
{
113+
uint32_t rc = (uintptr_t)addr;
114+
valid_params_if(ADDRESS_ALIAS, rc >= XIP_MAIN_BASE && rc < XIP_NOALLOC_BASE);
115+
return rc;
116+
}
117+
118+
// Untyped conversion alias pointer generation macros
119+
#define hw_set_alias_untyped(addr) ((void *)(REG_ALIAS_SET_BITS | hw_alias_check_addr(addr)))
120+
#define hw_clear_alias_untyped(addr) ((void *)(REG_ALIAS_CLR_BITS | hw_alias_check_addr(addr)))
121+
#define hw_xor_alias_untyped(addr) ((void *)(REG_ALIAS_XOR_BITS | hw_alias_check_addr(addr)))
122+
#define xip_noalloc_alias_untyped(addr) ((void *)(XIP_NOALLOC_BASE | xip_alias_check_addr(addr)))
123+
#define xip_nocache_alias_untyped(addr) ((void *)(XIP_NOCACHE_BASE | xip_alias_check_addr(addr)))
124+
#define xip_nocache_noalloc_alias_untyped(addr) \
125+
((void *)(XIP_NOCACHE_NOALLOC_BASE | xip_alias_check_addr(addr)))
126+
127+
// Typed conversion alias pointer generation macros
128+
#define hw_set_alias(p) ((typeof(p))hw_set_alias_untyped(p))
129+
#define hw_clear_alias(p) ((typeof(p))hw_clear_alias_untyped(p))
130+
#define hw_xor_alias(p) ((typeof(p))hw_xor_alias_untyped(p))
131+
#define xip_noalloc_alias(p) ((typeof(p))xip_noalloc_alias_untyped(p))
132+
#define xip_nocache_alias(p) ((typeof(p))xip_nocache_alias_untyped(p))
133+
#define xip_nocache_noalloc_alias(p) ((typeof(p))xip_nocache_noalloc_alias_untyped(p))
134+
135+
/*! \brief Atomically set the specified bits to 1 in a HW register
136+
* \ingroup hardware_base
137+
*
138+
* \param addr Address of writable register
139+
* \param mask Bit-mask specifying bits to set
140+
*/
141+
modm_always_inline static void
142+
hw_set_bits(io_rw_32 *addr, uint32_t mask)
143+
{
144+
*(io_rw_32 *)hw_set_alias_untyped((volatile void *)addr) = mask;
145+
}
146+
147+
/*! \brief Atomically clear the specified bits to 0 in a HW register
148+
* \ingroup hardware_base
149+
*
150+
* \param addr Address of writable register
151+
* \param mask Bit-mask specifying bits to clear
152+
*/
153+
modm_always_inline static void
154+
hw_clear_bits(io_rw_32 *addr, uint32_t mask)
155+
{
156+
*(io_rw_32 *)hw_clear_alias_untyped((volatile void *)addr) = mask;
157+
}
158+
159+
/*! \brief Atomically flip the specified bits in a HW register
160+
* \ingroup hardware_base
161+
*
162+
* \param addr Address of writable register
163+
* \param mask Bit-mask specifying bits to invert
164+
*/
165+
modm_always_inline static void
166+
hw_xor_bits(io_rw_32 *addr, uint32_t mask)
167+
{
168+
*(io_rw_32 *)hw_xor_alias_untyped((volatile void *)addr) = mask;
169+
}
170+
171+
/*! \brief Set new values for a sub-set of the bits in a HW register
172+
* \ingroup hardware_base
173+
*
174+
* Sets destination bits to values specified in \p values, if and only if corresponding bit in \p
175+
* write_mask is set
176+
*
177+
* Note: this method allows safe concurrent modification of *different* bits of
178+
* a register, but multiple concurrent access to the same bits is still unsafe.
179+
*
180+
* \param addr Address of writable register
181+
* \param values Bits values
182+
* \param write_mask Mask of bits to change
183+
*/
184+
modm_always_inline static void
185+
hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask)
186+
{
187+
hw_xor_bits(addr, (*addr ^ values) & write_mask);
188+
}
189+
190+
#ifdef __cplusplus
191+
}
192+
#endif
193+
194+
#endif

ext/rp/device.hpp.in

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2009, Martin Rosekeit
3+
* Copyright (c) 2009, Thorsten Lajewski
4+
* Copyright (c) 2009-2010, 2016, Fabian Greif
5+
* Copyright (c) 2012-2013, 2016, Niklas Hauser
6+
* Copyright (c) 2013, Kevin Laeufer
7+
*
8+
* This file is part of the modm project.
9+
*
10+
* This Source Code Form is subject to the terms of the Mozilla Public
11+
* License, v. 2.0. If a copy of the MPL was not distributed with this
12+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
13+
*/
14+
// ----------------------------------------------------------------------------
15+
16+
#ifndef MODM_DEVICE_HPP
17+
#define MODM_DEVICE_HPP
18+
19+
%% for define in defines:
20+
#define {{ define }} 1
21+
%% endfor
22+
23+
#include <stdint.h>
24+
// Defines for example the modm_always_inline macro
25+
#include <modm/architecture/utils.hpp>
26+
27+
// Include external device headers:
28+
%% for header in headers
29+
#include <{{ header }}>
30+
%% endfor
31+
32+
#endif // MODM_DEVICE_HPP

ext/rp/module.lb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
#
4+
# Copyright (c) 2022, Andrey Kunitsyn
5+
#
6+
# This file is part of the modm project.
7+
#
8+
# This Source Code Form is subject to the terms of the Mozilla Public
9+
# License, v. 2.0. If a copy of the MPL was not distributed with this
10+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
11+
# -----------------------------------------------------------------------------
12+
13+
import os
14+
15+
def init(module):
16+
module.name = ":cmsis:device"
17+
18+
def prepare(module, options):
19+
device = options[":target"]
20+
if not device.identifier["platform"] == "rp":
21+
return False
22+
23+
module.depends(":cmsis:core")
24+
return True
25+
26+
def build(env):
27+
env.collect(":build:path.include", "modm/ext/cmsis_device")
28+
29+
device = env[":target"]
30+
31+
env.outbasepath = "modm/ext/cmsis_device"
32+
33+
defines = []
34+
headers = [
35+
device.identifier.string.upper() + ".h"
36+
]
37+
38+
env.copy("pico-sdk/include", "")
39+
env.copy("address_mapped.h", "hardware/address_mapped.h")
40+
41+
env.substitutions = {
42+
"headers": headers,
43+
"defines": defines,
44+
}
45+
env.outbasepath = "modm/src/modm/platform"
46+
env.template("device.hpp.in")
47+
48+

ext/rp/pico-sdk

Submodule pico-sdk added at 36cdca5

0 commit comments

Comments
 (0)