From 4611bbac2341e9e586434b45637fe00ec0e33478 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Thu, 24 Sep 2020 09:48:08 -0400 Subject: [PATCH] better elf management and error recovery --- Makefile | 2 +- gui/wxmain.cpp | 12 ++--- source/adc.cpp | 25 +++++----- source/dac.cpp | 2 +- source/main.cpp | 122 ++++++++++++++++++++++++------------------------ 5 files changed, 81 insertions(+), 82 deletions(-) diff --git a/Makefile b/Makefile index 75633ed..50e7905 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,7 @@ endif # Stack size to be allocated to the Cortex-M process stack. This stack is # the stack used by the main() thread. ifeq ($(USE_PROCESS_STACKSIZE),) - USE_PROCESS_STACKSIZE = 0x400 + USE_PROCESS_STACKSIZE = 8192 endif # Stack size to the allocated to the Cortex-M main/exceptions stack. This diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp index fa9118d..0c6c9b3 100644 --- a/gui/wxmain.cpp +++ b/gui/wxmain.cpp @@ -181,7 +181,8 @@ void MainFrame::prepareEditor() static const char *makefile_text = R"make( all: - @arm-none-eabi-g++ -x c++ -mcpu=cortex-m4 -mthumb -Os --specs=nosys.specs -nostartfiles -fPIE $0 -o $0.o -Wl,-Ttext-segment=0 -Wl,-eprocess_data_entry -Wl,-zmax-page-size=512 + @arm-none-eabi-g++ -x c++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Os --specs=nosys.specs -nostartfiles -fPIE $0 -o $0.o -Wl,-Ttext-segment=0 -Wl,-eprocess_data_entry -Wl,-zmax-page-size=512 + @cp $0.o $0.orig.o @arm-none-eabi-strip -s -S --strip-unneeded $0.o @arm-none-eabi-objcopy --remove-section .ARM.exidx \ --remove-section .ARM.attributes \ @@ -195,14 +196,7 @@ static const char *file_header = R"cpp( using adcsample_t = uint16_t; -static void process_data(adcsample_t *samples, unsigned int size); - -__attribute__((optimize("-O0"))) -static void *alloc(unsigned int count) { - void *result = nullptr; - asm("mov r0, %0; mov r1, %1; svc 0" :: "r" (&result), "r" (count)); - return result; -} +void process_data(adcsample_t *samples, unsigned int size); extern "C" void process_data_entry() { auto func = (void (*)())process_data; diff --git a/source/adc.cpp b/source/adc.cpp index c912a7e..f63c386 100644 --- a/source/adc.cpp +++ b/source/adc.cpp @@ -20,7 +20,7 @@ constexpr static const ADCConfig adc_config = { static void adc_read_callback(ADCDriver *); -/*constexpr*/ static ADCConversionGroup adc_group_config = { +static ADCConversionGroup adc_group_config = { .circular = false, .num_channels = 1, .end_cb = adc_read_callback, @@ -29,7 +29,7 @@ static void adc_read_callback(ADCDriver *); .cfgr2 = 0, .tr1 = ADC_TR(0, 4095), .smpr = { - ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5), 0 + ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5), 0 }, .sqr = { ADC_SQR1_SQ1_N(ADC_CHANNEL_IN5), @@ -65,7 +65,7 @@ namespace adc adc_is_read_finished = false; adc_group_config.circular = false; adcStartConversion(adcd, &adc_group_config, buffer, count); - gptStartContinuous(gptd, 2); + gptStartContinuous(gptd, 8); while (!adc_is_read_finished); return buffer; } @@ -77,12 +77,13 @@ namespace adc adc_operation_func = operation_func; adc_group_config.circular = true; adcStartConversion(adcd, &adc_group_config, buffer, count); - gptStartContinuous(gptd, 2); + gptStartContinuous(gptd, 8); } void read_stop() { gptStopTimer(gptd); + adcStopConversion(adcd); adc_group_config.circular = false; adc_current_buffer = nullptr; adc_current_buffer_size = 0; @@ -126,15 +127,17 @@ namespace adc void adc_read_callback(ADCDriver *driver) { - if (!adc_group_config.circular) { + if (adc_group_config.circular) { + if (adc_operation_func != nullptr) { + auto half_size = adc_current_buffer_size / 2; + if (adcIsBufferComplete(driver)) + adc_operation_func(adc_current_buffer + half_size, half_size); + else + adc_operation_func(adc_current_buffer, half_size); + } + } else { gptStopTimer(gptd); adc_is_read_finished = true; - } else if (adc_operation_func != nullptr) { - auto half_size = adc_current_buffer_size / 2; - if (adcIsBufferComplete(driver)) - adc_operation_func(adc_current_buffer + half_size, half_size); - else - adc_operation_func(adc_current_buffer, half_size); } } diff --git a/source/dac.cpp b/source/dac.cpp index 6d5950e..8fae1e5 100644 --- a/source/dac.cpp +++ b/source/dac.cpp @@ -48,7 +48,7 @@ namespace dac void write_start(dacsample_t *buffer, size_t count) { dacStartConversion(dacd, &dac_group_config, buffer, count); - gptStartContinuous(gptd, 2); + gptStartContinuous(gptd, 8); } void write_stop() diff --git a/source/main.cpp b/source/main.cpp index f55c801..1e2772a 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -22,10 +22,19 @@ enum class RunStatus : char { Idle = '1', - Converting + Converting, + Recovered }; static RunStatus run_status = RunStatus::Idle; +#define MSG_CONVFIRST (1) +#define MSG_CONVSECOND (2) + +static msg_t conversionMBBuffer[8]; +static MAILBOX_DECL(conversionMB, conversionMBBuffer, 8); + +static THD_WORKING_AREA(conversionThreadWA, 1024); +static THD_FUNCTION(conversionThread, arg); static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); @@ -40,24 +49,34 @@ CC_ALIGN(CACHE_LINE_SIZE) static std::array dac_samples; static uint8_t elf_file_store[2048]; -static uint8_t elf_exec_store[2048]; +static uint8_t elf_exec_store[4096]; static elf::entry_t elf_entry = nullptr; -static volatile bool signal_operate_done = false; - static void signal_operate(adcsample_t *buffer, size_t count); +static void main_loop(); int main() { halInit(); chSysInit(); + // Enable FPU + SCB->CPACR |= 0xF << 20; + palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); // LED adc::init(); dac::init(); usbserial::init(); + chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA), + NORMALPRIO, + conversionThread, nullptr); + main_loop(); +} + +void main_loop() +{ static unsigned int dac_sample_count = 2048; while (true) { if (usbserial::is_active()) { @@ -79,7 +98,6 @@ int main() dac::write_start(&dac_samples[0], dac_samples.size()); break; case 's': - while (!signal_operate_done); usbserial::write(dac_samples.data(), dac_samples.size() * sizeof(adcsample_t)); break; case 'S': @@ -124,62 +142,42 @@ int main() } } -void quick_freeall(); - -void signal_operate(adcsample_t *buffer, size_t count) -{ - if (elf_entry) { - elf_entry(buffer, count); - quick_freeall(); - } - - auto dac_buffer = &dac_samples[buffer == &adc_samples[0] ? 0 : 1024]; - std::copy(buffer, buffer + count, dac_buffer); - signal_operate_done = buffer == &adc_samples[1024]; -} - -// Dynamic memory allocation below - -uint8_t quick_malloc_heap[8192]; -uint8_t *quick_malloc_next = quick_malloc_heap; - -void *quick_malloc(unsigned int size) -{ - if (auto free = std::distance(quick_malloc_next, quick_malloc_heap + 8192); free < 0 || size > static_cast(free)) - return nullptr; - - auto ptr = quick_malloc_next; - quick_malloc_next += size; - return ptr; -} - -void quick_freeall() +void conversion_abort() { - if (quick_malloc_next != quick_malloc_heap) - quick_malloc_next = quick_malloc_heap; + elf_entry = nullptr; + dac::write_stop(); + adc::read_stop(); + run_status = RunStatus::Recovered; } -void port_syscall(struct port_extctx *ctxp, uint32_t n) +THD_FUNCTION(conversionThread, arg) { - switch (n) { - case 0: - *reinterpret_cast(ctxp->r0) = quick_malloc(ctxp->r1); - break; - case 1: - quick_freeall(); - break; + (void)arg; + + while (1) { + msg_t message; + if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) { + auto samples = &adc_samples[0]; + auto halfsize = adc_samples.size() / 2; + if (message == MSG_CONVFIRST) { + if (elf_entry) + elf_entry(samples, halfsize); + std::copy(samples, samples + halfsize, &dac_samples[0]); + } else if (message == MSG_CONVSECOND) { + if (elf_entry) + elf_entry(samples + halfsize, halfsize); + std::copy(samples + halfsize, samples + halfsize * 2, &dac_samples[1024]); + } + } } - - chSysHalt("svc"); } -void conversion_abort() +void signal_operate(adcsample_t *buffer, size_t count) { - elf_entry = nullptr; - dac::write_stop(); - adc::read_stop(); - signal_operate_done = true; - run_status = RunStatus::Idle; + if (chMBGetUsedCountI(&conversionMB) > 1) + conversion_abort(); + else + chMBPostI(&conversionMB, buffer == &adc_samples[0] ? MSG_CONVFIRST : MSG_CONVSECOND); } extern "C" { @@ -189,14 +187,18 @@ void HardFault_Handler() { asm("push {lr}"); - if (run_status == RunStatus::Converting) { - uint32_t *stack; - asm("mrs %0, msp" : "=r" (stack)); - stack[6] = stack[5]; // Escape from elf_entry code - stack[7] |= (1 << 24); // Keep Thumb mode enabled + uint32_t *stack; + asm("mrs %0, psp" : "=r" (stack)); + //stack++; + stack[7] |= (1 << 24); // Keep Thumb mode enabled - conversion_abort(); - } + conversion_abort(); + + //if (run_status == RunStatus::Converting) { + // stack[6] = stack[5]; // Escape from elf_entry code + //} else /*if (run_status == RunStatus::Recovered)*/ { + stack[6] = (uint32_t)main_loop & ~1; // Return to safety + //} asm("pop {lr}; bx lr"); }