Skip to content

Commit 0178974

Browse files
committed
fix!: Use volatile for all non-cached memory accesses
1 parent a6be4c8 commit 0178974

6 files changed

Lines changed: 77 additions & 52 deletions

File tree

Inc/HALAL/Models/MDMA/MDMA.hpp

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ class MDMA {
3232
template <typename T> LinkedListNode(T* source_ptr, void* dest_ptr, size_t size) {
3333
init_node(source_ptr, dest_ptr, size);
3434
}
35-
36-
void set_next(MDMA_LinkNodeTypeDef* next_node) {
35+
void set_next(volatile MDMA_LinkNodeTypeDef* next_node) volatile {
3736
node.CLAR = reinterpret_cast<uint32_t>(next_node);
3837
}
39-
void set_destination(void* destination) {
38+
void set_destination(void* destination) volatile {
4039
uint32_t destination_address = reinterpret_cast<uint32_t>(destination);
4140
node.CDAR = destination_address;
4241

@@ -49,7 +48,7 @@ class MDMA {
4948
}
5049
reconfigure_ctcr();
5150
}
52-
void set_source(void* source) {
51+
void set_source(void* source) volatile {
5352
uint32_t source_address = reinterpret_cast<uint32_t>(source);
5453
node.CSAR = source_address;
5554

@@ -62,19 +61,19 @@ class MDMA {
6261
}
6362
reconfigure_ctcr();
6463
}
65-
auto get_node() -> MDMA_LinkNodeTypeDef* { return &node; }
66-
auto get_size() -> uint32_t { return node.CBNDTR; }
67-
auto get_destination() -> uint32_t { return node.CDAR; }
68-
auto get_source() -> uint32_t { return node.CSAR; }
69-
auto get_next() -> MDMA_LinkNodeTypeDef* {
70-
return reinterpret_cast<MDMA_LinkNodeTypeDef*>(node.CLAR);
64+
auto get_node() volatile -> volatile MDMA_LinkNodeTypeDef* { return &node; }
65+
auto get_size() const volatile -> uint32_t { return node.CBNDTR; }
66+
auto get_destination() const volatile -> uint32_t { return node.CDAR; }
67+
auto get_source() const volatile -> uint32_t { return node.CSAR; }
68+
auto get_next() const volatile -> volatile MDMA_LinkNodeTypeDef* {
69+
return reinterpret_cast<volatile MDMA_LinkNodeTypeDef*>(node.CLAR);
7170
}
7271

7372
private:
7473
alignas(8) MDMA_LinkNodeTypeDef node;
7574
size_t transfer_size{0};
7675

77-
void reconfigure_ctcr() {
76+
void reconfigure_ctcr() volatile {
7877
const uintptr_t src = node.CSAR;
7978
const uintptr_t dst = node.CDAR;
8079
const size_t size = transfer_size;
@@ -240,27 +239,27 @@ class MDMA {
240239
MDMA_HandleTypeDef handle;
241240
uint8_t id;
242241
volatile bool* done;
243-
MDMA_LinkNodeTypeDef* transfer_node;
242+
volatile MDMA_LinkNodeTypeDef* transfer_node;
244243

245244
Instance() : handle{}, id(0U), done(nullptr), transfer_node(nullptr) {}
246-
245+
247246
Instance(
248247
MDMA_HandleTypeDef handle_,
249248
uint8_t id_,
250249
volatile bool* done_,
251-
MDMA_LinkNodeTypeDef* transfer_node_
250+
volatile MDMA_LinkNodeTypeDef* transfer_node_
252251
)
253252
: handle(handle_), id(id_), done(done_), transfer_node(transfer_node_) {}
254253
};
255-
static void prepare_transfer(Instance& instance, MDMA::LinkedListNode* first_node);
256-
static void prepare_transfer(Instance& instance, MDMA_LinkNodeTypeDef* first_node);
254+
static void prepare_transfer(Instance& instance, volatile MDMA::LinkedListNode* first_node);
255+
static void prepare_transfer(Instance& instance, volatile MDMA_LinkNodeTypeDef* first_node);
257256
static Instance& get_instance(uint8_t id);
258257
static MDMA_Channel_TypeDef* get_channel(uint8_t id);
259258
static uint8_t get_instance_id(MDMA_Channel_TypeDef* channel);
260259

261260
inline static std::array<Instance, 8> instances{};
262261
static std::bitset<8> instance_free_map;
263-
inline static Stack<std::pair<MDMA::LinkedListNode*, volatile bool*>, 50> transfer_queue{};
262+
inline static Stack<std::pair<volatile MDMA::LinkedListNode*, volatile bool*>, 50> transfer_queue{};
264263

265264
static void TransferCompleteCallback(MDMA_HandleTypeDef* hmdma);
266265
static void TransferErrorCallback(MDMA_HandleTypeDef* hmdma);
@@ -303,5 +302,5 @@ class MDMA {
303302
* @param check A reference boolean that will be set to true if the transfer was successfully
304303
* done, false otherwise.
305304
*/
306-
static void transfer_list(MDMA::LinkedListNode* first_node, volatile bool* check = nullptr);
305+
static void transfer_list(volatile MDMA::LinkedListNode* first_node, volatile bool* check = nullptr);
307306
};

Inc/HALAL/Models/MPU.hpp

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,30 @@
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
5872
extern "C" const char __itcm_base;
5973
extern "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
}

Inc/HALAL/Models/SPI/SPI2.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,8 +1240,8 @@ struct SPIDomain {
12401240
}
12411241
auto error_code = HAL_SPI_TransmitReceive_DMA(
12421242
&spi_instance.hspi,
1243-
reinterpret_cast<const uint8_t*>(&tx_data),
1244-
reinterpret_cast<uint8_t*>(&rx_data),
1243+
const_cast<uint8_t*>(reinterpret_cast<const volatile uint8_t*>(&tx_data)),
1244+
const_cast<uint8_t*>(reinterpret_cast<volatile uint8_t*>(&rx_data)),
12451245
size / frame_size
12461246
);
12471247
return check_error_code(error_code);

Inc/HALAL/Services/ADC/ADC.hpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ struct ADCDomain {
828828
}
829829
return 0;
830830
}
831-
static uint16_t* get_dma_buffer(Peripheral peripheral) {
831+
static volatile uint16_t* get_dma_buffer(Peripheral peripheral) {
832832
const auto buffer_size = buffer_size_for(peripheral);
833833
const auto buffer_offset = buffer_offset_for(peripheral);
834834
if (buffer_size == 0U) {
@@ -840,12 +840,12 @@ struct ADCDomain {
840840
return nullptr;
841841
}
842842

843-
uint16_t* buffer = &dma_buffer_pool[buffer_offset];
843+
volatile uint16_t* buffer = &dma_buffer_pool[buffer_offset];
844844
std::fill_n(buffer, buffer_size, uint16_t{0});
845845
return buffer;
846846
}
847847

848-
static uint16_t* get_dma_slot(Peripheral peripheral, uint8_t index) {
848+
static volatile uint16_t* get_dma_slot(Peripheral peripheral, uint8_t index) {
849849
if (index >= buffer_size_for(peripheral)) {
850850
return nullptr;
851851
}
@@ -945,7 +945,7 @@ struct ADCDomain {
945945
ErrorHandler("ADC DMA instance unavailable");
946946
continue;
947947
}
948-
uint16_t* buffer = get_dma_buffer(peripheral);
948+
volatile uint16_t* buffer = get_dma_buffer(peripheral);
949949
if (buffer == nullptr) {
950950
continue;
951951
}
@@ -989,8 +989,13 @@ struct ADCDomain {
989989
continue;
990990
}
991991

992-
if (HAL_ADC_Start_DMA(hadc, reinterpret_cast<uint32_t*>(buffer), channel_count) !=
993-
HAL_OK) {
992+
if (HAL_ADC_Start_DMA(
993+
hadc,
994+
reinterpret_cast<uint32_t*>(
995+
const_cast<std::remove_volatile_t<std::remove_pointer_t<decltype(buffer)>>*>(buffer)
996+
),
997+
channel_count
998+
) != HAL_OK) {
994999
ErrorHandler("ADC DMA start failed");
9951000
continue;
9961001
}

Inc/HALAL/Services/DFSDM/DFSDM.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ struct DFSDM_CHANNEL_DOMAIN {
10171017
ErrorHandler("Filter cannot be bigger than 3");
10181018
return 0;
10191019
}
1020-
static int32_t* get_buffer_filter(uint8_t filter) {
1020+
static volatile int32_t* get_buffer_filter(uint8_t filter) {
10211021
switch (filter) {
10221022
case 0:
10231023
return Buffer_Filter0;
@@ -1032,7 +1032,7 @@ struct DFSDM_CHANNEL_DOMAIN {
10321032
return 0;
10331033
}
10341034

1035-
static int32_t* get_buffer_pointer(const Config cfg) {
1035+
static volatile int32_t* get_buffer_pointer(const Config cfg) {
10361036
return get_buffer_filter(cfg.filter) + cfg.buffer_pos_ini;
10371037
}
10381038

Src/HALAL/Models/MDMA/MDMA.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ uint8_t MDMA::get_instance_id(MDMA_Channel_TypeDef* channel) {
1818
return static_cast<uint8_t>((address - (MDMA_BASE + 0x40UL)) / 0x40UL);
1919
}
2020

21-
void MDMA::prepare_transfer(Instance& instance, MDMA_LinkNodeTypeDef* first_node) {
21+
void MDMA::prepare_transfer(Instance& instance, volatile MDMA_LinkNodeTypeDef* first_node) {
2222
if (instance.handle.State == HAL_MDMA_STATE_BUSY) {
2323
ErrorHandler("MDMA transfer already in progress");
2424
return;
@@ -27,7 +27,7 @@ void MDMA::prepare_transfer(Instance& instance, MDMA_LinkNodeTypeDef* first_node
2727

2828
instance.handle.State = HAL_MDMA_STATE_BUSY;
2929
instance.handle.ErrorCode = HAL_MDMA_ERROR_NONE;
30-
instance.handle.FirstLinkedListNodeAddress = first_node;
30+
instance.handle.FirstLinkedListNodeAddress = const_cast<MDMA_LinkNodeTypeDef*>(first_node);
3131

3232
MDMA_Channel_TypeDef* channel = instance.handle.Instance;
3333

@@ -56,7 +56,7 @@ void MDMA::prepare_transfer(Instance& instance, MDMA_LinkNodeTypeDef* first_node
5656
}
5757
}
5858

59-
void MDMA::prepare_transfer(Instance& instance, LinkedListNode* first_node) {
59+
void MDMA::prepare_transfer(Instance& instance, volatile LinkedListNode* first_node) {
6060
MDMA::prepare_transfer(instance, first_node->get_node());
6161
}
6262

@@ -91,7 +91,7 @@ void MDMA::inscribe(Instance& instance, uint8_t id) {
9191
mdma_handle.Init.DestBlockAddressOffset = 0;
9292

9393
MDMA_LinkNodeConfTypeDef nodeConfig{};
94-
MDMA_LinkNodeTypeDef* transfer_node = &internal_nodes[id];
94+
auto transfer_node = &internal_nodes[id];
9595

9696
nodeConfig.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE;
9797
nodeConfig.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE;
@@ -112,7 +112,7 @@ void MDMA::inscribe(Instance& instance, uint8_t id) {
112112
nodeConfig.SrcAddress = reinterpret_cast<uint32_t>(nullptr);
113113
nodeConfig.DstAddress = reinterpret_cast<uint32_t>(nullptr);
114114

115-
const HAL_StatusTypeDef status = HAL_MDMA_LinkedList_CreateNode(transfer_node, &nodeConfig);
115+
const HAL_StatusTypeDef status = HAL_MDMA_LinkedList_CreateNode(const_cast<MDMA_LinkNodeTypeDef*>(transfer_node), &nodeConfig);
116116
if (status != HAL_OK) {
117117
ErrorHandler("Error creating linked list in MDMA");
118118
}
@@ -182,7 +182,7 @@ void MDMA::irq_handler() {
182182
}
183183
}
184184

185-
void MDMA::transfer_list(MDMA::LinkedListNode* first_node, volatile bool* done) {
185+
void MDMA::transfer_list(volatile MDMA::LinkedListNode* first_node, volatile bool* done) {
186186
if (transfer_queue.size() >= TRANSFER_QUEUE_MAX_SIZE) {
187187
ErrorHandler("MDMA transfer queue full");
188188
return;

0 commit comments

Comments
 (0)