sandboxed user algorithm

pull/3/head
Clyne 4 years ago
parent 1a14ef827e
commit 4f59610a00

@ -148,7 +148,9 @@ CPPWARN = -Wall -Wextra -Wundef
# #
# List all user C define here, like -D_DEBUG=1 # 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 # Define ASM defines here
UADEFS = UADEFS =

@ -15,19 +15,18 @@
*/ */
/* /*
* STM32H743xI generic setup.
*
* AXI SRAM - BSS, Data, Heap. * AXI SRAM - BSS, Data, Heap.
* SRAM1 - SIGGEN. * SRAM1 - SIGGEN.
* SRAM2 - DAC. * SRAM2 - DAC.
* SRAM4 - ADC. * SRAM4 - ADC.
* DTCM-RAM - Main Stack, Process Stack. * DTCM-RAM - Unprivileged Stack, Main Stack, Process Stack.
* ITCM-RAM - STMDSP Algorithm. * ITCM-RAM - STMDSP Algorithm.
* BCKP SRAM - None. * BCKP SRAM - None.
*/ */
MEMORY MEMORY
{ {
flash0 (rx) : org = 0x08000000, len = 1M /* Flash bank1+bank2 */ flash0 (rx) : org = 0x08000000, len = 1M /* Flash bank1 + bank2 */
flashc (rx) : org = 0x0807F000, len = 4K /* Unprivileged firmware */
flash1 (rx) : org = 0x08000000, len = 512K /* Flash bank 1 */ flash1 (rx) : org = 0x08000000, len = 512K /* Flash bank 1 */
flash2 (rx) : org = 0x08080000, len = 512K /* Flash bank 2 */ flash2 (rx) : org = 0x08080000, len = 512K /* Flash bank 2 */
flash3 (rx) : org = 0x00000000, len = 0 flash3 (rx) : org = 0x00000000, len = 0
@ -35,14 +34,15 @@ MEMORY
flash5 (rx) : org = 0x00000000, len = 0 flash5 (rx) : org = 0x00000000, len = 0
flash6 (rx) : org = 0x00000000, len = 0 flash6 (rx) : org = 0x00000000, len = 0
flash7 (rx) : org = 0x00000000, len = 0 flash7 (rx) : org = 0x00000000, len = 0
ram0 (wx) : org = 0x24000000, len = 320k /* AXI SRAM */ ram0 (wx) : org = 0x24000000, len = 320K /* AXI SRAM */
ram1 (wx) : org = 0x30000000, len = 16k /* AHB SRAM1 */ ram1 (wx) : org = 0x30000000, len = 16K /* AHB SRAM1 */
ram2 (wx) : org = 0x30004000, len = 16k /* AHB SRAM2 */ ram2 (wx) : org = 0x30004000, len = 16K /* AHB SRAM2 */
ram3 (wx) : org = 0x38000000, len = 16k /* AHB SRAM4 */ ram3 (wx) : org = 0x38000000, len = 16K /* AHB SRAM4 */
ram4 (wx) : org = 0x00000000, len = 0 ram4 (wx) : org = 0x00000000, len = 0
ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */ ramc (wx) : org = 0x20000000, len = 4K /* Unprivileged data */
ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */ ram5 (wx) : org = 0x20001000, len = 124K /* DTCM-RAM */
ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */ ram6 (wx) : org = 0x00000000, len = 64K /* ITCM-RAM */
ram7 (wx) : org = 0x38800000, len = 4K /* BCKP SRAM */
} }
/* For each data/text section two region are defined, a virtual region /* For each data/text section two region are defined, a virtual region
@ -92,40 +92,19 @@ REGION_ALIAS("HEAP_RAM", ram0);
/* Stack rules inclusion.*/ /* Stack rules inclusion.*/
INCLUDE rules_stacks.ld INCLUDE rules_stacks.ld
/*===========================================================================*/
/* Custom sections for STM32H7xx. */
/* SRAM3 is assumed to be marked non-cacheable using MPU. */
/*===========================================================================*/
/* RAM region to be used for nocache segment.*/
/*REGION_ALIAS("NOCACHE_RAM", ram3);*/
/* RAM region to be used for eth segment.*/
/*REGION_ALIAS("ETH_RAM", ram3);*/
SECTIONS SECTIONS
{ {
/* Special section for non cache-able areas.*/ .convdata : ALIGN(4)
/*.nocache (NOLOAD) : ALIGN(4)
{ {
__nocache_base__ = .; *(.convdata)
*(.nocache)
*(.nocache.*)
*(.bss.__nocache_*)
. = ALIGN(4); . = ALIGN(4);
__nocache_end__ = .; } > ramc
} > NOCACHE_RAM*/
/* Special section for Ethernet DMA non cache-able areas.*/ .convcode : ALIGN(4)
/*.eth (NOLOAD) : ALIGN(4)
{ {
__eth_base__ = .; *(.convcode)
*(.eth)
*(.eth.*)
*(.bss.__eth_*)
. = ALIGN(4); . = ALIGN(4);
__eth_end__ = .; } > flashc
} > ETH_RAM*/
} }
/* Code rules inclusion.*/ /* Code rules inclusion.*/

@ -44,7 +44,7 @@
/* /*
* Memory attributes settings. * Memory attributes settings.
*/ */
#define STM32_NOCACHE_MPU_REGION MPU_REGION_6 #define STM32_NOCACHE_MPU_REGION MPU_REGION_1
#define STM32_NOCACHE_SRAM1_SRAM2 FALSE #define STM32_NOCACHE_SRAM1_SRAM2 FALSE
#define STM32_NOCACHE_SRAM3 FALSE #define STM32_NOCACHE_SRAM3 FALSE
#define STM32_NOCACHE_ALLSRAM TRUE #define STM32_NOCACHE_ALLSRAM TRUE

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

@ -15,13 +15,12 @@
static_assert(sizeof(adcsample_t) == sizeof(uint16_t)); static_assert(sizeof(adcsample_t) == sizeof(uint16_t));
static_assert(sizeof(dacsample_t) == sizeof(uint16_t)); static_assert(sizeof(dacsample_t) == sizeof(uint16_t));
#include "common.hpp"
#include "error.hpp"
#include "adc.hpp" #include "adc.hpp"
#include "cordic.hpp" #include "cordic.hpp"
#include "dac.hpp" #include "dac.hpp"
#include "elf_load.hpp" #include "elf_load.hpp"
#include "error.hpp"
#include "samplebuffer.hpp"
#include "sclock.hpp" #include "sclock.hpp"
#include "usbserial.hpp" #include "usbserial.hpp"
@ -45,30 +44,44 @@ static RunStatus run_status = RunStatus::Idle;
#define MSG_FOR_FIRST(m) (m & 1) #define MSG_FOR_FIRST(m) (m & 1)
#define MSG_FOR_MEASURE(m) (m > 2) #define MSG_FOR_MEASURE(m) (m > 2)
static msg_t conversionMBBuffer[4]; static ErrorManager EM;
static MAILBOX_DECL(conversionMB, conversionMBBuffer, 4);
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); static THD_FUNCTION(conversionThread, arg);
__attribute__((section(".convdata")))
static THD_WORKING_AREA(conversionThreadUPWA, 256);
static time_measurement_t conversion_time_measurement; static thread_t *conversionThreadHandle = nullptr;
__attribute__((section(".convdata")))
static ErrorManager EM; 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 static SampleBuffer samplesIn (reinterpret_cast<Sample *>(0x38000000)); // 16k
__attribute__((section(".convdata")))
static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x30004000)); // 16k static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x30004000)); // 16k
static SampleBuffer samplesSigGen (reinterpret_cast<Sample *>(0x30000000)); // 16k static SampleBuffer samplesSigGen (reinterpret_cast<Sample *>(0x30000000)); // 16k
static unsigned char elf_file_store[MAX_ELF_FILE_SIZE]; static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
__attribute__((section(".convdata")))
static ELF::Entry elf_entry = nullptr; static ELF::Entry elf_entry = nullptr;
static void signal_operate(adcsample_t *buffer, size_t count); static void signal_operate(adcsample_t *buffer, size_t count);
static void signal_operate_measure(adcsample_t *buffer, size_t count); static void signal_operate_measure(adcsample_t *buffer, size_t count);
static void main_loop(); static void main_loop();
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg);
int main() int main()
{ {
// Initialize the RTOS // Initialize the RTOS
@ -80,6 +93,26 @@ int main()
// Enable FPU // Enable FPU
SCB->CPACR |= 0xF << 20; 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(); ADC::begin();
DAC::begin(); DAC::begin();
SClock::begin(); SClock::begin();
@ -90,9 +123,14 @@ int main()
ADC::setRate(SClock::Rate::R32K); ADC::setRate(SClock::Rate::R32K);
chTMObjectInit(&conversion_time_measurement); chTMObjectInit(&conversion_time_measurement);
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, nullptr); chThdCreateStatic(monitorThreadWA, sizeof(monitorThreadWA),
chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA), NORMALPRIO, monitorThread, nullptr);
NORMALPRIO, conversionThread, nullptr); conversionThreadMonitorHandle = chThdCreateStatic(
conversionThreadMonitorWA, sizeof(conversionThreadMonitorWA),
NORMALPRIO, conversionThreadMonitor, nullptr);
conversionThreadHandle = chThdCreateStatic(
conversionThreadWA, sizeof(conversionThreadWA),
NORMALPRIO + 1, conversionThread, nullptr);
main_loop(); main_loop();
} }
@ -278,35 +316,47 @@ void conversion_abort()
run_status = RunStatus::Idle; run_status = RunStatus::Idle;
} }
THD_FUNCTION(conversionThread, arg) THD_FUNCTION(conversionThreadMonitor, arg)
{ {
(void)arg; (void)arg;
while (1) { while (1) {
// Recover from algorithm fault if necessary // Recover from algorithm fault if necessary
if (run_status == RunStatus::Recovering) //if (run_status == RunStatus::Recovering)
conversion_abort(); // 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; msg_t message;
if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) { asm("svc 0; mov %0, r0" : "=r" (message));
static Sample *samples = nullptr; if (message != 0) {
static unsigned int size = 0; auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata();
samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata(); auto size = samplesIn.size() / 2;
size = samplesIn.size() / 2;
if (elf_entry) { if (elf_entry) {
if (!MSG_FOR_MEASURE(message)) { if (!MSG_FOR_MEASURE(message)) {
//asm("cpsid i"); samples = elf_entry(samples, size);
//mpuDisable();
//port_unprivileged_jump((uint32_t)+[] {
samples = elf_entry(samples, size);
//}, 0xF800);
//mpuEnable(MPU_CTRL_PRIVDEFENA);
//asm("cpsie i");
} else { } else {
chTMStartMeasurementX(&conversion_time_measurement); //chTMStartMeasurementX(&conversion_time_measurement);
samples = elf_entry(samples, size); 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); ADC::setOperation(signal_operate);
} }
THD_FUNCTION(Thread1, arg) THD_FUNCTION(monitorThread, arg)
{ {
(void)arg; (void)arg;
@ -379,6 +429,29 @@ THD_FUNCTION(Thread1, arg)
extern "C" { 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)) __attribute__((naked))
void HardFault_Handler() void HardFault_Handler()
{ {

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

@ -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_
Loading…
Cancel
Save