firmware cleanup, thread optimizing; make buffer size refs consistent

pull/3/head
Clyne 3 years ago
parent 87851f4e6c
commit 3668d16828

@ -581,7 +581,7 @@ void MainFrame::onRunLogResults(wxCommandEvent& ce)
void MainFrame::onRunEditBSize(wxCommandEvent&)
{
wxTextEntryDialog dialog (this, "Enter new buffer size (100-3000)", "Set Buffer Size");
wxTextEntryDialog dialog (this, "Enter new buffer size (100-4000)", "Set Buffer Size");
if (dialog.ShowModal() == wxID_OK) {
if (wxString value = dialog.GetValue(); !value.IsEmpty()) {
if (unsigned long n; value.ToULong(&n)) {
@ -610,8 +610,9 @@ void MainFrame::onToolbarSampleRate(wxCommandEvent& ce)
void MainFrame::onRunGenUpload(wxCommandEvent&)
{
wxTextEntryDialog dialog (this, "Enter generator values below. Values must be whole numbers "
"between zero and 4095.", "Enter Generator Values");
wxTextEntryDialog dialog (this, "Enter up to 8000 generator values below. "
"Values must be whole numbers between zero and 4095.",
"Enter Generator Values");
if (dialog.ShowModal() == wxID_OK) {
if (wxString values = dialog.GetValue(); !values.IsEmpty()) {
if (values[0] == '/') {
@ -625,7 +626,7 @@ void MainFrame::onRunGenUpload(wxCommandEvent&)
}
} else {
std::vector<stmdsp::dacsample_t> samples;
while (!values.IsEmpty()) {
while (!values.IsEmpty() && samples.size() <= stmdsp::SAMPLES_MAX * 2) {
if (auto number_end = values.find_first_not_of("0123456789");
number_end != wxString::npos && number_end > 0)
{
@ -649,7 +650,7 @@ void MainFrame::onRunGenUpload(wxCommandEvent&)
m_device->siggen_upload(&samples[0], samples.size());
m_status_bar->SetStatusText("Generator ready.");
} else {
m_status_bar->SetStatusText("Error: Too many samples.");
m_status_bar->SetStatusText("Error: Too many samples (max is 8000).");
}
}
} else {

@ -51,24 +51,29 @@ static MAILBOX_DECL(conversionMB, conversionMBBuffer, 2);
// Thread for LED status and wakeup hold
__attribute__((section(".stacks")))
static THD_WORKING_AREA(monitorThreadWA, 1024);
static THD_WORKING_AREA(monitorThreadWA, 4096);
static THD_FUNCTION(monitorThread, arg);
// Thread for managing the conversion task
__attribute__((section(".stacks")))
static THD_WORKING_AREA(conversionThreadMonitorWA, 1024);
static THD_WORKING_AREA(conversionThreadMonitorWA, 4096);
static THD_FUNCTION(conversionThreadMonitor, arg);
static thread_t *conversionThreadHandle = nullptr;
// Thread for unprivileged algorithm execution
__attribute__((section(".stacks")))
static THD_WORKING_AREA(conversionThreadWA, 1024);
static THD_WORKING_AREA(conversionThreadWA, 128); // All we do is enter unprivileged mode.
static THD_FUNCTION(conversionThread, arg);
__attribute__((section(".convdata")))
static THD_WORKING_AREA(conversionThreadUPWA, 62 * 1024);
static thread_t *conversionThreadHandle = nullptr;
__attribute__((section(".convdata")))
static thread_t *conversionThreadMonitorHandle = nullptr;
__attribute__((section(".convdata")))
// Thread for USB monitoring
__attribute__((section(".stacks")))
static THD_WORKING_AREA(communicationThreadWA, 4096);
static THD_FUNCTION(communicationThread, arg);
static time_measurement_t conversion_time_measurement;
__attribute__((section(".convdata")))
static SampleBuffer samplesIn (reinterpret_cast<Sample *>(0x38000000)); // 16k
@ -81,9 +86,13 @@ static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
__attribute__((section(".convdata")))
static ELF::Entry elf_entry = nullptr;
__attribute__((section(".convcode")))
static void conversion_unprivileged_main();
static void mpu_setup();
static void conversion_abort();
static void signal_operate(adcsample_t *buffer, size_t count);
static void signal_operate_measure(adcsample_t *buffer, size_t count);
static void main_loop();
int main()
{
@ -91,31 +100,10 @@ int main()
halInit();
chSysInit();
palSetLineMode(LINE_BUTTON, PAL_MODE_INPUT);
// Enable FPU
SCB->CPACR |= 0xF << 20;
// Set up MPU for user algorithm
// Region 2: Data for algorithm manager thread
mpuConfigureRegion(MPU_REGION_2,
0x20000000,
MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_64K |
MPU_RASR_ENABLE);
// Region 3: Code for algorithm manager thread
mpuConfigureRegion(MPU_REGION_3,
0x0807F800,
MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_2K |
MPU_RASR_ENABLE);
// Region 4: Algorithm code
mpuConfigureRegion(MPU_REGION_4,
0x00000000,
MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_64K |
MPU_RASR_ENABLE);
SCB->CPACR |= 0xF << 20; // Enable FPU
mpu_setup();
palSetLineMode(LINE_BUTTON, PAL_MODE_INPUT);
ADC::begin();
DAC::begin();
SClock::begin();
@ -126,21 +114,31 @@ int main()
ADC::setRate(SClock::Rate::R32K);
chTMObjectInit(&conversion_time_measurement);
chThdCreateStatic(monitorThreadWA, sizeof(monitorThreadWA),
NORMALPRIO, monitorThread, nullptr);
chThdCreateStatic(
monitorThreadWA, sizeof(monitorThreadWA),
LOWPRIO,
monitorThread, nullptr);
conversionThreadMonitorHandle = chThdCreateStatic(
conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA),
NORMALPRIO, conversionThreadMonitor, nullptr);
conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA),
NORMALPRIO + 1,
conversionThreadMonitor, nullptr);
conversionThreadHandle = chThdCreateStatic(
conversionThreadWA, sizeof(conversionThreadWA),
NORMALPRIO + 1, conversionThread, nullptr);
main_loop();
conversionThreadWA, sizeof(conversionThreadWA),
HIGHPRIO,
conversionThread,
reinterpret_cast<void *>(reinterpret_cast<uint32_t>(conversionThreadUPWA) + 62 * 1024));
chThdCreateStatic(
communicationThreadWA, sizeof(communicationThreadWA),
NORMALPRIO,
communicationThread, nullptr);
chThdExit(0);
return 0;
}
void main_loop()
THD_FUNCTION(communicationThread, arg)
{
(void)arg;
while (1) {
if (USBSerial::isActive()) {
// Attempt to receive a command packet
@ -148,6 +146,24 @@ void main_loop()
// Packet received, first byte represents the desired command/action
switch (cmd[0]) {
// 'a' - Read contents of ADC buffer.
// 'A' - Write contents of ADC buffer.
// 'B' - Set ADC/DAC buffer size.
// 'd' - Read contents of DAC buffer.
// 'D' - Set siggen size and write to its buffer.
// 'E' - Load algorithm binary.
// 'e' - Unload algorithm.
// 'i' - Read "stmdsp" identifier string.
// 'I' - Read status information.
// 'M' - Begin conversion, measure algorithm execution time.
// 'm' - Read last algorithm execution time.
// 'R' - Begin conversion.
// 'r' - Read or write sample rate.
// 'S' - Stop conversion.
// 's' - Get latest block of conversion results.
// 'W' - Start signal generator (siggen).
// 'w' - Stop siggen.
case 'a':
USBSerial::write(samplesIn.bytedata(), samplesIn.bytesize());
break;
@ -159,6 +175,8 @@ void main_loop()
if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) &&
EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize))
{
// count is multiplied by two since this command receives size of buffer
// for each algorithm application.
unsigned int count = (cmd[1] | (cmd[2] << 8)) * 2;
if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) {
samplesIn.setSize(count);
@ -308,17 +326,6 @@ void main_loop()
}
}
void conversion_abort()
{
elf_entry = nullptr;
DAC::stop(0);
ADC::stop();
EM.add(Error::ConversionAborted);
chMBReset(&conversionMB);
run_status = RunStatus::Idle;
}
THD_FUNCTION(conversionThreadMonitor, arg)
{
(void)arg;
@ -333,22 +340,57 @@ THD_FUNCTION(conversionThreadMonitor, arg)
}
}
__attribute__((section(".convcode")))
static void convThdMain();
THD_FUNCTION(conversionThread, stack)
{
elf_entry = nullptr;
port_unprivileged_jump(reinterpret_cast<uint32_t>(conversion_unprivileged_main),
reinterpret_cast<uint32_t>(stack));
}
THD_FUNCTION(conversionThread, arg)
THD_FUNCTION(monitorThread, arg)
{
(void)arg;
elf_entry = nullptr;
port_unprivileged_jump(reinterpret_cast<uint32_t>(convThdMain),
reinterpret_cast<uint32_t>(conversionThreadUPWA) + 256);
bool erroron = false;
while (1) {
bool isidle = run_status == RunStatus::Idle;
auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW;
auto delay = isidle ? 500 : 250;
palSetLine(led);
chThdSleepMilliseconds(delay);
palClearLine(led);
chThdSleepMilliseconds(delay);
if (run_status == RunStatus::Idle && palReadLine(LINE_BUTTON)) {
palSetLine(LINE_LED_RED);
palSetLine(LINE_LED_YELLOW);
chSysLock();
while (palReadLine(LINE_BUTTON))
asm("nop");
while (!palReadLine(LINE_BUTTON))
asm("nop");
chSysUnlock();
palClearLine(LINE_LED_RED);
palClearLine(LINE_LED_YELLOW);
chThdSleepMilliseconds(500);
}
if (auto err = EM.hasError(); err ^ erroron) {
erroron = err;
if (err)
palSetLine(LINE_LED_RED);
else
palClearLine(LINE_LED_RED);
}
}
}
void convThdMain()
void conversion_unprivileged_main()
{
while (1) {
msg_t message;
asm("svc 0; mov %0, r0" : "=r" (message));
asm("svc 0; mov %0, r0" : "=r" (message)); // sleep until next message
if (message != 0) {
auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata();
auto size = samplesIn.size() / 2;
@ -357,9 +399,9 @@ void convThdMain()
if (!MSG_FOR_MEASURE(message)) {
samples = elf_entry(samples, size);
} else {
//chTMStartMeasurementX(&conversion_time_measurement);
asm("eor r0, r0; svc 2"); // start measurement
samples = elf_entry(samples, size);
//chTMStopMeasurementX(&conversion_time_measurement);
asm("mov r0, #1; svc 2"); // stop measurement
}
}
@ -371,6 +413,40 @@ void convThdMain()
}
}
void mpu_setup()
{
// Set up MPU for user algorithm
// Region 2: Data for algorithm manager thread
mpuConfigureRegion(MPU_REGION_2,
0x20000000,
MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_64K |
MPU_RASR_ENABLE);
// Region 3: Code for algorithm manager thread
mpuConfigureRegion(MPU_REGION_3,
0x0807F800,
MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_2K |
MPU_RASR_ENABLE);
// Region 4: Algorithm code
mpuConfigureRegion(MPU_REGION_4,
0x00000000,
MPU_RASR_ATTR_AP_RW_RW | MPU_RASR_ATTR_NON_CACHEABLE |
MPU_RASR_SIZE_64K |
MPU_RASR_ENABLE);
}
void conversion_abort()
{
elf_entry = nullptr;
DAC::stop(0);
ADC::stop();
EM.add(Error::ConversionAborted);
chMBReset(&conversionMB);
run_status = RunStatus::Idle;
}
void signal_operate(adcsample_t *buffer, size_t)
{
chSysLockFromISR();
@ -387,51 +463,13 @@ void signal_operate(adcsample_t *buffer, size_t)
void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count)
{
chSysLockFromISR();
chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST_MEASURE : MSG_CONVSECOND_MEASURE);
chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST_MEASURE
: MSG_CONVSECOND_MEASURE);
chSysUnlockFromISR();
ADC::setOperation(signal_operate);
}
THD_FUNCTION(monitorThread, arg)
{
(void)arg;
bool erroron = false;
while (1) {
bool isidle = run_status == RunStatus::Idle;
auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW;
auto delay = isidle ? 500 : 250;
palSetLine(led);
chThdSleepMilliseconds(delay);
palClearLine(led);
chThdSleepMilliseconds(delay);
if (run_status == RunStatus::Idle && palReadLine(LINE_BUTTON)) {
palSetLine(LINE_LED_RED);
palSetLine(LINE_LED_YELLOW);
chSysLock();
while (palReadLine(LINE_BUTTON))
asm("nop");
while (!palReadLine(LINE_BUTTON))
asm("nop");
chSysUnlock();
palClearLine(LINE_LED_RED);
palClearLine(LINE_LED_YELLOW);
chThdSleepMilliseconds(500);
}
if (auto err = EM.hasError(); err ^ erroron) {
erroron = err;
if (err)
palSetLine(LINE_LED_RED);
else
palClearLine(LINE_LED_RED);
}
}
}
extern "C" {
__attribute__((naked))
@ -466,6 +504,19 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n)
}
}
break;
case 2:
if (ctxp->r0 == 0) {
chTMStartMeasurementX(&conversion_time_measurement);
} else {
chTMStopMeasurementX(&conversion_time_measurement);
// Subtract measurement overhead from the result.
// Running an empty algorithm ("bx lr") takes 196 cycles as of 2/4/21.
// Only measures algorithm code time (loading args/storing result takes 9 cycles).
constexpr rtcnt_t measurement_overhead = 196 - 1;
if (conversion_time_measurement.last > measurement_overhead)
conversion_time_measurement.last -= measurement_overhead;
}
break;
default:
while (1);
break;
@ -475,6 +526,12 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n)
while (1);
}
__attribute__((naked))
void MemManage_Handler()
{
while (1);
}
__attribute__((naked))
void HardFault_Handler()
{

@ -6,7 +6,7 @@
using Sample = uint16_t;
// gives 8000
// gives 8000 (8192)
constexpr unsigned int MAX_SAMPLE_BUFFER_BYTESIZE = 16384;
constexpr unsigned int MAX_SAMPLE_BUFFER_SIZE = MAX_SAMPLE_BUFFER_BYTESIZE / sizeof(Sample);

Loading…
Cancel
Save