better elf management and error recovery

pull/3/head
Clyne 4 years ago
parent a263d2ab42
commit 4611bbac23

@ -55,7 +55,7 @@ endif
# Stack size to be allocated to the Cortex-M process stack. This stack is # Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread. # the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),) ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400 USE_PROCESS_STACKSIZE = 8192
endif endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This # Stack size to the allocated to the Cortex-M main/exceptions stack. This

@ -181,7 +181,8 @@ void MainFrame::prepareEditor()
static const char *makefile_text = R"make( static const char *makefile_text = R"make(
all: 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-strip -s -S --strip-unneeded $0.o
@arm-none-eabi-objcopy --remove-section .ARM.exidx \ @arm-none-eabi-objcopy --remove-section .ARM.exidx \
--remove-section .ARM.attributes \ --remove-section .ARM.attributes \
@ -195,14 +196,7 @@ static const char *file_header = R"cpp(
using adcsample_t = uint16_t; using adcsample_t = uint16_t;
static void process_data(adcsample_t *samples, unsigned int size); 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;
}
extern "C" void process_data_entry() { extern "C" void process_data_entry() {
auto func = (void (*)())process_data; auto func = (void (*)())process_data;

@ -20,7 +20,7 @@ constexpr static const ADCConfig adc_config = {
static void adc_read_callback(ADCDriver *); static void adc_read_callback(ADCDriver *);
/*constexpr*/ static ADCConversionGroup adc_group_config = { static ADCConversionGroup adc_group_config = {
.circular = false, .circular = false,
.num_channels = 1, .num_channels = 1,
.end_cb = adc_read_callback, .end_cb = adc_read_callback,
@ -29,7 +29,7 @@ static void adc_read_callback(ADCDriver *);
.cfgr2 = 0, .cfgr2 = 0,
.tr1 = ADC_TR(0, 4095), .tr1 = ADC_TR(0, 4095),
.smpr = { .smpr = {
ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_2P5), 0 ADC_SMPR1_SMP_AN5(ADC_SMPR_SMP_24P5), 0
}, },
.sqr = { .sqr = {
ADC_SQR1_SQ1_N(ADC_CHANNEL_IN5), ADC_SQR1_SQ1_N(ADC_CHANNEL_IN5),
@ -65,7 +65,7 @@ namespace adc
adc_is_read_finished = false; adc_is_read_finished = false;
adc_group_config.circular = false; adc_group_config.circular = false;
adcStartConversion(adcd, &adc_group_config, buffer, count); adcStartConversion(adcd, &adc_group_config, buffer, count);
gptStartContinuous(gptd, 2); gptStartContinuous(gptd, 8);
while (!adc_is_read_finished); while (!adc_is_read_finished);
return buffer; return buffer;
} }
@ -77,12 +77,13 @@ namespace adc
adc_operation_func = operation_func; adc_operation_func = operation_func;
adc_group_config.circular = true; adc_group_config.circular = true;
adcStartConversion(adcd, &adc_group_config, buffer, count); adcStartConversion(adcd, &adc_group_config, buffer, count);
gptStartContinuous(gptd, 2); gptStartContinuous(gptd, 8);
} }
void read_stop() void read_stop()
{ {
gptStopTimer(gptd); gptStopTimer(gptd);
adcStopConversion(adcd);
adc_group_config.circular = false; adc_group_config.circular = false;
adc_current_buffer = nullptr; adc_current_buffer = nullptr;
adc_current_buffer_size = 0; adc_current_buffer_size = 0;
@ -126,15 +127,17 @@ namespace adc
void adc_read_callback(ADCDriver *driver) void adc_read_callback(ADCDriver *driver)
{ {
if (!adc_group_config.circular) { if (adc_group_config.circular) {
gptStopTimer(gptd); if (adc_operation_func != nullptr) {
adc_is_read_finished = true;
} else if (adc_operation_func != nullptr) {
auto half_size = adc_current_buffer_size / 2; auto half_size = adc_current_buffer_size / 2;
if (adcIsBufferComplete(driver)) if (adcIsBufferComplete(driver))
adc_operation_func(adc_current_buffer + half_size, half_size); adc_operation_func(adc_current_buffer + half_size, half_size);
else else
adc_operation_func(adc_current_buffer, half_size); adc_operation_func(adc_current_buffer, half_size);
} }
} else {
gptStopTimer(gptd);
adc_is_read_finished = true;
}
} }

@ -48,7 +48,7 @@ namespace dac
void write_start(dacsample_t *buffer, size_t count) void write_start(dacsample_t *buffer, size_t count)
{ {
dacStartConversion(dacd, &dac_group_config, buffer, count); dacStartConversion(dacd, &dac_group_config, buffer, count);
gptStartContinuous(gptd, 2); gptStartContinuous(gptd, 8);
} }
void write_stop() void write_stop()

@ -22,10 +22,19 @@
enum class RunStatus : char enum class RunStatus : char
{ {
Idle = '1', Idle = '1',
Converting Converting,
Recovered
}; };
static RunStatus run_status = RunStatus::Idle; 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(adcsample_t) == sizeof(uint16_t));
static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); static_assert(sizeof(dacsample_t) == sizeof(uint16_t));
@ -40,24 +49,34 @@ CC_ALIGN(CACHE_LINE_SIZE)
static std::array<dacsample_t, CACHE_SIZE_ALIGN(dacsample_t, 2048)> dac_samples; static std::array<dacsample_t, CACHE_SIZE_ALIGN(dacsample_t, 2048)> dac_samples;
static uint8_t elf_file_store[2048]; 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 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 signal_operate(adcsample_t *buffer, size_t count);
static void main_loop();
int main() int main()
{ {
halInit(); halInit();
chSysInit(); chSysInit();
// Enable FPU
SCB->CPACR |= 0xF << 20;
palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); // LED palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); // LED
adc::init(); adc::init();
dac::init(); dac::init();
usbserial::init(); usbserial::init();
chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA),
NORMALPRIO,
conversionThread, nullptr);
main_loop();
}
void main_loop()
{
static unsigned int dac_sample_count = 2048; static unsigned int dac_sample_count = 2048;
while (true) { while (true) {
if (usbserial::is_active()) { if (usbserial::is_active()) {
@ -79,7 +98,6 @@ int main()
dac::write_start(&dac_samples[0], dac_samples.size()); dac::write_start(&dac_samples[0], dac_samples.size());
break; break;
case 's': case 's':
while (!signal_operate_done);
usbserial::write(dac_samples.data(), dac_samples.size() * sizeof(adcsample_t)); usbserial::write(dac_samples.data(), dac_samples.size() * sizeof(adcsample_t));
break; break;
case 'S': case 'S':
@ -124,62 +142,42 @@ int main()
} }
} }
void quick_freeall(); void conversion_abort()
void signal_operate(adcsample_t *buffer, size_t count)
{ {
if (elf_entry) { elf_entry = nullptr;
elf_entry(buffer, count); dac::write_stop();
quick_freeall(); adc::read_stop();
} run_status = RunStatus::Recovered;
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 THD_FUNCTION(conversionThread, arg)
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<unsigned int>(free)) (void)arg;
return nullptr;
auto ptr = quick_malloc_next; while (1) {
quick_malloc_next += size; msg_t message;
return ptr; 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]);
} }
void quick_freeall()
{
if (quick_malloc_next != quick_malloc_heap)
quick_malloc_next = quick_malloc_heap;
} }
void port_syscall(struct port_extctx *ctxp, uint32_t n)
{
switch (n) {
case 0:
*reinterpret_cast<void **>(ctxp->r0) = quick_malloc(ctxp->r1);
break;
case 1:
quick_freeall();
break;
} }
chSysHalt("svc");
} }
void conversion_abort() void signal_operate(adcsample_t *buffer, size_t count)
{ {
elf_entry = nullptr; if (chMBGetUsedCountI(&conversionMB) > 1)
dac::write_stop(); conversion_abort();
adc::read_stop(); else
signal_operate_done = true; chMBPostI(&conversionMB, buffer == &adc_samples[0] ? MSG_CONVFIRST : MSG_CONVSECOND);
run_status = RunStatus::Idle;
} }
extern "C" { extern "C" {
@ -189,14 +187,18 @@ void HardFault_Handler()
{ {
asm("push {lr}"); asm("push {lr}");
if (run_status == RunStatus::Converting) {
uint32_t *stack; uint32_t *stack;
asm("mrs %0, msp" : "=r" (stack)); asm("mrs %0, psp" : "=r" (stack));
stack[6] = stack[5]; // Escape from elf_entry code //stack++;
stack[7] |= (1 << 24); // Keep Thumb mode enabled 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"); asm("pop {lr}; bx lr");
} }

Loading…
Cancel
Save