sandboxed user algorithm
This commit is contained in:
parent
1a14ef827e
commit
4f59610a00
4
Makefile
4
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 =
|
||||
|
@ -15,19 +15,18 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* STM32H743xI generic setup.
|
||||
*
|
||||
* AXI SRAM - BSS, Data, Heap.
|
||||
* SRAM1 - SIGGEN.
|
||||
* SRAM2 - DAC.
|
||||
* SRAM4 - ADC.
|
||||
* DTCM-RAM - Main Stack, Process Stack.
|
||||
* DTCM-RAM - Unprivileged Stack, Main Stack, Process Stack.
|
||||
* ITCM-RAM - STMDSP Algorithm.
|
||||
* BCKP SRAM - None.
|
||||
*/
|
||||
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 */
|
||||
flash2 (rx) : org = 0x08080000, len = 512K /* Flash bank 2 */
|
||||
flash3 (rx) : org = 0x00000000, len = 0
|
||||
@ -35,14 +34,15 @@ MEMORY
|
||||
flash5 (rx) : org = 0x00000000, len = 0
|
||||
flash6 (rx) : org = 0x00000000, len = 0
|
||||
flash7 (rx) : org = 0x00000000, len = 0
|
||||
ram0 (wx) : org = 0x24000000, len = 320k /* AXI SRAM */
|
||||
ram1 (wx) : org = 0x30000000, len = 16k /* AHB SRAM1 */
|
||||
ram2 (wx) : org = 0x30004000, len = 16k /* AHB SRAM2 */
|
||||
ram3 (wx) : org = 0x38000000, len = 16k /* AHB SRAM4 */
|
||||
ram0 (wx) : org = 0x24000000, len = 320K /* AXI SRAM */
|
||||
ram1 (wx) : org = 0x30000000, len = 16K /* AHB SRAM1 */
|
||||
ram2 (wx) : org = 0x30004000, len = 16K /* AHB SRAM2 */
|
||||
ram3 (wx) : org = 0x38000000, len = 16K /* AHB SRAM4 */
|
||||
ram4 (wx) : org = 0x00000000, len = 0
|
||||
ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
|
||||
ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */
|
||||
ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */
|
||||
ramc (wx) : org = 0x20000000, len = 4K /* Unprivileged data */
|
||||
ram5 (wx) : org = 0x20001000, len = 124K /* DTCM-RAM */
|
||||
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
|
||||
@ -92,40 +92,19 @@ REGION_ALIAS("HEAP_RAM", ram0);
|
||||
/* Stack rules inclusion.*/
|
||||
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
|
||||
{
|
||||
/* Special section for non cache-able areas.*/
|
||||
/*.nocache (NOLOAD) : ALIGN(4)
|
||||
.convdata : ALIGN(4)
|
||||
{
|
||||
__nocache_base__ = .;
|
||||
*(.nocache)
|
||||
*(.nocache.*)
|
||||
*(.bss.__nocache_*)
|
||||
*(.convdata)
|
||||
. = ALIGN(4);
|
||||
__nocache_end__ = .;
|
||||
} > NOCACHE_RAM*/
|
||||
} > ramc
|
||||
|
||||
/* Special section for Ethernet DMA non cache-able areas.*/
|
||||
/*.eth (NOLOAD) : ALIGN(4)
|
||||
.convcode : ALIGN(4)
|
||||
{
|
||||
__eth_base__ = .;
|
||||
*(.eth)
|
||||
*(.eth.*)
|
||||
*(.bss.__eth_*)
|
||||
*(.convcode)
|
||||
. = ALIGN(4);
|
||||
__eth_end__ = .;
|
||||
} > ETH_RAM*/
|
||||
} > flashc
|
||||
}
|
||||
|
||||
/* Code rules inclusion.*/
|
||||
|
@ -44,7 +44,7 @@
|
||||
/*
|
||||
* 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_SRAM3 FALSE
|
||||
#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;
|
||||
};
|
||||
|
147
source/main.cpp
147
source/main.cpp
@ -15,13 +15,12 @@
|
||||
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 THD_WORKING_AREA(conversionThreadWA, 2048);
|
||||
static THD_FUNCTION(conversionThread, arg);
|
||||
|
||||
static time_measurement_t conversion_time_measurement;
|
||||
|
||||
static ErrorManager EM;
|
||||
|
||||
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 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(conversionThreadMonitor, arg)
|
||||
{
|
||||
(void)arg;
|
||||
while (1) {
|
||||
// Recover from algorithm fault if necessary
|
||||
//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) {
|
||||
// Recover from algorithm fault if necessary
|
||||
if (run_status == RunStatus::Recovering)
|
||||
conversion_abort();
|
||||
|
||||
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");
|
||||
} else {
|
||||
chTMStartMeasurementX(&conversion_time_measurement);
|
||||
samples = elf_entry(samples, size);
|
||||
chTMStopMeasurementX(&conversion_time_measurement);
|
||||
} else {
|
||||
//chTMStartMeasurementX(&conversion_time_measurement);
|
||||
samples = elf_entry(samples, size);
|
||||
//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()
|
||||
{
|
||||
|
52
source/samplebuffer.cpp
Normal file
52
source/samplebuffer.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
39
source/samplebuffer.hpp
Normal file
39
source/samplebuffer.hpp
Normal file
@ -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…
x
Reference in New Issue
Block a user