Skip to content

Commit aaecc65

Browse files
authored
feat(ADC): Refactor ADC to not use MPUManager (#592)
1 parent aaf0500 commit aaecc65

2 files changed

Lines changed: 94 additions & 23 deletions

File tree

Inc/HALAL/Services/ADC/ADC.hpp

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
#include "ErrorHandler/ErrorHandler.hpp"
1111
#include "HALAL/Models/DMA/DMA2.hpp"
1212
#include "HALAL/Models/GPIO.hpp"
13-
#include "HALAL/Models/MPUManager/MPUManager.hpp"
13+
1414
#include "HALAL/Models/Pin.hpp"
15+
#include "HALAL/Models/MPU.hpp"
1516

1617
using std::array;
1718
using std::size_t;
@@ -250,7 +251,32 @@ struct ADCDomain {
250251
return regular_ranks[zero_based_rank];
251252
}
252253

253-
static inline std::array<uint16_t*, 3> dma_buffers{nullptr, nullptr, nullptr};
254+
struct BufferSizes {
255+
std::size_t adc1_size = 0;
256+
std::size_t adc2_size = 0;
257+
std::size_t adc3_size = 0;
258+
};
259+
260+
static consteval BufferSizes calculate_buffer_sizes(span<const Config> cfgs) {
261+
BufferSizes sizes;
262+
for (const auto& cfg : cfgs) {
263+
switch (cfg.peripheral) {
264+
case Peripheral::ADC_1:
265+
sizes.adc1_size++;
266+
break;
267+
case Peripheral::ADC_2:
268+
sizes.adc2_size++;
269+
break;
270+
case Peripheral::ADC_3:
271+
sizes.adc3_size++;
272+
break;
273+
case Peripheral::AUTO:
274+
compile_error("ADC: peripheral not resolved");
275+
break;
276+
}
277+
}
278+
return sizes;
279+
}
254280

255281
static consteval bool is_valid_channel(Channel ch) {
256282
switch (ch) {
@@ -646,21 +672,7 @@ struct ADCDomain {
646672
return nullptr;
647673
}
648674

649-
static uint16_t* ensure_dma_buffer(Peripheral peripheral) {
650-
const uint8_t pidx = peripheral_index(peripheral);
651-
if (dma_buffers[pidx] == nullptr) {
652-
dma_buffers[pidx] = static_cast<uint16_t*>(MPUManager::allocate_non_cached_memory(
653-
sizeof(uint16_t) * max_channels_per_peripheral
654-
));
655-
}
656-
if (dma_buffers[pidx] == nullptr) {
657-
ErrorHandler("ADC DMA buffer allocation failed");
658-
return nullptr;
659-
}
660675

661-
std::fill_n(dma_buffers[pidx], max_channels_per_peripheral, uint16_t{0});
662-
return dma_buffers[pidx];
663-
}
664676

665677
struct Instance {
666678
ADC_HandleTypeDef* handle = nullptr;
@@ -723,9 +735,16 @@ struct ADCDomain {
723735
}
724736
};
725737

726-
template <std::size_t N> struct Init {
738+
template <std::size_t N, std::array<Config, N> cfgs> struct Init {
727739
static inline std::array<Instance, N> instances{};
728740

741+
static constexpr auto buffer_sizes = calculate_buffer_sizes(cfgs);
742+
743+
// Static DMA buffers in non-cached D1 RAM, sized to actual usage
744+
D1_NC static inline std::array<uint16_t, buffer_sizes.adc1_size > 0 ? buffer_sizes.adc1_size : 1> dma_buffer_adc1{};
745+
D1_NC static inline std::array<uint16_t, buffer_sizes.adc2_size > 0 ? buffer_sizes.adc2_size : 1> dma_buffer_adc2{};
746+
D1_NC static inline std::array<uint16_t, buffer_sizes.adc3_size > 0 ? buffer_sizes.adc3_size : 1> dma_buffer_adc3{};
747+
729748
static constexpr bool is_resolved_config(const Config& cfg) {
730749
return cfg.peripheral != Peripheral::AUTO && cfg.channel != Channel::AUTO;
731750
}
@@ -744,6 +763,59 @@ struct ADCDomain {
744763
return &hadc1;
745764
}
746765

766+
static uint16_t* get_dma_buffer(Peripheral peripheral) {
767+
uint16_t* buffer = nullptr;
768+
size_t buffer_size = 0;
769+
770+
switch (peripheral) {
771+
case Peripheral::ADC_1:
772+
buffer = dma_buffer_adc1.data();
773+
buffer_size = buffer_sizes.adc1_size;
774+
break;
775+
case Peripheral::ADC_2:
776+
buffer = dma_buffer_adc2.data();
777+
buffer_size = buffer_sizes.adc2_size;
778+
break;
779+
case Peripheral::ADC_3:
780+
buffer = dma_buffer_adc3.data();
781+
buffer_size = buffer_sizes.adc3_size;
782+
break;
783+
case Peripheral::AUTO:
784+
break;
785+
}
786+
787+
if (buffer == nullptr || buffer_size == 0) {
788+
ErrorHandler("ADC DMA buffer not available");
789+
return nullptr;
790+
}
791+
792+
std::fill_n(buffer, buffer_size, uint16_t{0});
793+
return buffer;
794+
}
795+
796+
static uint16_t* get_dma_slot(Peripheral peripheral, uint8_t index) {
797+
switch (peripheral) {
798+
case Peripheral::ADC_1:
799+
if (index < buffer_sizes.adc1_size) {
800+
return &dma_buffer_adc1[index];
801+
}
802+
break;
803+
case Peripheral::ADC_2:
804+
if (index < buffer_sizes.adc2_size) {
805+
return &dma_buffer_adc2[index];
806+
}
807+
break;
808+
case Peripheral::ADC_3:
809+
if (index < buffer_sizes.adc3_size) {
810+
return &dma_buffer_adc3[index];
811+
}
812+
break;
813+
case Peripheral::AUTO:
814+
break;
815+
}
816+
return nullptr;
817+
}
818+
747819
static void configure_peripheral(const Config& cfg, uint8_t channel_count) {
748820
ADC_HandleTypeDef* hadc = handle_for(cfg.peripheral);
749821

@@ -833,8 +905,7 @@ struct ADCDomain {
833905
ErrorHandler("ADC DMA instance unavailable");
834906
continue;
835907
}
836-
837-
uint16_t* buffer = ensure_dma_buffer(peripheral);
908+
uint16_t* buffer = get_dma_buffer(peripheral);
838909
if (buffer == nullptr) {
839910
continue;
840911
}
@@ -898,9 +969,7 @@ struct ADCDomain {
898969
instances[i].sample_time = cfg.sample_time;
899970
instances[i].resolution = cfg.resolution;
900971
instances[i].output = cfg.output;
901-
instances[i].dma_slot = (periph_ready[pidx] && dma_buffers[pidx] != nullptr)
902-
? &dma_buffers[pidx][instance_ranks[i]]
903-
: nullptr;
972+
instances[i].dma_slot = periph_ready[pidx] ? get_dma_slot(cfg.peripheral, instance_ranks[i]) : nullptr;
904973
}
905974
}
906975
};

Inc/ST-LIB.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ template <auto&... devs> struct Board {
266266
DigitalInputDomain::Init<dinN>::instances
267267
);
268268
EthernetDomain::Init<ethN>::init(cfg.eth_cfgs, DigitalOutputDomain::Init<doutN>::instances);
269-
ADCDomain::Init<adcN>::init(
269+
ADCDomain::Init<adcN, cfg.adc_cfgs>::init(
270270
cfg.adc_cfgs,
271271
GPIODomain::Init<gpioN>::instances,
272272
DMADomain::Init<dmaN>::instances
@@ -297,6 +297,8 @@ template <auto&... devs> struct Board {
297297

298298
if constexpr (std::is_same_v<Domain, MPUDomain>) {
299299
return Domain::template Init<N, cfg.mpu_cfgs>::instances[idx];
300+
} else if constexpr (std::is_same_v<Domain, ADCDomain>) {
301+
return Domain::template Init<N, cfg.adc_cfgs>::instances[idx];
300302
} else {
301303
return Domain::template Init<N>::instances[idx];
302304
}

0 commit comments

Comments
 (0)