]> code.bitgloo.com Git - clyne/stmdsp.git/commitdiff
sandboxed user algorithm
authorClyne Sullivan <clyne@bitgloo.com>
Wed, 27 Jan 2021 16:18:33 +0000 (11:18 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Wed, 27 Jan 2021 16:18:33 +0000 (11:18 -0500)
Makefile
STM32H723xG.ld
cfg/mcuconf.h
source/common.hpp [deleted file]
source/main.cpp
source/samplebuffer.cpp [new file with mode: 0644]
source/samplebuffer.hpp [new file with mode: 0644]

index efb47ad4459ebe77cd732d3955a5a8747482f588..178b026c95a95a4f8d2ec3b7c5f8ea43a756a19e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -148,7 +148,9 @@ CPPWARN = -Wall -Wextra -Wundef
 #
 
 # 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 =
index eb3d63b7035f709badebb924bcf64ce98d4a0640..e59c9001e65b85b4ea7e458dc44aad64d80b2734 100644 (file)
 */\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
@@ -35,14 +34,15 @@ MEMORY
     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
@@ -92,40 +92,19 @@ REGION_ALIAS("HEAP_RAM", ram0);
 /* 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
index 27a2939c2e7ef4f66bad495dd3696b14a19c9980..1fb3655a23da31b129ca158650adf8802f244602 100644 (file)
@@ -44,7 +44,7 @@
 /*\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
diff --git a/source/common.hpp b/source/common.hpp
deleted file mode 100644 (file)
index 876cf74..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#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;
-};
-
index 97612f43c6a2ab6034233a45b64bfb606d6816c6..1a89c935805ee1ed6439eea01b5c69b9fe102972 100644 (file)
 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"
 
@@ -45,30 +44,44 @@ static RunStatus run_status = RunStatus::Idle;
 #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
@@ -80,6 +93,26 @@ int main()
     // 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();
@@ -90,9 +123,14 @@ int main()
     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();
 }
@@ -278,35 +316,47 @@ void conversion_abort()
     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);
                 } 
             }
 
@@ -340,7 +390,7 @@ void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count)
     ADC::setOperation(signal_operate);
 }
 
-THD_FUNCTION(Thread1, arg)
+THD_FUNCTION(monitorThread, arg)
 {
     (void)arg;
 
@@ -379,6 +429,29 @@ THD_FUNCTION(Thread1, 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()
 {
diff --git a/source/samplebuffer.cpp b/source/samplebuffer.cpp
new file mode 100644 (file)
index 0000000..6932392
--- /dev/null
@@ -0,0 +1,52 @@
+#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);
+}
+
diff --git a/source/samplebuffer.hpp b/source/samplebuffer.hpp
new file mode 100644 (file)
index 0000000..9aabfdd
--- /dev/null
@@ -0,0 +1,39 @@
+#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_
+