1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-01 10:23:19 +02:00

Added more x86 wrappers. Only 35 remain, and then we can do some serious testing.

This commit is contained in:
Stefan de Bruijn
2021-07-05 21:25:33 +02:00
parent a6be38ff7f
commit c785ae3332
15 changed files with 446 additions and 85 deletions

View File

@@ -174,6 +174,7 @@
<ClInclude Include="X86TestSupport\esp_err.h" />
<ClInclude Include="X86TestSupport\esp_system.h" />
<ClInclude Include="X86TestSupport\freertos\FreeRTOS.h" />
<ClInclude Include="X86TestSupport\freertos\FreeRTOSTypes.h" />
<ClInclude Include="X86TestSupport\freertos\Queue.h" />
<ClInclude Include="X86TestSupport\freertos\Task.h" />
<ClInclude Include="X86TestSupport\FS.h" />
@@ -303,7 +304,12 @@
<ClCompile Include="Grbl_Esp32\test\TestFrameworkTest.cpp" />
<ClCompile Include="Grbl_Esp32\test\test_main.cpp" />
<ClCompile Include="X86TestSupport\Arduino.cpp" />
<ClCompile Include="X86TestSupport\driver\dac.cpp" />
<ClCompile Include="X86TestSupport\driver\ledc.cpp" />
<ClCompile Include="X86TestSupport\driver\uartdriver.cpp" />
<ClCompile Include="X86TestSupport\ExceptionHelper.cpp" />
<ClCompile Include="X86TestSupport\freertos\Queue.cpp" />
<ClCompile Include="X86TestSupport\freertos\Task.cpp" />
<ClCompile Include="X86TestSupport\FS.cpp" />
<ClCompile Include="X86TestSupport\nvs.cpp" />
<ClCompile Include="X86TestSupport\Print.cpp" />

View File

@@ -37,6 +37,15 @@
<Filter Include="tests">
<UniqueIdentifier>{9396f607-9b99-4f0e-bfdb-f549462e0205}</UniqueIdentifier>
</Filter>
<Filter Include="X86TestSupport\freertos">
<UniqueIdentifier>{170a3d62-e923-4fa4-919a-c5a265fc6327}</UniqueIdentifier>
</Filter>
<Filter Include="X86TestSupport\driver">
<UniqueIdentifier>{1c6b65a5-ab00-4633-aba8-cb541e15d722}</UniqueIdentifier>
</Filter>
<Filter Include="X86TestSupport\soc">
<UniqueIdentifier>{2fe0b2ec-2f5f-44c9-8e5d-33a53d96d80c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Grbl_Esp32\src\Machine\SPIBus.h">
@@ -60,9 +69,6 @@
<ClInclude Include="Grbl_Esp32\src\SimpleOutputStream.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\task.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\Spindles\Spindle.h">
<Filter>src\Spindles</Filter>
</ClInclude>
@@ -141,9 +147,6 @@
<ClInclude Include="Grbl_Esp32\src\Probe.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\Queue.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\Machine\Endstops.h">
<Filter>src\Machine</Filter>
</ClInclude>
@@ -159,9 +162,6 @@
<ClInclude Include="Grbl_Esp32\src\Pins\PinCapabilities.h">
<Filter>src\Pins</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\uart.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\soc\dport_reg.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
@@ -177,9 +177,6 @@
<ClInclude Include="Grbl_Esp32\src\Config.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\rmt.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\GCode.h">
<Filter>src</Filter>
</ClInclude>
@@ -189,18 +186,12 @@
<ClInclude Include="Grbl_Esp32\src\WebUI\Authentication.h">
<Filter>src\WebUI</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\soc\ledc_struct.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\Regex.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\WebUI\ESPResponse.h">
<Filter>src\WebUI</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\dac.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="Grbl_Esp32\src\Spindles\DacSpindle.h">
<Filter>src\Spindles</Filter>
</ClInclude>
@@ -225,9 +216,6 @@
<ClInclude Include="X86TestSupport\esp_system.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\FreeRTOS.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\SoftwareGPIO.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
@@ -405,9 +393,6 @@
<ClInclude Include="Grbl_Esp32\src\Machine\I2SOBus.h">
<Filter>src\Machine</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\ledc.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\SPI.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
@@ -495,6 +480,33 @@
<ClInclude Include="X86TestSupport\Capture.h">
<Filter>X86TestSupport</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\Task.h">
<Filter>X86TestSupport\freertos</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\Queue.h">
<Filter>X86TestSupport\freertos</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\FreeRTOS.h">
<Filter>X86TestSupport\freertos</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\freertos\FreeRTOSTypes.h">
<Filter>X86TestSupport\freertos</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\dac.h">
<Filter>X86TestSupport\driver</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\ledc.h">
<Filter>X86TestSupport\driver</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\rmt.h">
<Filter>X86TestSupport\driver</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\driver\uart.h">
<Filter>X86TestSupport\driver</Filter>
</ClInclude>
<ClInclude Include="X86TestSupport\soc\ledc_struct.h">
<Filter>X86TestSupport\soc</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Grbl_Esp32\src\WebUI\JSONEncoder.cpp">
@@ -827,6 +839,21 @@
<ClCompile Include="X86TestSupport\nvs.cpp">
<Filter>X86TestSupport</Filter>
</ClCompile>
<ClCompile Include="X86TestSupport\freertos\Task.cpp">
<Filter>X86TestSupport\freertos</Filter>
</ClCompile>
<ClCompile Include="X86TestSupport\freertos\Queue.cpp">
<Filter>X86TestSupport\freertos</Filter>
</ClCompile>
<ClCompile Include="X86TestSupport\driver\dac.cpp">
<Filter>X86TestSupport\driver</Filter>
</ClCompile>
<ClCompile Include="X86TestSupport\driver\ledc.cpp">
<Filter>X86TestSupport\driver</Filter>
</ClCompile>
<ClCompile Include="X86TestSupport\driver\uartdriver.cpp">
<Filter>X86TestSupport\driver</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="Grbl_Esp32\src\SimpleOutputStream.md">

View File

@@ -46,3 +46,29 @@ void delay(int ms) {
int temperatureRead(void) {
return 22; // Nobody cares
}
esp_reset_reason_t esp_reset_reason(void) {
return ESP_RST_POWERON;
}
uint64_t EspClass::getEfuseMac() {
return 0x0102030405060708ULL;
}
uint32_t EspClass::getCpuFreqMHz() {
return 240;
}
const char* EspClass::getSdkVersion() {
return "v1.0-UnitTest-foobar";
}
uint32_t EspClass::getFreeHeap() {
return 0xFFFF;
}
uint32_t EspClass::getFlashChipSize() {
return 4 * 1024 * 1024;
}
void EspClass::restart() {
throw SystemRestartException();
}
EspClass ESP;

View File

@@ -4,6 +4,8 @@
#include "esp_err.h"
class SystemRestartException {};
#define IRAM_ATTR
// From Arduino.h:

View File

@@ -3,6 +3,7 @@
#include <string>
#include <cstdint>
#include <vector>
#include <unordered_map>
// Capture here defines everything that we want to know. Specifically, we want to capture per ID:
// 1. Timings. *When* did something happen?
@@ -11,16 +12,16 @@
// An ID itself is a string. This can be a pin ID (gpio.1), an uart (uart.0), an ledc, or whatever.
struct CaptureEvent {
uint32_t time;
uint32_t time = 0;
std::string id;
std::vector<uint32_t> data;
};
class Capture {
Capture() {}
Capture() = default;
std::vector<CaptureEvent> events;
uint32_t currentTime;
uint32_t currentTime = 0;
public:
static Capture& instance() {
@@ -30,7 +31,7 @@ public:
void reset() { events.clear(); }
void write(std::string id, uint32_t value) {
void write(const std::string& id, uint32_t value) {
CaptureEvent evt;
evt.time = currentTime;
evt.id = id;
@@ -39,6 +40,79 @@ public:
events.push_back(evt);
}
void wait(uint32_t delay) { currentTime += delay; }
void write(const std::string& id, uint32_t value, uint32_t time) {
CaptureEvent evt;
evt.time = time;
evt.id = id;
evt.data.reserve(1);
evt.data.push_back(value);
events.push_back(evt);
}
void write(const std::string& id, uint32_t value, std::vector<uint32_t> data) {
CaptureEvent evt;
evt.time = currentTime;
evt.id = id;
evt.data = data;
events.push_back(evt);
}
void write(const std::string& id, uint32_t value, uint32_t time, std::vector<uint32_t> data) {
CaptureEvent evt;
evt.time = time;
evt.id = id;
evt.data = data;
events.push_back(evt);
}
uint32_t current() { return currentTime; }
void wait(uint32_t delay) { currentTime += delay; }
void waitUntil(uint32_t value) {
if (value > currentTime) {
currentTime = value;
}
}
void yield() { wait(1); }
};
class Inputs {
std::unordered_map<std::string, std::vector<uint32_t>> data_;
public:
static Inputs& instance() {
static Inputs instance;
return instance;
}
void reset() { data_.clear(); }
void set(const std::string& id, uint32_t value) {
auto it = data_.find(id);
auto vec = std::vector<uint32_t> { value };
if (it == data_.end()) {
data_.insert(std::make_pair(id, vec));
} else {
it->second = vec;
}
}
void set(const std::string& id, const std::vector<uint32_t>& value) {
auto it = data_.find(id);
if (it == data_.end()) {
data_.insert(std::make_pair(id, value));
} else {
it->second = value;
}
}
const std::vector<uint32_t>& get(const std::string& key) {
static std::vector<uint32_t> empty;
auto it = data_.find(key);
if (it == data_.end()) {
return empty;
} else {
return it->second;
}
}
};

View File

@@ -3,12 +3,9 @@ These functions still need to be implemented for X86 unit tests to run:
Note: I2S can be stubs. vTask can run through thread probably. xQueue should be a queue. nvs is already implemented, but needs forwarders. UART needs work.
TODO: Two things need to be captured: (1) uart/pin/etc and (2) timings. All timings are 0, *unless* something sleeps, which updates the 'current time'. So I don't want to emulate as-is, but rather make things super-fast. The only notable exception is spinlocks... we should device something to handle that.
"__int64 __cdecl esp_timer_get_time(void)" (?esp_timer_get_time@@YA_JXZ)
"class SPIClass SPI" (?SPI@@3VSPIClass@@A)
"class fs::SDFS SD" (?SD@@3VSDFS@fs@@A)
"class fs::SPIFFSFS SPIFFS" (?SPIFFS@@3VSPIFFSFS@fs@@A)
"double __cdecl ledcSetup(unsigned char,double,unsigned char)" (?ledcSetup@@YANENE@Z)
"enum esp_reset_reason_t __cdecl esp_reset_reason(void)" (?esp_reset_reason@@YA?AW4esp_reset_reason_t@@XZ)
"enum i2s_out_pulser_status_t __cdecl i2s_out_get_pulser_status(void)" (?i2s_out_get_pulser_status@@YA?AW4i2s_out_pulser_status_t@@XZ)
"int __cdecl i2s_out_init(void)" (?i2s_out_init@@YAHXZ)
"int __cdecl i2s_out_reset(void)" (?i2s_out_reset@@YAHXZ)
@@ -19,62 +16,24 @@ TODO: Two things need to be captured: (1) uart/pin/etc and (2) timings. All timi
"int __cdecl rmt_config(struct rmt_config_t const *)" (?rmt_config@@YAHPBUrmt_config_t@@@Z)
"int __cdecl rmt_fill_tx_items(enum rmt_channel_t,struct rmt_item32_s const *,unsigned short,unsigned short)" (?rmt_fill_tx_items@@YAHW4rmt_channel_t@@PBUrmt_item32_s@@GG@Z)
"int __cdecl rmt_set_source_clk(enum rmt_channel_t,enum rmt_source_clk_t)" (?rmt_set_source_clk@@YAHW4rmt_channel_t@@W4rmt_source_clk_t@@@Z)
"int __cdecl uart_driver_install(enum uart_port_t,int,int,int,void * *,int)" (?uart_driver_install@@YAHW4uart_port_t@@HHHPAPAXH@Z)
"int __cdecl uart_flush(enum uart_port_t)" (?uart_flush@@YAHW4uart_port_t@@@Z)
"int __cdecl uart_get_buffered_data_len(enum uart_port_t,unsigned int *)" (?uart_get_buffered_data_len@@YAHW4uart_port_t@@PAI@Z)
"int __cdecl uart_param_config(enum uart_port_t,struct uart_config_t const *)" (?uart_param_config@@YAHW4uart_port_t@@PBUuart_config_t@@@Z)
"int __cdecl uart_read_bytes(enum uart_port_t,unsigned char *,unsigned int,unsigned int)" (?uart_read_bytes@@YAHW4uart_port_t@@PAEII@Z)
"int __cdecl uart_set_mode(enum uart_port_t,enum uart_mode_t)" (?uart_set_mode@@YAHW4uart_port_t@@W4uart_mode_t@@@Z)
"int __cdecl uart_set_pin(enum uart_port_t,int,int,int,int)" (?uart_set_pin@@YAHW4uart_port_t@@HHHH@Z)
"int __cdecl uart_wait_tx_done(enum uart_port_t,unsigned int)" (?uart_wait_tx_done@@YAHW4uart_port_t@@I@Z)
"int __cdecl uart_write_bytes(enum uart_port_t,char const *,unsigned int)" (?uart_write_bytes@@YAHW4uart_port_t@@PBDI@Z)
"int __cdecl xPortGetFreeHeapSize(void)" (?xPortGetFreeHeapSize@@YAHXZ)
"int __cdecl xQueueGenericReceive(void *,void * const,unsigned int,int)" (?xQueueGenericReceive@@YAHPAXQAXIH@Z)
"int __cdecl xQueueGenericReset(void *,int)" (?xQueueGenericReset@@YAHPAXH@Z)
"int __cdecl xQueueGenericSend(void *,void const * const,unsigned int,int)" (?xQueueGenericSend@@YAHPAXQBXIH@Z)
"int __cdecl xQueueGenericSendFromISR(void *,void const * const,int * const,int)" (?xQueueGenericSendFromISR@@YAHPAXQBXQAHH@Z)
"int __cdecl xTaskCreatePinnedToCore(void (__cdecl*)(void *),char const * const,unsigned int,void * const,unsigned int,void * * const,int)" (?xTaskCreatePinnedToCore@@YAHP6AXPAX@ZQBDIQAXIQAPAXH@Z)
"protected: int __thiscall Stream::timedPeek(void)" (?timedPeek@Stream@@IAEHXZ)
"protected: int __thiscall Stream::timedRead(void)" (?timedRead@Stream@@IAEHXZ)
"public: bool __thiscall Stream::findUntil(char const *,unsigned int,char const *,unsigned int)" (?findUntil@Stream@@QAE_NPBDI0I@Z)
"public: bool __thiscall fs::SDFS::begin(unsigned char,class SPIClass &,unsigned int,char const *,unsigned char,bool)" (?begin@SDFS@fs@@QAE_NEAAVSPIClass@@IPBDE_N@Z)
"public: bool __thiscall fs::SPIFFSFS::begin(bool,char const *,unsigned char,char const *)" (?begin@SPIFFSFS@fs@@QAE_N_NPBDE1@Z)
"public: bool __thiscall fs::SPIFFSFS::format(void)" (?format@SPIFFSFS@fs@@QAE_NXZ)
"public: char const * __thiscall EspClass::getSdkVersion(void)" (?getSdkVersion@EspClass@@QAEPBDXZ)
"public: unsigned __int64 __thiscall EspClass::getEfuseMac(void)" (?getEfuseMac@EspClass@@QAE_KXZ)
"public: unsigned __int64 __thiscall fs::SDFS::cardSize(void)" (?cardSize@SDFS@fs@@QAE_KXZ)
"public: unsigned __int64 __thiscall fs::SDFS::totalBytes(void)" (?totalBytes@SDFS@fs@@QAE_KXZ)
"public: unsigned __int64 __thiscall fs::SDFS::usedBytes(void)" (?usedBytes@SDFS@fs@@QAE_KXZ)
"public: unsigned int __thiscall EspClass::getCpuFreqMHz(void)" (?getCpuFreqMHz@EspClass@@QAEIXZ)
"public: unsigned int __thiscall EspClass::getFlashChipSize(void)" (?getFlashChipSize@EspClass@@QAEIXZ)
"public: unsigned int __thiscall EspClass::getFreeHeap(void)" (?getFreeHeap@EspClass@@QAEIXZ)
"public: unsigned int __thiscall fs::SPIFFSFS::totalBytes(void)" (?totalBytes@SPIFFSFS@fs@@QAEIXZ)
"public: unsigned int __thiscall fs::SPIFFSFS::usedBytes(void)" (?usedBytes@SPIFFSFS@fs@@QAEIXZ)
"public: void __thiscall EspClass::restart(void)" (?restart@EspClass@@QAEXXZ)
"public: void __thiscall fs::SDFS::end(void)" (?end@SDFS@fs@@QAEXXZ)
"struct EspClass ESP" (?ESP@@3UEspClass@@A)
"struct hw_timer_s * __cdecl timerBegin(unsigned char,unsigned short,bool)" (?timerBegin@@YAPAUhw_timer_s@@EG_N@Z)
"struct ledc_dev_t volatile LEDC" (?LEDC@@3Uledc_dev_t@@C)
"struct rmt_dev_s volatile RMT" (?RMT@@3Urmt_dev_s@@C)
"unsigned int __cdecl getApbFrequency(void)" (?getApbFrequency@@YAIXZ)
"unsigned int __cdecl i2s_out_push_sample(unsigned int)" (?i2s_out_push_sample@@YAII@Z)
"unsigned int __cdecl xTaskGetTickCount(void)" (?xTaskGetTickCount@@YAIXZ)
"unsigned long __cdecl millis(void)" (?millis@@YAKXZ)
"void * __cdecl xQueueGenericCreate(unsigned int,unsigned int,unsigned char)" (?xQueueGenericCreate@@YAPAXIIE@Z)
"void __cdecl dacWrite(unsigned char,unsigned char)" (?dacWrite@@YAXEE@Z)
"void __cdecl delay(unsigned int)" (?delay@@YAXI@Z)
"void __cdecl i2s_out_delay(void)" (?i2s_out_delay@@YAXXZ)
"void __cdecl ledcAttachPin(unsigned char,unsigned char)" (?ledcAttachPin@@YAXEE@Z)
"void __cdecl ledcDetachPin(unsigned char)" (?ledcDetachPin@@YAXE@Z)
"void __cdecl ledcWrite(unsigned char,unsigned int)" (?ledcWrite@@YAXEI@Z)
"void __cdecl pinMatrixOutAttach(unsigned char,unsigned char,bool,bool)" (?pinMatrixOutAttach@@YAXEE_N0@Z)
"void __cdecl timerAlarmDisable(struct hw_timer_s *)" (?timerAlarmDisable@@YAXPAUhw_timer_s@@@Z)
"void __cdecl timerAlarmEnable(struct hw_timer_s *)" (?timerAlarmEnable@@YAXPAUhw_timer_s@@@Z)
"void __cdecl timerAlarmWrite(struct hw_timer_s *,unsigned __int64,bool)" (?timerAlarmWrite@@YAXPAUhw_timer_s@@_K_N@Z)
"void __cdecl timerAttachInterrupt(struct hw_timer_s *,void (__cdecl*)(void),bool)" (?timerAttachInterrupt@@YAXPAUhw_timer_s@@P6AXXZ_N@Z)
"void __cdecl timerWrite(struct hw_timer_s *,unsigned __int64)" (?timerWrite@@YAXPAUhw_timer_s@@_K@Z)
"void __cdecl vTaskDelay(unsigned int)" (?vTaskDelay@@YAXI@Z)
"void __cdecl vTaskDelayUntil(unsigned int * const,unsigned int)" (?vTaskDelayUntil@@YAXQAII@Z)
"void __cdecl vTaskEnterCritical(class std::mutex *)" (?vTaskEnterCritical@@YAXPAVmutex@std@@@Z)
"void __cdecl vTaskExitCritical(class std::mutex *)" (?vTaskExitCritical@@YAXPAVmutex@std@@@Z)
_esp_task_wdt_reset

View File

@@ -0,0 +1,12 @@
#include "dac.h"
#include "../Capture.h"
#include <string>
#include <sstream>
void dacWrite(uint8_t pin, uint8_t value) {
std::ostringstream oss;
oss << "DAC." << pin;
Capture::instance().write(oss.str(), value);
}

View File

@@ -0,0 +1,51 @@
#include "ledc.h"
#include "../soc/ledc_struct.h"
#include "../Arduino.h"
#include "../Capture.h"
#include <sstream>
class LEDCInfo {
public:
LEDCInfo() : chan_(0), freq_(0), pin_(0) {}
LEDCInfo(int chan, double freq, int pin) : chan_(chan), freq_(freq), pin_(pin) {
std::ostringstream oss;
oss << "ledc." << chan << ";freq=" << freq << ";pin=" << pin;
key_ = oss.str();
}
int chan_;
double freq_;
int pin_;
std::string key_;
void write(uint32_t duty) { Capture::instance().write(key_, duty); }
};
LEDCInfo infos[16];
uint32_t getApbFrequency() { // in Hz
return 80'000'000; // 80 MHz
}
double ledcSetup(uint8_t chan, double freq, uint8_t resolution_bits) {
infos[chan] = LEDCInfo(chan, freq, 0);
return freq;
}
void ledcWrite(uint8_t channel, uint32_t duty) {
infos[channel].write(duty);
}
void ledcAttachPin(uint8_t pin, uint8_t channel) {
auto old = infos[channel];
infos[channel] = LEDCInfo(channel, old.freq_, pin);
}
void ledcDetachPin(uint8_t pin) {
for (int i = 0; i < 16; ++i) {
if (infos[i].pin_ == pin) {
infos[i] = LEDCInfo(0, 0, 0);
}
}
}
// TODO FIXME: Find some way to cope with these:
void pinMatrixOutAttach(uint8_t pin, uint8_t function, bool invertOut, bool invertEnable) {} // Cannot capture this...
void pinMatrixOutDetach(uint8_t pin, bool invertOut, bool invertEnable) {} // Cannot capture this...

View File

@@ -0,0 +1,63 @@
#include "uart.h"
#include "../Capture.h"
#include "../esp_err.h"
#include <sstream>
#include <algorithm>
inline std::string uart_key(uart_port_t uart_num) {
std::ostringstream key;
key << "uart." << uart_num;
return key.str();
}
esp_err_t uart_flush(uart_port_t uart_num) {
return ESP_OK;
}
esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t* uart_config) {
return ESP_OK;
}
esp_err_t uart_driver_install(
uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t* uart_queue, int intr_alloc_flags) {
return ESP_OK;
}
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size) {
auto key = uart_key(uart_num);
const auto& val = Inputs::instance().get(key);
*size = val.size();
return ESP_OK;
}
int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait) {
auto key = uart_key(uart_num);
const auto& val = Inputs::instance().get(key);
auto max = std::min(length, val.size());
for (size_t i = 0; i < max; ++i) {
buf[i] = uint8_t(val[i]);
}
std::vector<uint32_t> newval(val.begin() + max, val.end());
Inputs::instance().set(key, newval);
return int(max);
}
int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size) {
auto key = uart_key(uart_num);
auto val = Inputs::instance().get(key);
for (size_t i = 0; i < size; ++i) {
val.push_back(uint32_t(uint8_t(src[i])));
}
Inputs::instance().set(key, val);
return int(size);
}
esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode) {
return ESP_OK;
}
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) {
return ESP_OK;
}
esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) {
return ESP_OK;
}

View File

@@ -2,12 +2,10 @@
#include "Task.h"
#include "Queue.h"
#include "FreeRTOSTypes.h"
#include <mutex>
/* "mux" data structure (spinlock) */
using portMUX_TYPE = std::mutex;
#define portMAX_DELAY (TickType_t)0xffffffffUL
void vTaskExitCritical(portMUX_TYPE* mux);
void vTaskEnterCritical(portMUX_TYPE* mux);

View File

@@ -0,0 +1,15 @@
#pragma once
#include <mutex>
using portMUX_TYPE = std::mutex;
#define portMAX_DELAY (TickType_t)0xffffffffUL
using portBASE_TYPE = int;
using UBaseType_t = unsigned int;
using BaseType_t = portBASE_TYPE;
using TickType_t = uint32_t;
typedef void (*TaskFunction_t)(void*);
typedef void* TaskHandle_t;

View File

@@ -0,0 +1,62 @@
#include "Queue.h"
#include <atomic>
#include <vector>
#include <mutex>
QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType /* =0 */) {
auto ptr = new QueueHandle();
ptr->entrySize = uxItemSize;
ptr->numberItems = uxQueueLength;
ptr->data.resize(uxItemSize * uxQueueLength);
return ptr;
}
BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void* const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek) {
std::lock_guard<std::mutex> lock(xQueue->mutex);
if (xQueue->readIndex != xQueue->writeIndex) {
memcpy(pvBuffer, xQueue->data.data() + xQueue->readIndex, xQueue->entrySize);
auto newPtr = xQueue->readIndex + xQueue->entrySize;
if (newPtr == xQueue->data.size()) {
newPtr = 0;
}
xQueue->readIndex = newPtr;
return pdTRUE;
} else {
return errQUEUE_FULL; // no receive
}
}
BaseType_t xQueueGenericSendFromISR(QueueHandle_t xQueue,
const void* const pvItemToQueue,
BaseType_t* const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition) {
std::lock_guard<std::mutex> lock(xQueue->mutex);
auto newPtr = xQueue->writeIndex + xQueue->entrySize;
if (newPtr == xQueue->data.size()) {
newPtr = 0;
}
if (xQueue->readIndex != newPtr) {
memcpy(xQueue->data.data() + xQueue->writeIndex, pvItemToQueue, xQueue->entrySize);
xQueue->writeIndex = newPtr;
return pdTRUE;
} else {
return errQUEUE_FULL;
}
}
BaseType_t xQueueGenericReset(QueueHandle_t xQueue, BaseType_t xNewQueue) {
std::lock_guard<std::mutex> lock(xQueue->mutex);
xQueue->writeIndex = xQueue->readIndex = 0;
return pdTRUE;
}
BaseType_t xQueueGenericSend(QueueHandle_t xQueue, const void* const pvItemToQueue, TickType_t xTicksToWait, BaseType_t xCopyPosition) {
return xQueueGenericSendFromISR(xQueue, pvItemToQueue, nullptr, xCopyPosition);
}

View File

@@ -1,11 +1,27 @@
#pragma once
#include "task.h"
#include "Task.h"
#include "FreeRTOSTypes.h"
typedef void* QueueHandle_t;
#include <queue>
#include <mutex>
using xQueueHandle = QueueHandle_t;
struct QueueHandle {
std::mutex mutex;
size_t numberItems = 16;
size_t entrySize = 1;
size_t readIndex = 0;
size_t writeIndex = 0;
// Basically this is just a round-robin buffer:
std::vector<char> data;
};
using QueueHandle_t = QueueHandle*;
using xQueueHandle = QueueHandle_t;
#define errQUEUE_FULL ((BaseType_t)0)
#define queueSEND_TO_BACK ((BaseType_t)0)
#define queueSEND_TO_FRONT ((BaseType_t)1)
#define queueOVERWRITE ((BaseType_t)2)

View File

@@ -0,0 +1,56 @@
#include "Task.h"
#include "Capture.h"
#include "../Arduino.h"
// This code is based on std::thread, which is actually incorrect. A closer representation would be to
// use thread fibers like MS ConvertThreadToFiber and CreateFiber. That way, we can have 2 threads (one for
// each CPU) and then allocate multiple cooperative (non-preemptive) fibers on it.
#include <thread>
#include <vector>
#include <memory>
std::vector<std::unique_ptr<std::thread>> threads;
BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,
const char* const pcName,
const uint32_t usStackDepth,
void* const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t* const pvCreatedTask,
const BaseType_t xCoreID) {
std::unique_ptr<std::thread> thread = std::make_unique<std::thread>(pvTaskCode, pvParameters);
threads.emplace_back(std::move(thread));
return pdTRUE;
}
void vTaskDelay(const TickType_t xTicksToDelay) {
Capture::instance().wait(xTicksToDelay);
}
void vTaskDelayUntil(TickType_t* const pxPreviousWakeTime, const TickType_t xTimeIncrement) {
Capture::instance().waitUntil((*pxPreviousWakeTime + xTimeIncrement));
}
TickType_t xTaskGetTickCount(void) {
auto& inst = Capture::instance();
inst.wait(1);
return inst.current();
}
unsigned long micros() {
return xTaskGetTickCount() / (portTICK_PERIOD_MS / 1000);
}
unsigned long millis() {
return xTaskGetTickCount() / portTICK_PERIOD_MS;
}
void delay(uint32_t value) {
vTaskDelay(value * portTICK_PERIOD_MS); // delay a while
}
void delayMicroseconds(uint32_t us) {
vTaskDelay(us * (portTICK_PERIOD_MS / 1000)); // delay a while
}

View File

@@ -2,17 +2,10 @@
#include "../Arduino.h"
#include "FreeRTOS.h"
#define portBASE_TYPE int
typedef unsigned portBASE_TYPE UBaseType_t;
typedef portBASE_TYPE BaseType_t;
typedef uint32_t TickType_t;
#include "FreeRTOSTypes.h"
void vTaskDelay(const TickType_t xTicksToDelay);
typedef void (*TaskFunction_t)(void*);
typedef void* TaskHandle_t;
#define CONFIG_ARDUINO_RUNNING_CORE 0
BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,
@@ -51,7 +44,8 @@ TickType_t xTaskGetTickCount(void);
// Keep this in sync with the portMUX_TYPE struct definition please.
#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
# define portMUX_INITIALIZER_UNLOCKED {}
# define portMUX_INITIALIZER_UNLOCKED \
{}
#else
# define portMUX_INITIALIZER_UNLOCKED \
{ .owner = portMUX_FREE_VAL, .count = 0, .lastLockedFn = "(never locked)", .lastLockedLine = -1 }