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
# 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

@ -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;

@ -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) {
gptStopTimer(gptd);
adc_is_read_finished = true;
} else if (adc_operation_func != nullptr) {
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;
}
}

@ -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()

@ -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<dacsample_t, CACHE_SIZE_ALIGN(dacsample_t, 2048)> 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<unsigned int>(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<void **>(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
asm("mrs %0, psp" : "=r" (stack));
//stack++;
stack[7] |= (1 << 24); // Keep Thumb mode enabled
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");
}

Loading…
Cancel
Save