From d060dce4ec03dad8bcde265ff5b5eb68cd009ea2 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 15 Aug 2020 08:44:02 -0400 Subject: [PATCH 1/2] move drivers into namespaces --- source/adc.cpp | 101 ++++++++++++++++++++++--------------------- source/adc.hpp | 31 +++++++------ source/dac.cpp | 39 +++++++++-------- source/dac.hpp | 9 ++-- source/main.cpp | 26 +++++------ source/usbserial.cpp | 61 +++++++++++++------------- source/usbserial.hpp | 12 +++-- 7 files changed, 149 insertions(+), 130 deletions(-) diff --git a/source/adc.cpp b/source/adc.cpp index 851b461..609ffce 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -18,7 +18,7 @@ constexpr static const ADCConfig adc_config = { .difsel = 0 }; -void adc_read_callback(ADCDriver *); +static void adc_read_callback(ADCDriver *); /*constexpr*/ static ADCConversionGroup adc_group_config = { .circular = false, @@ -46,61 +46,64 @@ constexpr static const GPTConfig gpt_config = { static bool adc_is_read_finished = false; -void adc_init() -{ - palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); - - gptStart(gptd, &gpt_config); - adcStart(adcd, &adc_config); - adcSTM32EnableVREF(adcd); -} - -adcsample_t *adc_read(adcsample_t *buffer, size_t count) -{ - adc_is_read_finished = false; - adcStartConversion(adcd, &adc_group_config, buffer, count); - gptStartContinuous(gptd, 100); // 10kHz - while (!adc_is_read_finished); - return buffer; -} - void adc_read_callback([[maybe_unused]] ADCDriver *driver) { gptStopTimer(gptd); adc_is_read_finished = true; } -void adc_set_rate(ADCRate rate) +namespace adc { - uint32_t val = 0; - - switch (rate) { - case ADCRate::R2P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5); - break; - case ADCRate::R6P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_6P5); - break; - case ADCRate::R12P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5); - break; - case ADCRate::R24P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5); - break; - case ADCRate::R47P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_47P5); - break; - case ADCRate::R92P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_92P5); - break; - case ADCRate::R247P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5); - break; - case ADCRate::R640P5: - val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_640P5); - break; + void init() + { + palSetPadMode(GPIOA, 0, PAL_MODE_INPUT_ANALOG); + + gptStart(gptd, &gpt_config); + adcStart(adcd, &adc_config); + adcSTM32EnableVREF(adcd); + } + + adcsample_t *read(adcsample_t *buffer, size_t count) + { + adc_is_read_finished = false; + adcStartConversion(adcd, &adc_group_config, buffer, count); + gptStartContinuous(gptd, 100); // 10kHz + while (!adc_is_read_finished); + return buffer; + } + + void set_rate(rate r) + { + uint32_t val = 0; + + switch (r) { + case rate::R2P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5); + break; + case rate::R6P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_6P5); + break; + case rate::R12P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_12P5); + break; + case rate::R24P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5); + break; + case rate::R47P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_47P5); + break; + case rate::R92P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_92P5); + break; + case rate::R247P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_247P5); + break; + case rate::R640P5: + val = ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_640P5); + break; + } + + adc_group_config.smpr[0] = val; } - - adc_group_config.smpr[0] = val; } diff --git a/source/adc.hpp b/source/adc.hpp index 4c3836e..e026d0c 100644 --- a/source/adc.hpp +++ b/source/adc.hpp @@ -14,20 +14,23 @@ #include "hal.h" -enum class ADCRate { - R2P5, - R6P5, - R12P5, - R24P5, - R47P5, - R92P5, - R247P5, - R640P5 -}; - -void adc_init(); -adcsample_t *adc_read(adcsample_t *buffer, size_t count); -void adc_set_rate(ADCRate rate); +namespace adc +{ + enum class rate { + R2P5, + R6P5, + R12P5, + R24P5, + R47P5, + R92P5, + R247P5, + R640P5 + }; + + void init(); + adcsample_t *read(adcsample_t *buffer, size_t count); + void set_rate(rate r); +} #endif // STMDSP_ADC_HPP_ diff --git a/source/dac.cpp b/source/dac.cpp index d2bcf37..6096d8e 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -34,24 +34,27 @@ constexpr static const GPTConfig gpt_config = { .dier = 0 }; -void dac_init() +namespace dac { - palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); - //palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); - - dacStart(dacd, &dac_config); - gptStart(gptd, &gpt_config); -} - -void dac_write_start(dacsample_t *buffer, size_t count) -{ - dacStartConversion(dacd, &dac_group_config, buffer, count); - gptStartContinuous(gptd, 1); -} - -void dac_write_stop() -{ - gptStopTimer(gptd); - dacStopConversion(dacd); + void init() + { + palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); + //palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); + + dacStart(dacd, &dac_config); + gptStart(gptd, &gpt_config); + } + + void write_start(dacsample_t *buffer, size_t count) + { + dacStartConversion(dacd, &dac_group_config, buffer, count); + gptStartContinuous(gptd, 1); + } + + void write_stop() + { + gptStopTimer(gptd); + dacStopConversion(dacd); + } } diff --git a/source/dac.hpp b/source/dac.hpp index ce67f40..9d529bf 100644 --- a/source/dac.hpp +++ b/source/dac.hpp @@ -14,9 +14,12 @@ #include "hal.h" -void dac_init(); -void dac_write_start(dacsample_t *buffer, size_t count); -void dac_write_stop(); +namespace dac +{ + void init(); + void write_start(dacsample_t *buffer, size_t count); + void write_stop(); +} #endif // STMDSP_DAC_HPP_ diff --git a/source/main.cpp b/source/main.cpp index cfd20a9..b5ebf86 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -33,39 +33,39 @@ int main() palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); // LED - adc_init(); - dac_init(); - usbserial_init(); + adc::init(); + dac::init(); + usbserial::init(); static unsigned int dac_sample_count = 2048; while (true) { - if (usbserial_is_active()) { + if (usbserial::is_active()) { // Expect to receive a byte command 'packet'. - if (char cmd[3]; usbserial_read(&cmd, 1) > 0) { + if (char cmd[3]; usbserial::read(&cmd, 1) > 0) { switch (cmd[0]) { case 'r': // Read in analog signal - if (usbserial_read(&cmd[1], 2) < 2) + if (usbserial::read(&cmd[1], 2) < 2) break; if (auto count = std::min(static_cast(cmd[1] | (cmd[2] << 8)), adc_samples.size()); count > 0) { - adc_read(&adc_samples[0], count); - usbserial_write(adc_samples.data(), count * sizeof(adcsample_t)); + adc::read(&adc_samples[0], count); + usbserial::write(adc_samples.data(), count * sizeof(adcsample_t)); } break; case 'W': - if (usbserial_read(&cmd[1], 2) < 2) + if (usbserial::read(&cmd[1], 2) < 2) break; if (auto count = std::min(static_cast(cmd[1] | (cmd[2] << 8)), dac_samples.size()); count > 0) dac_sample_count = count; else - dac_write_stop(); + dac::write_stop(); break; case 'w': - if (usbserial_read(&dac_samples[0], 2 * dac_sample_count) != 2 * dac_sample_count) + if (usbserial::read(&dac_samples[0], 2 * dac_sample_count) != 2 * dac_sample_count) break; - dac_write_start(&dac_samples[0], dac_sample_count); + dac::write_start(&dac_samples[0], dac_sample_count); break; case 'i': // Identify ourself as an stmdsp device - usbserial_write("stmdsp", 6); + usbserial::write("stmdsp", 6); break; default: break; diff --git a/source/usbserial.cpp b/source/usbserial.cpp index 5d605e6..ec2fc5d 100644 --- a/source/usbserial.cpp +++ b/source/usbserial.cpp @@ -15,35 +15,38 @@ constexpr static const auto sdud = &SDU1; -void usbserial_init() +namespace usbserial { - palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10)); - palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10)); - - sduObjectInit(sdud); - sduStart(sdud, &serusbcfg); - - // Reconnect bus so device can re-enumerate on reset - usbDisconnectBus(serusbcfg.usbp); - chThdSleepMilliseconds(1500); - usbStart(serusbcfg.usbp, &usbcfg); - usbConnectBus(serusbcfg.usbp); -} - -bool usbserial_is_active() -{ - return sdud->config->usbp->state == USB_ACTIVE; -} - -size_t usbserial_read(void *buffer, size_t count) -{ - auto bss = reinterpret_cast(sdud); - return streamRead(bss, static_cast(buffer), count); -} - -size_t usbserial_write(const void *buffer, size_t count) -{ - auto bss = reinterpret_cast(sdud); - return streamWrite(bss, static_cast(buffer), count); + void init() + { + palSetPadMode(GPIOA, 11, PAL_MODE_ALTERNATE(10)); + palSetPadMode(GPIOA, 12, PAL_MODE_ALTERNATE(10)); + + sduObjectInit(sdud); + sduStart(sdud, &serusbcfg); + + // Reconnect bus so device can re-enumerate on reset + usbDisconnectBus(serusbcfg.usbp); + chThdSleepMilliseconds(1500); + usbStart(serusbcfg.usbp, &usbcfg); + usbConnectBus(serusbcfg.usbp); + } + + bool is_active() + { + return sdud->config->usbp->state == USB_ACTIVE; + } + + size_t read(void *buffer, size_t count) + { + auto bss = reinterpret_cast(sdud); + return streamRead(bss, static_cast(buffer), count); + } + + size_t write(const void *buffer, size_t count) + { + auto bss = reinterpret_cast(sdud); + return streamWrite(bss, static_cast(buffer), count); + } } diff --git a/source/usbserial.hpp b/source/usbserial.hpp index 4b0eab2..4c33d51 100644 --- a/source/usbserial.hpp +++ b/source/usbserial.hpp @@ -14,10 +14,14 @@ #include "hal.h" -void usbserial_init(); -bool usbserial_is_active(); -size_t usbserial_read(void *buffer, size_t count); -size_t usbserial_write(const void *buffer, size_t count); +namespace usbserial +{ + void init(); + bool is_active(); + + size_t read(void *buffer, size_t count); + size_t write(const void *buffer, size_t count); +} #endif // STMDSP_USBSERIAL_HPP_ From 29e4b4cf091dd47c9f435ef1d315a1609b83fb19 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sat, 15 Aug 2020 09:16:54 -0400 Subject: [PATCH 2/2] add elf load draft, filter program template --- .gitignore | 1 + filter/Makefile | 14 +++++++ filter/test.cpp | 15 +++++++ source/elf_format.hpp | 93 +++++++++++++++++++++++++++++++++++++++++++ source/elf_load.cpp | 77 +++++++++++++++++++++++++++++++++++ source/elf_load.hpp | 12 ++++++ 6 files changed, 212 insertions(+) create mode 100644 filter/Makefile create mode 100644 filter/test.cpp create mode 100644 source/elf_format.hpp create mode 100644 source/elf_load.cpp create mode 100644 source/elf_load.hpp diff --git a/.gitignore b/.gitignore index c24aa5f..d01aefe 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ ChibiOS_* **/.* gui/stmdspgui **/*.o +**/*.so perf* diff --git a/filter/Makefile b/filter/Makefile new file mode 100644 index 0000000..a1ce186 --- /dev/null +++ b/filter/Makefile @@ -0,0 +1,14 @@ +all: + @arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Os --specs=nosys.specs -nostartfiles -fPIE -c test.cpp + @arm-none-eabi-ld -shared -n -N -z max-page-size=512 -Ttext-segment=0 \ + test.o -o test.so + @arm-none-eabi-strip -s -S --strip-unneeded test.so + @arm-none-eabi-objcopy --remove-section .dynsym \ + --remove-section .dynstr \ + --remove-section .dynamic \ + --remove-section .hash \ + --remove-section .ARM.exidx \ + --remove-section .ARM.attributes \ + --remove-section .comment \ + test.so + diff --git a/filter/test.cpp b/filter/test.cpp new file mode 100644 index 0000000..0953539 --- /dev/null +++ b/filter/test.cpp @@ -0,0 +1,15 @@ +#include + +using adcsample_t = uint16_t; +__attribute__((section(".process_data"))) +void process_data(adcsample_t *samples, unsigned int size); + +//////////////////////////////////////////////////////////////////////////////// + +void process_data(adcsample_t *samples, unsigned int size) +{ + size--; + for (unsigned int i = 0; i < size; i++) + samples[i] = samples[i] * 80 / 100 + samples[i + 1] * 20 / 100; +} + diff --git a/source/elf_format.hpp b/source/elf_format.hpp new file mode 100644 index 0000000..ed74c7b --- /dev/null +++ b/source/elf_format.hpp @@ -0,0 +1,93 @@ +#ifndef STMDSP_ELF_FORMAT_HPP_ +#define STMDSP_ELF_FORMAT_HPP_ + +#include + +#define EI_NIDENT 16 + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_RESERVED 0x70000000 + +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xF) +#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t) & 0xF)) + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xFF) +#define ELF32_R_INFO(s, t) (((s) << 8) + ((t) & 0xFF)) + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef uint32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} __attribute__((packed)) Elf32_Ehdr; + +typedef struct { + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} __attribute__((packed)) Elf32_Shdr; + +typedef struct { + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} __attribute__((packed)) Elf32_Sym; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} __attribute__((packed)) Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} __attribute__((packed)) Elf32_Rela; + +typedef struct { + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} __attribute__((packed)) Elf32_Phdr; + +#endif // STMDSP_ELF_FORMAT_HPP_ + diff --git a/source/elf_load.cpp b/source/elf_load.cpp new file mode 100644 index 0000000..661dbc3 --- /dev/null +++ b/source/elf_load.cpp @@ -0,0 +1,77 @@ +#include "elf_load.hpp" +#include "elf_format.hpp" + +#include +#include + +extern void *elf_load_offset; +static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' }; + +template +constexpr static auto ptr_from_offset(void *base, uint32_t offset) +{ + return reinterpret_cast(reinterpret_cast(base) + offset); +} + +static Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name); + +namespace elf { + +entry_t elf_load(void *elf_data) +{ + auto ehdr = reinterpret_cast(elf_data); + if (std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header)) + return nullptr; + + auto phdr = ptr_from_offset(elf_data, ehdr->e_phoff); + for (Elf32_Half i = 0; i < ehdr->e_phnum; i++) { + if (phdr->p_type == PT_LOAD) { + std::memcpy(ptr_from_offset(elf_load_offset, phdr->p_vaddr), + ptr_from_offset(elf_data, phdr->p_offset), + phdr->p_filesz); + //break; + } + } + + // Zero .bss section + if (auto bss_section = find_section(ehdr, ".bss"); bss_section) { + auto bss = ptr_from_offset(elf_load_offset, bss_section->sh_addr); + std::fill(bss, bss + bss_section->sh_size / sizeof(uint32_t), 0); + } + + // Fix global offset table (GOT) entries + if (auto got_section = find_section(ehdr, ".got"); got_section) { + auto got = ptr_from_offset(elf_load_offset, got_section->sh_addr); + for (size_t i = 0; i < got_section->sh_size / sizeof(void *); i++) + got[i] = ptr_from_offset(got[i], reinterpret_cast(elf_load_offset)); + } + + //// Run any initial constructors + //if (auto init_section = find_section(ehdr, ".init_array"); init_section) { + // auto init_array = reinterpret_cast(elf_load_offset + init_section->sh_addr); + // std::for_each(init_array, init_array + init_section->sh_size / sizeof(void (*)()), + // [elf_load_offset](auto func) { (func + elf_load_offset)(); }); + //} + + return ptr_from_offset(elf_load_offset, ehdr->e_entry); +} + +} // namespace elf + +Elf32_Shdr *find_section(Elf32_Ehdr *ehdr, const char *name) +{ + auto shdr = ptr_from_offset(ehdr, ehdr->e_shoff); + auto shdr_str = ptr_from_offset(ehdr, + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize); + + for (Elf32_Half i = 0; i < ehdr->e_shnum; i++) { + char *section = ptr_from_offset(ehdr, shdr_str->sh_offset) + shdr->sh_name; + if (!strcmp(section, name)) + return shdr; + + shdr = ptr_from_offset(shdr, ehdr->e_shentsize); + } + + return 0; +} + diff --git a/source/elf_load.hpp b/source/elf_load.hpp new file mode 100644 index 0000000..722b19b --- /dev/null +++ b/source/elf_load.hpp @@ -0,0 +1,12 @@ +#ifndef ELF_LOAD_HPP_ +#define ELF_LOAD_HPP_ + +namespace elf +{ + using entry_t = void (*)(); + + entry_t load(void *file_data); +} + +#endif // ELF_LOAD_HPP_ +