increase signal buffers; fix oversample

pull/3/head
Clyne 4 years ago
parent 716be4fc87
commit ec2e1fd5c6

@ -168,11 +168,14 @@ void hal_lld_init(void) {
/* MPU initialization.*/ /* MPU initialization.*/
#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) || (STM32_NOCACHE_SRAM3 == TRUE) || \ #if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) || (STM32_NOCACHE_SRAM3 == TRUE) || \
(STM32_NOCACHE_SRAM4 == TRUE) (STM32_NOCACHE_ALLSRAM == TRUE)
{ {
uint32_t base, size; uint32_t base, size;
#if (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == TRUE) #if (STM32_NOCACHE_ALLSRAM == TRUE)
base = 0x30000000U;
size = MPU_RASR_SIZE_256M;
#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == TRUE)
base = 0x30000000U; base = 0x30000000U;
size = MPU_RASR_SIZE_512K; size = MPU_RASR_SIZE_512K;
#elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == FALSE) #elif (STM32_NOCACHE_SRAM1_SRAM2 == TRUE) && (STM32_NOCACHE_SRAM3 == FALSE)
@ -181,9 +184,6 @@ void hal_lld_init(void) {
#elif (STM32_NOCACHE_SRAM1_SRAM2 == FALSE) && (STM32_NOCACHE_SRAM3 == TRUE) #elif (STM32_NOCACHE_SRAM1_SRAM2 == FALSE) && (STM32_NOCACHE_SRAM3 == TRUE)
base = 0x30040000U; base = 0x30040000U;
size = MPU_RASR_SIZE_16K; size = MPU_RASR_SIZE_16K;
#elif (STM32_NOCACHE_SRAM4 == TRUE)
base = 0x38000000U;
size = MPU_RASR_SIZE_16K;
#else #else
#error "invalid constants used in mcuconf.h" #error "invalid constants used in mcuconf.h"
#endif #endif

@ -148,7 +148,7 @@ 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 = #-DSTM32_ENFORCE_H7_REV_V # Must be removed for non-Rev-V devices. UDEFS = -DCORTEX_ENABLE_WFI_IDLE=FALSE
# Define ASM defines here # Define ASM defines here
UADEFS = UADEFS =

@ -18,30 +18,31 @@
* STM32H743xI generic setup. * STM32H743xI generic setup.
* *
* AXI SRAM - BSS, Data, Heap. * AXI SRAM - BSS, Data, Heap.
* SRAM1+SRAM2 - None. * SRAM1 - SIGGEN.
* SRAM4 - NOCACHE. * SRAM2 - DAC.
* SRAM4 - ADC.
* DTCM-RAM - Main Stack, Process Stack. * DTCM-RAM - 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 */
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
flash4 (rx) : org = 0x00000000, len = 0 flash4 (rx) : org = 0x00000000, len = 0
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 = 32k /* AHB SRAM1+SRAM2 */ 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 */ ram5 (wx) : org = 0x20000000, len = 128k /* DTCM-RAM */
ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */ ram6 (wx) : org = 0x00000000, len = 64k /* ITCM-RAM */
ram7 (wx) : org = 0x38800000, len = 4k /* BCKP SRAM */ 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
@ -97,7 +98,7 @@ INCLUDE rules_stacks.ld
/*===========================================================================*/ /*===========================================================================*/
/* RAM region to be used for nocache segment.*/ /* RAM region to be used for nocache segment.*/
REGION_ALIAS("NOCACHE_RAM", ram3); /*REGION_ALIAS("NOCACHE_RAM", ram3);*/
/* RAM region to be used for eth segment.*/ /* RAM region to be used for eth segment.*/
/*REGION_ALIAS("ETH_RAM", ram3);*/ /*REGION_ALIAS("ETH_RAM", ram3);*/
@ -105,7 +106,7 @@ REGION_ALIAS("NOCACHE_RAM", ram3);
SECTIONS SECTIONS
{ {
/* Special section for non cache-able areas.*/ /* Special section for non cache-able areas.*/
.nocache (NOLOAD) : ALIGN(4) /*.nocache (NOLOAD) : ALIGN(4)
{ {
__nocache_base__ = .; __nocache_base__ = .;
*(.nocache) *(.nocache)
@ -113,7 +114,7 @@ SECTIONS
*(.bss.__nocache_*) *(.bss.__nocache_*)
. = ALIGN(4); . = ALIGN(4);
__nocache_end__ = .; __nocache_end__ = .;
} > NOCACHE_RAM } > NOCACHE_RAM*/
/* Special section for Ethernet DMA non cache-able areas.*/ /* Special section for Ethernet DMA non cache-able areas.*/
/*.eth (NOLOAD) : ALIGN(4) /*.eth (NOLOAD) : ALIGN(4)

@ -230,7 +230,7 @@
* @note Disabling this option saves both code and data space. * @note Disabling this option saves both code and data space.
*/ */
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE #define ADC_USE_WAIT FALSE
#endif #endif
/** /**
@ -238,7 +238,7 @@
* @note Disabling this option saves both code and data space. * @note Disabling this option saves both code and data space.
*/ */
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE #define ADC_USE_MUTUAL_EXCLUSION FALSE
#endif #endif
/*===========================================================================*/ /*===========================================================================*/
@ -290,7 +290,7 @@
* @note Disabling this option saves both code and data space. * @note Disabling this option saves both code and data space.
*/ */
#if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__) #if !defined(DAC_USE_WAIT) || defined(__DOXYGEN__)
#define DAC_USE_WAIT TRUE #define DAC_USE_WAIT FALSE
#endif #endif
/** /**
@ -298,7 +298,7 @@
* @note Disabling this option saves both code and data space. * @note Disabling this option saves both code and data space.
*/ */
#if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) #if !defined(DAC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define DAC_USE_MUTUAL_EXCLUSION TRUE #define DAC_USE_MUTUAL_EXCLUSION FALSE
#endif #endif
/*===========================================================================*/ /*===========================================================================*/

@ -46,8 +46,8 @@
*/ */
#define STM32_NOCACHE_MPU_REGION MPU_REGION_6 #define STM32_NOCACHE_MPU_REGION MPU_REGION_6
#define STM32_NOCACHE_SRAM1_SRAM2 FALSE #define STM32_NOCACHE_SRAM1_SRAM2 FALSE
#define STM32_NOCACHE_SRAM3 FALSE // keep #define STM32_NOCACHE_SRAM3 FALSE
#define STM32_NOCACHE_SRAM4 TRUE #define STM32_NOCACHE_ALLSRAM TRUE
/* /*
* PWR system settings. * PWR system settings.

@ -19,7 +19,7 @@
namespace stmdsp namespace stmdsp
{ {
constexpr unsigned int SAMPLES_MAX = 3000; constexpr unsigned int SAMPLES_MAX = 4000;
class scanner class scanner
{ {

@ -47,7 +47,7 @@ static const std::array<unsigned int, 6> srateNums {
static const char *makefile_text = R"make( static const char *makefile_text = R"make(
all: all:
@arm-none-eabi-g++ -x c++ -Os -fno-exceptions -fno-rtti \ @arm-none-eabi-g++ -x c++ -Os -fno-exceptions -fno-rtti \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mtune=cortex-m4 \ -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16 -mtune=cortex-m7 \
-nostartfiles \ -nostartfiles \
-Wl,-Ttext-segment=0x00000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry \ -Wl,-Ttext-segment=0x00000000 -Wl,-zmax-page-size=512 -Wl,-eprocess_data_entry \
$0 -o $0.o $0 -o $0.o

@ -24,7 +24,7 @@ ADCConversionGroup ADC::m_group_config = {
.end_cb = ADC::conversionCallback, .end_cb = ADC::conversionCallback,
.error_cb = nullptr, .error_cb = nullptr,
.cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */ .cfgr = ADC_CFGR_EXTEN_RISING | ADC_CFGR_EXTSEL_SRC(13), /* TIM6_TRGO */
.cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSS_1, // Oversampling 2x .cfgr2 = ADC_CFGR2_ROVSE | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSS_0, // Oversampling 2x
.ccr = 0, .ccr = 0,
.pcsel = 0, .pcsel = 0,
.ltr1 = 0, .htr1 = 0x0FFF, .ltr1 = 0, .htr1 = 0x0FFF,

@ -1,12 +1,12 @@
#include <array> #include <array>
#include <cstdint> #include <cstdint>
//#define ENABLE_SIGGEN
constexpr unsigned int MAX_SAMPLE_BUFFER_SIZE = 4000;
using Sample = uint16_t; 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 class SampleBuffer
{ {
public: public:
@ -14,12 +14,6 @@ public:
m_buffer(buffer) {} m_buffer(buffer) {}
void clear() { void clear() {
/*static const Sample ref[21] = {
100, 200, 400, 600, 800, 1000, 1200, 1400, 1600, 1800,
2000, 2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600, 3800, 4095
};
for (unsigned int i = 0; i < m_size; i++)
m_buffer[i] = ref[i % 21];*/
std::fill(m_buffer, m_buffer + m_size, 2048); std::fill(m_buffer, m_buffer + m_size, 2048);
} }
void modify(Sample *data, unsigned int srcsize) { void modify(Sample *data, unsigned int srcsize) {
@ -60,7 +54,6 @@ public:
} }
private: private:
//std::array<Sample, MAX_SAMPLE_BUFFER_SIZE> m_buffer;
Sample *m_buffer = nullptr; Sample *m_buffer = nullptr;
unsigned int m_size = MAX_SAMPLE_BUFFER_SIZE; unsigned int m_size = MAX_SAMPLE_BUFFER_SIZE;
Sample *m_modified = nullptr; Sample *m_modified = nullptr;

@ -27,6 +27,10 @@ public:
return condition; return condition;
} }
bool hasError() {
return m_index > 0;
}
Error pop() { Error pop() {
return m_index == 0 ? Error::None : m_queue[--m_index]; return m_index == 0 ? Error::None : m_queue[--m_index];
} }

@ -1,387 +1,383 @@
/** /**
* @file main.cpp * @file main.cpp
* @brief Program entry point. * @brief Program entry point.
* *
* Copyright (C) 2020 Clyne Sullivan * Copyright (C) 2020 Clyne Sullivan
* *
* Distributed under the GNU GPL v3 or later. You should have received a copy of * Distributed under the GNU GPL v3 or later. You should have received a copy of
* the GNU General Public License along with this program. * the GNU General Public License along with this program.
* If not, see <https://www.gnu.org/licenses/>. * If not, see <https://www.gnu.org/licenses/>.
*/ */
#include "ch.h" #include "ch.h"
#include "hal.h" #include "hal.h"
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 "common.hpp"
#include "error.hpp" #include "error.hpp"
#include "adc.hpp" #include "adc.hpp"
#include "dac.hpp" #include "dac.hpp"
#include "elf_load.hpp" #include "elf_load.hpp"
#include "sclock.hpp" #include "sclock.hpp"
#include "usbserial.hpp" #include "usbserial.hpp"
#include <array> #include <array>
constexpr unsigned int MAX_ELF_FILE_SIZE = 8 * 1024; constexpr unsigned int MAX_ELF_FILE_SIZE = 8 * 1024;
enum class RunStatus : char enum class RunStatus : char
{ {
Idle = '1', Idle = '1',
Running Running
}; };
static RunStatus run_status = RunStatus::Idle; static RunStatus run_status = RunStatus::Idle;
#define MSG_CONVFIRST (1) #define MSG_CONVFIRST (1)
#define MSG_CONVSECOND (2) #define MSG_CONVSECOND (2)
#define MSG_CONVFIRST_MEASURE (3) #define MSG_CONVFIRST_MEASURE (3)
#define MSG_CONVSECOND_MEASURE (4) #define MSG_CONVSECOND_MEASURE (4)
#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 msg_t conversionMBBuffer[4];
static MAILBOX_DECL(conversionMB, conversionMBBuffer, 4); static MAILBOX_DECL(conversionMB, conversionMBBuffer, 4);
static THD_WORKING_AREA(conversionThreadWA, 2048); static THD_WORKING_AREA(conversionThreadWA, 2048);
static THD_FUNCTION(conversionThread, arg); static THD_FUNCTION(conversionThread, arg);
static time_measurement_t conversion_time_measurement; static time_measurement_t conversion_time_measurement;
static ErrorManager EM; static ErrorManager EM;
static SampleBuffer samplesIn (reinterpret_cast<Sample *>(0x38000000)); static SampleBuffer samplesIn (reinterpret_cast<Sample *>(0x38000000)); // 16k
static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x38002000)); static SampleBuffer samplesOut (reinterpret_cast<Sample *>(0x30004000)); // 16k
#ifdef ENABLE_SIGGEN static SampleBuffer samplesSigGen (reinterpret_cast<Sample *>(0x30000000)); // 16k
static SampleBuffer samplesSigGen;
#endif static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
static ELF::Entry elf_entry = nullptr;
static unsigned char elf_file_store[MAX_ELF_FILE_SIZE];
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 signal_operate(adcsample_t *buffer, size_t count); static void main_loop();
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);
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg); int main()
{
int main() // Initialize the RTOS
{ halInit();
// Initialize the RTOS chSysInit();
halInit();
chSysInit(); // Enable FPU
SCB->CPACR |= 0xF << 20;
//SCB_DisableDCache();
ADC::begin();
// Enable FPU DAC::begin();
SCB->CPACR |= 0xF << 20; SClock::begin();
USBSerial::begin();
ADC::begin();
DAC::begin(); SClock::setRate(SClock::Rate::R32K);
SClock::begin(); ADC::setRate(SClock::Rate::R32K);
USBSerial::begin();
chTMObjectInit(&conversion_time_measurement);
SClock::setRate(SClock::Rate::R32K); chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, nullptr);
ADC::setRate(SClock::Rate::R32K); chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA),
NORMALPRIO, conversionThread, nullptr);
// Start the conversion manager thread
chTMObjectInit(&conversion_time_measurement); main_loop();
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, }
nullptr);
chThdCreateStatic(conversionThreadWA, sizeof(conversionThreadWA), void main_loop()
NORMALPRIO, conversionThread, nullptr); {
main_loop(); while (1) {
} if (USBSerial::isActive()) {
// Attempt to receive a command packet
void main_loop() if (unsigned char cmd[3]; USBSerial::read(&cmd[0], 1) > 0) {
{ // Packet received, first byte represents the desired command/action
switch (cmd[0]) {
while (1) {
if (USBSerial::isActive()) { case 'a':
// Attempt to receive a command packet USBSerial::write(samplesIn.bytedata(), samplesIn.bytesize());
if (unsigned char cmd[3]; USBSerial::read(&cmd[0], 1) > 0) { break;
// Packet received, first byte represents the desired command/action case 'A':
switch (cmd[0]) { USBSerial::read(samplesIn.bytedata(), samplesIn.bytesize());
break;
case 'a':
USBSerial::write(samplesIn.bytedata(), samplesIn.bytesize()); case 'B':
break; if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) &&
case 'A': EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize))
USBSerial::read(samplesIn.bytedata(), samplesIn.bytesize()); {
break; unsigned int count = (cmd[1] | (cmd[2] << 8)) * 2;
if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) {
case 'B': samplesIn.setSize(count);
if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) && samplesOut.setSize(count);
EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) }
{ }
unsigned int count = (cmd[1] | (cmd[2] << 8)) * 2; break;
if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) {
samplesIn.setSize(count); case 'd':
samplesOut.setSize(count); USBSerial::write(samplesOut.bytedata(), samplesOut.bytesize());
} break;
} case 'D':
break; if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) {
unsigned int count = cmd[1] | (cmd[2] << 8);
case 'd': if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) {
USBSerial::write(samplesOut.bytedata(), samplesOut.bytesize()); samplesSigGen.setSize(count);
break; USBSerial::read(samplesSigGen.bytedata(), samplesSigGen.bytesize());
#ifdef ENABLE_SIGGEN }
case 'D': }
if (EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) { break;
unsigned int count = cmd[1] | (cmd[2] << 8);
if (EM.assert(count <= MAX_SAMPLE_BUFFER_SIZE, Error::BadParam)) { // 'E' - Reads in and loads the compiled conversion code binary from USB.
samplesSigGen.setSize(count); case 'E':
USBSerial::read(samplesSigGen.bytedata(), samplesSigGen.bytesize()); if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) &&
} EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize))
} {
break; // Only load the binary if it can fit in the memory reserved for it.
#endif unsigned int size = cmd[1] | (cmd[2] << 8);
if (EM.assert(size < sizeof(elf_file_store), Error::BadUserCodeSize)) {
// 'E' - Reads in and loads the compiled conversion code binary from USB. USBSerial::read(elf_file_store, size);
case 'E': elf_entry = ELF::load(elf_file_store);
if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle) &&
EM.assert(USBSerial::read(&cmd[1], 2) == 2, Error::BadParamSize)) EM.assert(elf_entry != nullptr, Error::BadUserCodeLoad);
{ }
// Only load the binary if it can fit in the memory reserved for it. }
unsigned int size = cmd[1] | (cmd[2] << 8); break;
if (EM.assert(size < sizeof(elf_file_store), Error::BadUserCodeSize)) {
USBSerial::read(elf_file_store, size); // 'e' - Unloads the currently loaded conversion code
elf_entry = ELF::load(elf_file_store); case 'e':
elf_entry = nullptr;
EM.assert(elf_entry != nullptr, Error::BadUserCodeLoad); break;
}
} // 'i' - Sends an identifying string to confirm that this is the stmdsp device.
break; case 'i':
USBSerial::write(reinterpret_cast<const uint8_t *>("stmdsp"), 6);
// 'e' - Unloads the currently loaded conversion code break;
case 'e':
elf_entry = nullptr; // 'I' - Sends the current run status.
break; case 'I':
{
// 'i' - Sends an identifying string to confirm that this is the stmdsp device. unsigned char buf[2] = {
case 'i': static_cast<unsigned char>(run_status),
USBSerial::write(reinterpret_cast<const uint8_t *>("stmdsp"), 6); static_cast<unsigned char>(EM.pop())
break; };
USBSerial::write(buf, sizeof(buf));
// 'I' - Sends the current run status. }
case 'I': break;
{
unsigned char buf[2] = { // 'M' - Begins continuous sampling, but measures the execution time of the first
static_cast<unsigned char>(run_status), // sample processing. This duration can be later read through 'm'.
static_cast<unsigned char>(EM.pop()) case 'M':
}; if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) {
USBSerial::write(buf, sizeof(buf)); run_status = RunStatus::Running;
} samplesOut.clear();
break; ADC::start(samplesIn.data(), samplesIn.size(), signal_operate_measure);
DAC::start(0, samplesOut.data(), samplesOut.size());
// 'M' - Begins continuous sampling, but measures the execution time of the first }
// sample processing. This duration can be later read through 'm'. break;
case 'M':
if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { // 'm' - Returns the last measured sample processing time, presumably in processor
run_status = RunStatus::Running; // ticks.
samplesOut.clear(); case 'm':
ADC::start(samplesIn.data(), samplesIn.size(), signal_operate_measure); USBSerial::write(reinterpret_cast<uint8_t *>(&conversion_time_measurement.last),
DAC::start(0, samplesOut.data(), samplesOut.size()); sizeof(rtcnt_t));
} break;
break;
// 'R' - Begin continuous sampling/conversion of the ADC. Samples will go through
// 'm' - Returns the last measured sample processing time, presumably in processor // the conversion code, and will be sent out over the DAC.
// ticks. case 'R':
case 'm': if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) {
USBSerial::write(reinterpret_cast<uint8_t *>(&conversion_time_measurement.last), run_status = RunStatus::Running;
sizeof(rtcnt_t)); samplesOut.clear();
break; ADC::start(samplesIn.data(), samplesIn.size(), signal_operate);
DAC::start(0, samplesOut.data(), samplesOut.size());
// 'R' - Begin continuous sampling/conversion of the ADC. Samples will go through }
// the conversion code, and will be sent out over the DAC. break;
case 'R':
if (EM.assert(run_status == RunStatus::Idle, Error::NotIdle)) { case 'r':
run_status = RunStatus::Running; if (EM.assert(USBSerial::read(&cmd[1], 1) == 1, Error::BadParamSize)) {
samplesOut.clear(); if (cmd[1] == 0xFF) {
ADC::start(samplesIn.data(), samplesIn.size(), signal_operate); unsigned char r = SClock::getRate();
DAC::start(0, samplesOut.data(), samplesOut.size()); USBSerial::write(&r, 1);
} } else {
break; auto r = static_cast<SClock::Rate>(cmd[1]);
SClock::setRate(r);
case 'r': ADC::setRate(r);
if (EM.assert(USBSerial::read(&cmd[1], 1) == 1, Error::BadParamSize)) { }
if (cmd[1] == 0xFF) { }
unsigned char r = SClock::getRate(); break;
USBSerial::write(&r, 1);
} else { // 'S' - Stops the continuous sampling/conversion.
auto r = static_cast<SClock::Rate>(cmd[1]); case 'S':
SClock::setRate(r); if (run_status == RunStatus::Running) {
ADC::setRate(r); DAC::stop(0);
} ADC::stop();
} run_status = RunStatus::Idle;
break; }
break;
// 'S' - Stops the continuous sampling/conversion.
case 'S': case 's':
if (run_status == RunStatus::Running) { if (auto samps = samplesOut.modified(); samps != nullptr) {
DAC::stop(0); unsigned char buf[2] = {
ADC::stop(); static_cast<unsigned char>(samplesOut.size() / 2 & 0xFF),
run_status = RunStatus::Idle; static_cast<unsigned char>(((samplesOut.size() / 2) >> 8) & 0xFF)
} };
break; USBSerial::write(buf, 2);
unsigned int total = samplesOut.bytesize() / 2;
case 's': unsigned int offset = 0;
if (auto samps = samplesOut.modified(); samps != nullptr) { unsigned char unused;
unsigned char buf[2] = { while (total > 512) {
static_cast<unsigned char>(samplesOut.size() / 2 & 0xFF), USBSerial::write(reinterpret_cast<uint8_t *>(samps) + offset, 512);
static_cast<unsigned char>(((samplesOut.size() / 2) >> 8) & 0xFF) while (USBSerial::read(&unused, 1) == 0);
}; offset += 512;
USBSerial::write(buf, 2); total -= 512;
unsigned int total = samplesOut.bytesize() / 2; }
unsigned int offset = 0; USBSerial::write(reinterpret_cast<uint8_t *>(samps) + offset, total);
unsigned char unused; while (USBSerial::read(&unused, 1) == 0);
while (total > 512) { } else {
USBSerial::write(reinterpret_cast<uint8_t *>(samps) + offset, 512); USBSerial::write(reinterpret_cast<const uint8_t *>("\0\0"), 2);
while (USBSerial::read(&unused, 1) == 0); }
offset += 512; break;
total -= 512;
} case 'W':
USBSerial::write(reinterpret_cast<uint8_t *>(samps) + offset, total); DAC::start(1, samplesSigGen.data(), samplesSigGen.size());
while (USBSerial::read(&unused, 1) == 0); break;
} else { case 'w':
USBSerial::write(reinterpret_cast<const uint8_t *>("\0\0"), 2); DAC::stop(1);
} break;
break;
default:
#ifdef ENABLE_SIGGEN break;
case 'W': }
DAC::start(1, samplesSigGen.data(), samplesSigGen.size()); }
break; }
case 'w':
DAC::stop(1); chThdSleepMicroseconds(100);
break; }
#endif }
default: void conversion_abort()
break; {
} elf_entry = nullptr;
} DAC::stop(0);
} ADC::stop();
EM.add(Error::ConversionAborted);
chThdSleepMicroseconds(100); }
}
} THD_FUNCTION(conversionThread, arg)
{
void conversion_abort() (void)arg;
{
elf_entry = nullptr; while (1) {
DAC::stop(0); msg_t message;
ADC::stop(); if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) {
EM.add(Error::ConversionAborted); auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata();
} auto size = samplesIn.size() / 2;
THD_FUNCTION(conversionThread, arg) if (elf_entry) {
{ if (!MSG_FOR_MEASURE(message)) {
(void)arg; samples = elf_entry(samples, size);
} else {
while (1) { chTMStartMeasurementX(&conversion_time_measurement);
msg_t message; samples = elf_entry(samples, size);
if (chMBFetchTimeout(&conversionMB, &message, TIME_INFINITE) == MSG_OK) { chTMStopMeasurementX(&conversion_time_measurement);
auto samples = MSG_FOR_FIRST(message) ? samplesIn.data() : samplesIn.middata(); }
auto size = samplesIn.size() / 2; }
if (elf_entry) { if (MSG_FOR_FIRST(message))
if (!MSG_FOR_MEASURE(message)) { samplesOut.modify(samples, size);
samples = elf_entry(samples, size); else
} else { samplesOut.midmodify(samples, size);
chTMStartMeasurementX(&conversion_time_measurement); }
samples = elf_entry(samples, size); }
chTMStopMeasurementX(&conversion_time_measurement); }
}
} void signal_operate(adcsample_t *buffer, size_t)
{
if (MSG_FOR_FIRST(message)) chSysLockFromISR();
samplesOut.modify(samples, size);
else if (chMBGetUsedCountI(&conversionMB) > 1) {
samplesOut.midmodify(samples, size); chSysUnlockFromISR();
} conversion_abort();
} } else {
} chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST : MSG_CONVSECOND);
chSysUnlockFromISR();
void signal_operate(adcsample_t *buffer, size_t) }
{ }
chSysLockFromISR();
void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count)
if (chMBGetUsedCountI(&conversionMB) > 1) { {
chSysUnlockFromISR(); chSysLockFromISR();
conversion_abort(); chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST_MEASURE : MSG_CONVSECOND_MEASURE);
} else { chSysUnlockFromISR();
chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST : MSG_CONVSECOND);
chSysUnlockFromISR(); ADC::setOperation(signal_operate);
} }
}
THD_FUNCTION(Thread1, arg)
void signal_operate_measure(adcsample_t *buffer, [[maybe_unused]] size_t count) {
{ (void)arg;
chSysLockFromISR();
chMBPostI(&conversionMB, buffer == samplesIn.data() ? MSG_CONVFIRST_MEASURE : MSG_CONVSECOND_MEASURE); bool erroron = false;
chSysUnlockFromISR(); while (1) {
bool isidle = run_status == RunStatus::Idle;
ADC::setOperation(signal_operate); auto led = isidle ? LINE_LED_GREEN : LINE_LED_YELLOW;
} auto delay = isidle ? 500 : 250;
THD_FUNCTION(Thread1, arg) palSetLine(led);
{ chThdSleepMilliseconds(delay);
(void)arg; palClearLine(led);
while (1) { chThdSleepMilliseconds(delay);
palSetLine(LINE_LED1);
chThdSleepMilliseconds(70); if (auto err = EM.hasError(); err ^ erroron) {
palSetLine(LINE_LED2); erroron = err;
chThdSleepMilliseconds(70); if (err)
palSetLine(LINE_LED3); palSetLine(LINE_LED_RED);
chThdSleepMilliseconds(240); else
palClearLine(LINE_LED1); palClearLine(LINE_LED_RED);
chThdSleepMilliseconds(70); }
palClearLine(LINE_LED2); }
chThdSleepMilliseconds(70); }
palClearLine(LINE_LED3);
chThdSleepMilliseconds(240); extern "C" {
}
} __attribute__((naked))
void HardFault_Handler()
extern "C" { {
while (1);
__attribute__((naked)) // //asm("push {lr}");
void HardFault_Handler() //
{ // uint32_t *stack;
while (1); // uint32_t lr;
// //asm("push {lr}"); // asm("\
// // tst lr, #4; \
// uint32_t *stack; // ite eq; \
// uint32_t lr; // mrseq %0, msp; \
// asm("\ // mrsne %0, psp; \
// tst lr, #4; \ // mov %1, lr; \
// ite eq; \ // " : "=r" (stack), "=r" (lr));
// mrseq %0, msp; \ // //stack++;
// mrsne %0, psp; \ // stack[7] |= (1 << 24); // Keep Thumb mode enabled
// mov %1, lr; \ //
// " : "=r" (stack), "=r" (lr)); // conversion_abort();
// //stack++; //
// stack[7] |= (1 << 24); // Keep Thumb mode enabled // // TODO test lr and decide how to recover
// //
// conversion_abort(); // //if (run_status == RunStatus::Converting) {
// // stack[6] = stack[5]; // Escape from elf_entry code
// // TODO test lr and decide how to recover // //} else /*if (run_status == RunStatus::Recovered)*/ {
// // // stack[6] = (uint32_t)main_loop & ~1; // Return to safety
// //if (run_status == RunStatus::Converting) { // //}
// stack[6] = stack[5]; // Escape from elf_entry code //
// //} else /*if (run_status == RunStatus::Recovered)*/ { // //asm("pop {lr}; bx lr");
// // stack[6] = (uint32_t)main_loop & ~1; // Return to safety // asm("bx lr");
// //} }
//
// //asm("pop {lr}; bx lr"); } // extern "C"
// asm("bx lr");
}
} // extern "C"

Loading…
Cancel
Save