4444// Defines for attributes
4545// Note1: Variables declared with these attributes will likely not be initialized by the startup
4646// Note2: These attributes can only be used for static/global variables
47- #define D1_NC __attribute__ ((section(" .mpu_ram_d1_nc.user" )))
48- #define D2_NC __attribute__ ((section(" .mpu_ram_d2_nc.user" )))
49- #define D3_NC __attribute__ ((section(" .mpu_ram_d3_nc.user" )))
50- #define D1_C __attribute__ ((section(" .ram_d1.user" )))
51- #define D2_C __attribute__ ((section(" .ram_d2.user" )))
52- #define D3_C __attribute__ ((section(" .ram_d3.user" )))
53-
54- // Define for RAM code
47+ #ifdef SIM_ON
48+ #define D1_NC
49+ #define D2_NC
50+ #define D3_NC
51+ #define D1_C
52+ #define D2_C
53+ #define D3_C
54+ #define RAM_CODE
55+ #else
56+ /*
57+ * Use C++ attribute syntax when compiled as C++, otherwise fall back to GCC-style
58+ * `__attribute__` so the header is safe to include from both C and C++ translation
59+ * units (some build units may be plain C and would reject the [[...]] syntax).
60+ */
5561#define RAM_CODE __attribute__ ((section(" .ram_code" )))
5662
63+ #define D1_NC __attribute__ ((section(" .mpu_ram_d1_nc.user" ), used)) volatile
64+ #define D2_NC __attribute__ ((section(" .mpu_ram_d2_nc.user" ), used)) volatile
65+ #define D3_NC __attribute__ ((section(" .mpu_ram_d3_nc.user" ), used)) volatile
66+ #define D1_C __attribute__ ((section(" .ram_d1.user" ), used))
67+ #define D2_C __attribute__ ((section(" .ram_d2.user" ), used))
68+ #define D3_C __attribute__ ((section(" .ram_d3.user" ), used))
69+ #endif
70+
5771// Memory Bank Symbols from Linker
5872extern " C" const char __itcm_base;
5973extern " C" const char __itcm_size;
@@ -260,14 +274,21 @@ struct MPUDomain {
260274 void * ptr;
261275 std::size_t size;
262276
263- template <mpu_buffer_request auto & Target, typename ... Args>
264- auto & construct (Args&&... args) {
265- using T = typename std::remove_cvref_t <decltype (Target)>::buffer_type;
277+ template <auto & Target, typename ... Args> auto & construct (Args&&... args) {
278+ using Request = std::remove_cvref_t <decltype (Target)>;
279+ static_assert (mpu_buffer_request<Request>, " Target must be a valid MPUDomain buffer" );
280+ constexpr bool is_nc = Request::e.memory_type == MemoryType::NonCached;
281+ static_assert (is_nc && std::is_volatile_v<typename Request::buffer_type>, " Non cached buffers must be volatile to work as intended" );
282+ using T = typename Request::buffer_type;
266283 return *new (ptr) T (std::forward<Args>(args)...);
267284 }
268285
269- template <mpu_buffer_request auto & Target> auto * as () {
270- using T = typename std::remove_cvref_t <decltype (Target)>::buffer_type;
286+ template <auto & Target> auto * as () {
287+ using Request = std::remove_cvref_t <decltype (Target)>;
288+ static_assert (mpu_buffer_request<Request>, " Target must be a valid MPUDomain buffer" );
289+ constexpr bool is_nc = Request::e.memory_type == MemoryType::NonCached;
290+ static_assert (is_nc && std::is_volatile_v<typename Request::buffer_type>, " Non cached buffers must be volatile to work as intended" );
291+ using T = typename Request::buffer_type;
271292 return static_cast <T*>(ptr);
272293 }
273294 };
@@ -290,17 +311,17 @@ struct MPUDomain {
290311
291312 // Sections defined in Linker Script (aligned to 32 bytes just in case)
292313 __attribute__ ((section(" .mpu_ram_d1_nc.buffer" ))) alignas (32
293- ) static inline uint8_t d1_nc_buffer[Sizes.d1_nc_total > 0 ? Sizes.d1_nc_total : 1 ];
314+ ) static inline volatile uint8_t d1_nc_buffer[Sizes.d1_nc_total > 0 ? Sizes.d1_nc_total : 1 ];
294315 __attribute__ ((section(" .ram_d1.buffer" ))) alignas (32
295316 ) static inline uint8_t d1_c_buffer[Sizes.d1_c_total > 0 ? Sizes.d1_c_total : 1 ];
296317
297318 __attribute__ ((section(" .mpu_ram_d2_nc.buffer" ))) alignas (32
298- ) static inline uint8_t d2_nc_buffer[Sizes.d2_nc_total > 0 ? Sizes.d2_nc_total : 1 ];
319+ ) static inline volatile uint8_t d2_nc_buffer[Sizes.d2_nc_total > 0 ? Sizes.d2_nc_total : 1 ];
299320 __attribute__ ((section(" .ram_d2.buffer" ))) alignas (32
300321 ) static inline uint8_t d2_c_buffer[Sizes.d2_c_total > 0 ? Sizes.d2_c_total : 1 ];
301322
302323 __attribute__ ((section(" .mpu_ram_d3_nc.buffer" ))) alignas (32
303- ) static inline uint8_t d3_nc_buffer[Sizes.d3_nc_total > 0 ? Sizes.d3_nc_total : 1 ];
324+ ) static inline volatile uint8_t d3_nc_buffer[Sizes.d3_nc_total > 0 ? Sizes.d3_nc_total : 1 ];
304325 __attribute__ ((section(" .ram_d3.buffer" ))) alignas (32
305326 ) static inline uint8_t d3_c_buffer[Sizes.d3_c_total > 0 ? Sizes.d3_c_total : 1 ];
306327
@@ -326,7 +347,7 @@ struct MPUDomain {
326347 );
327348
328349 // Assign pointers
329- uint8_t * bases_nc[3 ] = {&d1_nc_buffer[0 ], &d2_nc_buffer[0 ], &d3_nc_buffer[0 ]};
350+ volatile uint8_t * bases_nc[3 ] = {&d1_nc_buffer[0 ], &d2_nc_buffer[0 ], &d3_nc_buffer[0 ]};
330351 uint8_t * bases_c[3 ] = {&d1_c_buffer[0 ], &d2_c_buffer[0 ], &d3_c_buffer[0 ]};
331352
332353 for (std::size_t i = 0 ; i < N; i++) {
@@ -338,7 +359,7 @@ struct MPUDomain {
338359 size_t d_idx = static_cast <size_t >(cfg.domain ) - 1 ;
339360
340361 if (cfg.type == MemoryType::NonCached) {
341- inst.ptr = bases_nc[d_idx] + cfg.offset ;
362+ inst.ptr = const_cast < uint8_t *>( bases_nc[d_idx] + cfg.offset ) ;
342363 } else {
343364 inst.ptr = bases_c[d_idx] + cfg.offset ;
344365 }
0 commit comments