#
# List all user C define here, like -D_DEBUG=1
-UDEFS = -DCORTEX_ENABLE_WFI_IDLE=TRUE -DPORT_USE_SYSCALL=TRUE
+UDEFS = -DCORTEX_ENABLE_WFI_IDLE=TRUE \
+ -DPORT_USE_SYSCALL=TRUE \
+ -DPORT_USE_GUARD_MPU_REGION=MPU_REGION_0
# Define ASM defines here
UADEFS =
*/\r
\r
/*\r
- * STM32H743xI generic setup.\r
- * \r
* AXI SRAM - BSS, Data, Heap.\r
* SRAM1 - SIGGEN.\r
* SRAM2 - DAC.\r
* SRAM4 - ADC.\r
- * DTCM-RAM - Main Stack, Process Stack.\r
+ * DTCM-RAM - Unprivileged Stack, Main Stack, Process Stack.\r
* ITCM-RAM - STMDSP Algorithm.\r
* BCKP SRAM - None.\r
*/\r
MEMORY\r
{\r
- flash0 (rx) : org = 0x08000000, len = 1M /* Flash bank1+bank2 */\r
+ flash0 (rx) : org = 0x08000000, len = 1M /* Flash bank1 + bank2 */\r
+ flashc (rx) : org = 0x0807F000, len = 4K /* Unprivileged firmware */\r
flash1 (rx) : org = 0x08000000, len = 512K /* Flash bank 1 */\r
flash2 (rx) : org = 0x08080000, len = 512K /* Flash bank 2 */\r
flash3 (rx) : org = 0x00000000, len = 0\r
flash5 (rx) : org = 0x00000000, len = 0\r
flash6 (rx) : org = 0x00000000, len = 0\r
flash7 (rx) : org = 0x00000000, len = 0\r
- ram0 (wx) : org = 0x24000000, len = 320k /* AXI SRAM */\r
- ram1 (wx) : org = 0x30000000, len = 16k /* AHB SRAM1 */\r
- ram2 (wx) : org = 0x30004000, len = 16k /* AHB SRAM2 */\r
- ram3 (wx) : org = 0x38000000, len = 16k /* AHB SRAM4 */\r
+ ram0 (wx) : org = 0x24000000, len = 320K /* AXI SRAM */\r
+ ram1 (wx) : org = 0x30000000, len = 16K /* AHB SRAM1 */\r
+ ram2 (wx) : org = 0x30004000, len = 16K /* AHB SRAM2 */\r
+ ram3 (wx) : org = 0x38000000, len = 16K /* AHB SRAM4 */\r
ram4 (wx) : org = 0x00000000, len = 0\r
- ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */\r
- ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */\r
- ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */\r
+ ramc (wx) : org = 0x20000000, len = 4K /* Unprivileged data */\r
+ ram5 (wx) : org = 0x20001000, len = 124K /* DTCM-RAM */\r
+ ram6 (wx) : org = 0x00000000, len = 64K /* ITCM-RAM */\r
+ ram7 (wx) : org = 0x38800000, len = 4K /* BCKP SRAM */\r
}\r
\r
/* For each data/text section two region are defined, a virtual region\r
/* Stack rules inclusion.*/\r
INCLUDE rules_stacks.ld\r
\r
-/*===========================================================================*/\r
-/* Custom sections for STM32H7xx. */\r
-/* SRAM3 is assumed to be marked non-cacheable using MPU. */\r
-/*===========================================================================*/\r
-\r
-/* RAM region to be used for nocache segment.*/\r
-/*REGION_ALIAS("NOCACHE_RAM", ram3);*/\r
-\r
-/* RAM region to be used for eth segment.*/\r
-/*REGION_ALIAS("ETH_RAM", ram3);*/\r
-\r
SECTIONS\r
{\r
- /* Special section for non cache-able areas.*/\r
- /*.nocache (NOLOAD) : ALIGN(4)\r
+ .convdata : ALIGN(4)\r
{\r
- __nocache_base__ = .;\r
- *(.nocache)\r
- *(.nocache.*)\r
- *(.bss.__nocache_*)\r
+ *(.convdata)\r
. = ALIGN(4);\r
- __nocache_end__ = .;\r
- } > NOCACHE_RAM*/\r
+ } > ramc\r
\r
- /* Special section for Ethernet DMA non cache-able areas.*/\r
- /*.eth (NOLOAD) : ALIGN(4)\r
+ .convcode : ALIGN(4)\r
{\r
- __eth_base__ = .;\r
- *(.eth)\r
- *(.eth.*)\r
- *(.bss.__eth_*)\r
+ *(.convcode)\r
. = ALIGN(4);\r
- __eth_end__ = .;\r
- } > ETH_RAM*/\r
+ } > flashc\r
}\r
\r
/* Code rules inclusion.*/\r
/*\r
* Memory attributes settings.\r
*/\r
-#define STM32_NOCACHE_MPU_REGION MPU_REGION_6\r
+#define STM32_NOCACHE_MPU_REGION MPU_REGION_1\r
#define STM32_NOCACHE_SRAM1_SRAM2 FALSE\r
#define STM32_NOCACHE_SRAM3 FALSE\r
#define STM32_NOCACHE_ALLSRAM TRUE\r
+++ /dev/null
-#include <array>
-#include <cstdint>
-
-using Sample = uint16_t;
-
-// gives 8000
-constexpr unsigned int MAX_SAMPLE_BUFFER_BYTESIZE = 16384;
-constexpr unsigned int MAX_SAMPLE_BUFFER_SIZE = MAX_SAMPLE_BUFFER_BYTESIZE / sizeof(Sample);
-
-class SampleBuffer
-{
-public:
- SampleBuffer(Sample *buffer) :
- m_buffer(buffer) {}
-
- void clear() {
- std::fill(m_buffer, m_buffer + m_size, 2048);
- }
- void modify(Sample *data, unsigned int srcsize) {
- auto size = srcsize < m_size ? srcsize : m_size;
- std::copy(data, data + size, m_buffer);
- m_modified = m_buffer;
- }
- void midmodify(Sample *data, unsigned int srcsize) {
- auto size = srcsize < m_size / 2 ? srcsize : m_size / 2;
- std::copy(data, data + size, middata());
- m_modified = middata();
- }
-
- void setSize(unsigned int size) {
- m_size = size < MAX_SAMPLE_BUFFER_SIZE ? size : MAX_SAMPLE_BUFFER_SIZE;
- }
-
- Sample *data() {
- return m_buffer;
- }
- Sample *middata() {
- return m_buffer + m_size / 2;
- }
- uint8_t *bytedata() {
- return reinterpret_cast<uint8_t *>(m_buffer);
- }
-
- Sample *modified() {
- auto m = m_modified;
- m_modified = nullptr;
- return m;
- }
- unsigned int size() const {
- return m_size;
- }
- unsigned int bytesize() const {
- return m_size * sizeof(Sample);
- }
-
-private:
- Sample *m_buffer = nullptr;
- unsigned int m_size = MAX_SAMPLE_BUFFER_SIZE;
- Sample *m_modified = nullptr;
-};
-
static_assert(sizeof(adcsample_t) == sizeof(uint16_t));
static_assert(sizeof(dacsample_t) == sizeof(uint16_t));
-#include "common.hpp"
-#include "error.hpp"
-
#include "adc.hpp"
#include "cordic.hpp"
#include "dac.hpp"
#include "elf_load.hpp"
+#include "error.hpp"
+#include "samplebuffer.hpp"
#include "sclock.hpp"
#include "usbserial.hpp"
#define MSG_FOR_FIRST(m) (m & 1)
#define MSG_FOR_MEASURE(m) (m > 2)
-static msg_t conversionMBBuffer[4];
-static MAILBOX_DECL(conversionMB, conversionMBBuffer, 4);
+static ErrorManager EM;
-static THD_WORKING_AREA(conversionThreadWA, 2048);
+static msg_t conversionMBBuffer[2];
+static MAILBOX_DECL(conversionMB, conversionMBBuffer, 2);
+
+// Thread for LED status and wakeup hold
+static THD_WORKING_AREA(monitorThreadWA, 128);
+static THD_FUNCTION(monitorThread, arg);
+// Thread for managing the conversion task
+static THD_WORKING_AREA(conversionThreadMonitorWA, 128);
+static THD_FUNCTION(conversionThreadMonitor, arg);
+// Thread for unprivileged algorithm execution
+static THD_WORKING_AREA(conversionThreadWA, 128);
static THD_FUNCTION(conversionThread, arg);
+__attribute__((section(".convdata")))
+static THD_WORKING_AREA(conversionThreadUPWA, 256);
-static time_measurement_t conversion_time_measurement;
-
-static ErrorManager EM;
+static thread_t *conversionThreadHandle = nullptr;
+__attribute__((section(".convdata")))
+static thread_t *conversionThreadMonitorHandle = nullptr;
+__attribute__((section(".convdata")))
+static time_measurement_t conversion_time_measurement;
+__attribute__((section(".convdata")))
static SampleBuffer samplesIn (reinterpret_cast<Sample *>(0x38000000)); // 16k
+__attribute__((section(".convdata")))
static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x30004000)); // 16k
+
static SampleBuffer samplesSigGen (reinterpret_cast<Sample *>(0x30000000)); // 16k
static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
+__attribute__((section(".convdata")))
static ELF::Entry elf_entry = nullptr;
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();
-static THD_WORKING_AREA(waThread1, 128);
-static THD_FUNCTION(Thread1, arg);
-
int main()
{
// Initialize the RTOS
// 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_4K |
+ MPU_RASR_ENABLE);
+ // Region 3: Code for algorithm manager thread
+ mpuConfigureRegion(MPU_REGION_3,
+ 0x08080000,
+ MPU_RASR_ATTR_AP_RO_RO | MPU_RASR_ATTR_NON_CACHEABLE |
+ MPU_RASR_SIZE_4K |
+ 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);
+
ADC::begin();
DAC::begin();
SClock::begin();
ADC::setRate(SClock::Rate::R32K);
chTMObjectInit(&conversion_time_measurement);
- chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, nullptr);
- chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA),
- NORMALPRIO, conversionThread, nullptr);
+ chThdCreateStatic(monitorThreadWA, sizeof(monitorThreadWA),
+ NORMALPRIO, monitorThread, nullptr);
+ conversionThreadMonitorHandle = chThdCreateStatic(
+ conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA),
+ NORMALPRIO, conversionThreadMonitor, nullptr);
+ conversionThreadHandle = chThdCreateStatic(
+ conversionThreadWA, sizeof(conversionThreadWA),
+ NORMALPRIO + 1, conversionThread, nullptr);
main_loop();
}
run_status = RunStatus::Idle;
}
-THD_FUNCTION(conversionThread, arg)
+THD_FUNCTION(conversionThreadMonitor, arg)
{
(void)arg;
-
while (1) {
// Recover from algorithm fault if necessary
- if (run_status == RunStatus::Recovering)
- conversion_abort();
+ //if (run_status == RunStatus::Recovering)
+ // conversion_abort();
+
+ msg_t message;
+ if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK)
+ chMsgSend(conversionThreadHandle, message);
+ }
+}
+
+__attribute__((section(".convcode")))
+static void convThdMain();
+THD_FUNCTION(conversionThread, arg)
+{
+ (void)arg;
+ elf_entry = nullptr;
+ port_unprivileged_jump(reinterpret_cast<uint32_t>(convThdMain),
+ reinterpret_cast<uint32_t>(conversionThreadUPWA) + 256);
+}
+
+void convThdMain()
+{
+ while (1) {
msg_t message;
- if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) {
- static Sample *samples = nullptr;
- static unsigned int size = 0;
- samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata();
- size = samplesIn.size() / 2;
+ asm("svc 0; mov %0, r0" : "=r" (message));
+ if (message != 0) {
+ auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata();
+ auto size = samplesIn.size() / 2;
if (elf_entry) {
if (!MSG_FOR_MEASURE(message)) {
- //asm("cpsid i");
- //mpuDisable();
- //port_unprivileged_jump((uint32_t)+[] {
- samples = elf_entry(samples, size);
- //}, 0xF800);
- //mpuEnable(MPU_CTRL_PRIVDEFENA);
- //asm("cpsie i");
+ samples = elf_entry(samples, size);
} else {
- chTMStartMeasurementX(&conversion_time_measurement);
+ //chTMStartMeasurementX(&conversion_time_measurement);
samples = elf_entry(samples, size);
- chTMStopMeasurementX(&conversion_time_measurement);
+ //chTMStopMeasurementX(&conversion_time_measurement);
}
}
ADC::setOperation(signal_operate);
}
-THD_FUNCTION(Thread1, arg)
+THD_FUNCTION(monitorThread, arg)
{
(void)arg;
extern "C" {
+__attribute__((naked))
+void port_syscall(struct port_extctx *ctxp, uint32_t n)
+{
+ switch (n) {
+ case 0: {
+ chSysLock();
+ chMsgWaitS();
+ auto msg = chMsgGet(conversionThreadMonitorHandle);
+ chMsgReleaseS(conversionThreadMonitorHandle, MSG_OK);
+ //chSchDoYieldS();
+ chSysUnlock();
+ ctxp->r0 = msg;
+ }
+ break;
+ default:
+ while (1);
+ break;
+ }
+
+ asm("svc 0");
+ while (1);
+}
+
__attribute__((naked))
void HardFault_Handler()
{
--- /dev/null
+#include "common.hpp"
+
+SampleBuffer::SampleBuffer(Sample *buffer) :
+ m_buffer(buffer) {}
+
+void SampleBuffer::clear() {
+ std::fill(m_buffer, m_buffer + m_size, 2048);
+}
+__attribute__((section(".convcode")))
+void SampleBuffer::modify(Sample *data, unsigned int srcsize) {
+ auto size = srcsize < m_size ? srcsize : m_size;
+ for (Sample *d = data, *s = m_buffer; d != data + size;)
+ *d++ = *s++;
+ m_modified = m_buffer;
+}
+__attribute__((section(".convcode")))
+void SampleBuffer::midmodify(Sample *data, unsigned int srcsize) {
+ auto size = srcsize < m_size / 2 ? srcsize : m_size / 2;
+ for (Sample *d = data, *s = middata(); d != data + size;)
+ *d++ = *s++;
+ m_modified = middata();
+}
+
+void SampleBuffer::setSize(unsigned int size) {
+ m_size = size < MAX_SAMPLE_BUFFER_SIZE ? size : MAX_SAMPLE_BUFFER_SIZE;
+}
+
+__attribute__((section(".convcode")))
+Sample *SampleBuffer::data() {
+ return m_buffer;
+}
+__attribute__((section(".convcode")))
+Sample *SampleBuffer::middata() {
+ return m_buffer + m_size / 2;
+}
+uint8_t *SampleBuffer::bytedata() {
+ return reinterpret_cast<uint8_t *>(m_buffer);
+}
+
+Sample *SampleBuffer::modified() {
+ auto m = m_modified;
+ m_modified = nullptr;
+ return m;
+}
+__attribute__((section(".convcode")))
+unsigned int SampleBuffer::size() const {
+ return m_size;
+}
+unsigned int SampleBuffer::bytesize() const {
+ return m_size * sizeof(Sample);
+}
+
--- /dev/null
+#ifndef SAMPLEBUFFER_HPP_
+#define SAMPLEBUFFER_HPP_
+
+#include <array>
+#include <cstdint>
+
+using Sample = uint16_t;
+
+// gives 8000
+constexpr unsigned int MAX_SAMPLE_BUFFER_BYTESIZE = 16384;
+constexpr unsigned int MAX_SAMPLE_BUFFER_SIZE = MAX_SAMPLE_BUFFER_BYTESIZE / sizeof(Sample);
+
+class SampleBuffer
+{
+public:
+ SampleBuffer(Sample *buffer);
+
+ void clear();
+
+ void modify(Sample *data, unsigned int srcsize);
+ void midmodify(Sample *data, unsigned int srcsize);
+ Sample *modified();
+
+ Sample *data();
+ Sample *middata();
+ uint8_t *bytedata();
+
+ void setSize(unsigned int size);
+ unsigned int size() const;
+ unsigned int bytesize() const;
+
+private:
+ Sample *m_buffer = nullptr;
+ unsigned int m_size = MAX_SAMPLE_BUFFER_SIZE;
+ Sample *m_modified = nullptr;
+};
+
+#endif // SAMPLEBUFFER_HPP_
+