aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2021-02-04 21:14:19 -0500
committerClyne Sullivan <clyne@bitgloo.com>2021-02-04 21:14:19 -0500
commit3668d168288ef085724f0c48bd7a4123599f2719 (patch)
treef495f33206769b65b6170d3c8e4d0bb7a8451aa7
parent87851f4e6c4aebd65e28ef16823ada7b197e2edc (diff)
firmware cleanup, thread optimizing; make buffer size refs consistent
-rw-r--r--gui/wxmain.cpp11
-rw-r--r--source/main.cpp261
-rw-r--r--source/samplebuffer.hpp2
3 files changed, 166 insertions, 108 deletions
diff --git a/gui/wxmain.cpp b/gui/wxmain.cpp
index 10e5d7a..c7acddf 100644
--- a/gui/wxmain.cpp
+++ b/gui/wxmain.cpp
@@ -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 {
diff --git a/source/main.cpp b/source/main.cpp
index d94f694..0dfc0e7 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -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;
@@ -476,6 +527,12 @@ void port_syscall(struct port_extctx *ctxp, uint32_t n)
}
__attribute__((naked))
+void MemManage_Handler()
+{
+ while (1);
+}
+
+__attribute__((naked))
void HardFault_Handler()
{
// Below not working (yet)
diff --git a/source/samplebuffer.hpp b/source/samplebuffer.hpp
index 9aabfdd..334c048 100644
--- a/source/samplebuffer.hpp
+++ b/source/samplebuffer.hpp
@@ -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);