Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
fc27690
Initial work on io state inspection
MaartenS11 Oct 10, 2023
f363b92
Obtain io state through portOutput/InputRegister
MaartenS11 Oct 14, 2023
ca93a52
Remove io map from Module struct
MaartenS11 Oct 14, 2023
6391e40
Use NUM_DIGITAL_PINS because SOC_GPIO_PIN_COUNT is esp specific
MaartenS11 Oct 14, 2023
2173305
Serialize/deserialize pin mode in snapshot data
MaartenS11 Oct 15, 2023
3d29223
Use digitalPinToBitMask in an attempt to make the code more microcont…
MaartenS11 Oct 15, 2023
410a94e
Port WARDuino to the Zephyr RTOS
MaartenS11 Feb 2, 2024
e8e9a03
Try correcting for drift in the servo motor driver
MaartenS11 Feb 5, 2024
74a0fa3
Fixed cmake with branch rebase
MaartenS11 Mar 9, 2024
7c8532f
Use vfprintf instead of fprintf to handle variadic arguments
MaartenS11 Mar 9, 2024
8d79243
Loading snapshots should work again now
MaartenS11 Mar 9, 2024
4f55465
Hacky but it's starting to work
MaartenS11 Feb 14, 2024
d102350
Somewhat hacky way of extracting the current sensor value
MaartenS11 Feb 14, 2024
41ed76e
Put uart heartbeat for sensors in a thread + colour_sensor now return…
MaartenS11 Feb 14, 2024
0cd0ee5
Allow controlling multiple motors
MaartenS11 Feb 24, 2024
98f5f54
Added anti-stall system to motor driver
MaartenS11 Feb 28, 2024
035fcc9
Merge remote-tracking branch 'origin/exp/io-state' into feat/zephyr-p…
MaartenS11 Mar 9, 2024
b6e2c68
Make motor driver reversible
MaartenS11 Mar 20, 2024
865bc32
Added some things needed to make uart sensor work
MaartenS11 Apr 1, 2024
2b420fc
Added invoke_primitive function that makes it easy to call primitives…
MaartenS11 Apr 8, 2024
6368bb5
New API for reversible primitives
MaartenS11 Apr 8, 2024
315464d
Rename PinState to IOStateElement and clean up debugger ioState inter…
MaartenS11 Apr 11, 2024
00cccde
Clang format
MaartenS11 Aug 2, 2024
0e29161
Merge remote-tracking branch 'origin/main' into feat/obb-reversible
MaartenS11 Aug 2, 2024
01ee63e
Only run the reverse operation for the primitive that was just execut…
MaartenS11 Aug 3, 2024
6995bca
Use ms to configure stall timeout for motors
MaartenS11 Aug 6, 2024
aedd0a1
Adjust speed faster when stalling
MaartenS11 Aug 7, 2024
051e9bf
Don't wait for the full 10ms if we have already detected movement
MaartenS11 Aug 7, 2024
8c6fe19
Stripped out open bot brain primitives
MaartenS11 Aug 19, 2024
958b399
Clang format
MaartenS11 Aug 19, 2024
77aa523
Make chip_digital_write on arduino reversible using the new macros
MaartenS11 Aug 19, 2024
1b291f5
Remove io-arduino.cpp and fix usage of PinState
MaartenS11 Aug 19, 2024
e22697d
def_prim_serialize should not return anything for chip_digital_write
MaartenS11 Aug 19, 2024
f8b01cb
Add extra clause to if so int32_t and int are bot considered I32 in c…
MaartenS11 Aug 19, 2024
5b5d298
Add new macros + restore_external_state + get_io_state to ESP-IDF
MaartenS11 Aug 19, 2024
0c53588
Install primitive reverse for chip_digital_write
MaartenS11 Aug 20, 2024
fa8a558
Just use NUM_PRIMITIVES and set it to 5
MaartenS11 Aug 20, 2024
829ae4b
Move last remaining bits of io.h into primitives.h
MaartenS11 Aug 20, 2024
9edb6ab
Add reversible primitive code to emulated.cpp
MaartenS11 Aug 20, 2024
296fffd
Fixed zephyr build
MaartenS11 Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions platforms/Zephyr/boards/stm32l496g_disco.overlay
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,20 @@

pwms =
<&pwm8 3 10000 PWM_POLARITY_NORMAL>,
<&pwm8 4 10000 PWM_POLARITY_NORMAL>;
<&pwm8 4 10000 PWM_POLARITY_NORMAL>,
<&pwm8 1 10000 PWM_POLARITY_NORMAL>,
<&pwm8 2 10000 PWM_POLARITY_NORMAL>;

warduino-uarts =
<&usart1>;
};
};

&timers8 {
status = "okay";
pwm8: pwm {
status = "okay";
pinctrl-0 = <&tim8_ch3_pc8 &tim8_ch4_pc9>;
pinctrl-0 = <&tim8_ch3_pc8 &tim8_ch4_pc9 &tim8_ch1_pc6 &tim8_ch2_pc7>;
pinctrl-names =
"default";
};
Expand Down
64 changes: 58 additions & 6 deletions src/Debug/debugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endif

#include "../Memory/mem.h"
#include "../Primitives/primitives.h"
#include "../Utils//util.h"
#include "../Utils/macros.h"
#include "../WARDuino/CallbackHandler.h"
Expand Down Expand Up @@ -714,11 +715,18 @@ bool Debugger::handlePushedEvent(char *bytes) const {
}

void Debugger::snapshot(Module *m) {
uint16_t numberBytes = 10;
uint8_t state[] = {
pcState, breakpointsState, callstackState, globalsState,
tableState, memoryState, branchingTableState, stackState,
callbacksState, eventsState};
uint16_t numberBytes = 11;
uint8_t state[] = {pcState,
breakpointsState,
callstackState,
globalsState,
tableState,
memoryState,
branchingTableState,
stackState,
callbacksState,
eventsState,
ioState};
inspect(m, numberBytes, state);
}

Expand Down Expand Up @@ -843,6 +851,26 @@ void Debugger::inspect(Module *m, uint16_t sizeStateArray, uint8_t *state) {
addComma = true;
break;
}
case ioState: {
this->channel->write("%s", addComma ? "," : "");
this->channel->write("\"io\": [");
bool comma = false;
std::vector<IOStateElement *> external_state = get_io_state(m);
for (auto state_elem : external_state) {
this->channel->write("%s{", comma ? ", " : "");
this->channel->write(
R"("key": "%s", "output": %s, "value": %d)",
state_elem->key.c_str(),
state_elem->output ? "true" : "false",
state_elem->value);
this->channel->write("}");
comma = true;
delete state_elem;
}
this->channel->write("]");
addComma = true;
break;
}
default: {
debug("dumpExecutionState: Received unknown state request\n");
break;
Expand Down Expand Up @@ -953,7 +981,8 @@ bool Debugger::saveState(Module *m, uint8_t *interruptData) {
uint8_t *program_state = nullptr;
uint8_t *end_state = nullptr;
program_state = interruptData + 1; // skip interruptLoadSnapshot
end_state = program_state + read_B32(&program_state);
uint32_t len = read_B32(&program_state);
end_state = program_state + len;

debug("saving program_state\n");
while (program_state < end_state) {
Expand Down Expand Up @@ -1169,6 +1198,29 @@ bool Debugger::saveState(Module *m, uint8_t *interruptData) {
}
break;
}
case ioState: {
debug("receiving ioState\n");
uint8_t io_state_count = *program_state++;
std::vector<IOStateElement> external_state;
external_state.reserve(io_state_count);
for (int i = 0; i < io_state_count; i++) {
IOStateElement state_elem;
state_elem.key = "";
char c = (char)*program_state++;
while (c != '\0') {
state_elem.key += c;
c = (char)*program_state++;
}
state_elem.output = *program_state++;
state_elem.value = (int)read_B32(&program_state);
external_state.emplace_back(state_elem);
debug("pin %s(%s) = %d\n", state_elem.key.c_str(),
state_elem.output ? "output" : "input",
state_elem.value);
}
restore_external_state(m, external_state);
break;
}
default: {
FATAL("saveState: Received unknown program state\n");
}
Expand Down
3 changes: 2 additions & 1 deletion src/Debug/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ enum ExecutionState {
branchingTableState = 0x07,
stackState = 0x08,
callbacksState = 0x09,
eventsState = 0x0A
eventsState = 0x0A,
ioState = 0x0B,
};

enum InterruptTypes {
Expand Down
89 changes: 89 additions & 0 deletions src/Primitives/arduino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,32 @@ int prim_index = 0;
PrimitiveEntry *p = &primitives[prim_index++]; \
p->name = #prim_name; \
p->f = &(prim_name); \
p->f_reverse = nullptr; \
p->f_serialize_state = nullptr; \
} else { \
FATAL("pim_index out of bounds"); \
} \
}

#define install_primitive_reverse(prim_name) \
{ \
PrimitiveEntry *p = &primitives[prim_index - 1]; \
p->f_reverse = &(prim_name##_reverse); \
p->f_serialize_state = &(prim_name##_serialize); \
}

#define def_prim(function_name, type) \
Type function_name##_type = type; \
bool function_name(Module *m)

#define def_prim_reverse(function_name) \
void function_name##_reverse(Module *m, \
std::vector<IOStateElement> external_state)

#define def_prim_serialize(function_name) \
void function_name##_serialize( \
std::vector<IOStateElement *> &external_state)

// TODO: use fp
#define pop_args(n) m->sp -= n
#define get_arg(m, arg) m->stack[(m)->sp - (arg)].value
Expand Down Expand Up @@ -491,6 +508,36 @@ def_prim(chip_digital_write, twoToNoneU32) {
return true;
}

def_prim_reverse(chip_digital_write) {
for (IOStateElement state : external_state) {
if (!state.output) {
continue;
}

if (state.key[0] == 'p') {
invoke_primitive(m, "chip_digital_write", stoi(state.key.substr(1)),
(uint32_t)state.value);
}
}
}

def_prim_serialize(chip_digital_write) {
for (int i = 0; i < NUM_DIGITAL_PINS; i++) {
uint32_t bit_mask = digitalPinToBitMask(i);
auto *state = new IOStateElement();
state->key = "p" + std::to_string(i);
uint8_t port = digitalPinToPort(i);
if (*portModeRegister(port) & bit_mask) { // DDR
state->output = true;
state->value = (*portOutputRegister(port) & bit_mask) > 0;
} else {
state->output = false;
state->value = (*portInputRegister(port) & bit_mask) > 0;
}
external_state.push_back(state);
}
}

def_prim(chip_delay, oneToNoneU32) {
delay(arg0.uint32);
pop_args(1);
Expand Down Expand Up @@ -954,6 +1001,7 @@ void install_primitives() {

install_primitive(chip_pin_mode);
install_primitive(chip_digital_write);
install_primitive_reverse(chip_digital_write);
install_primitive(chip_delay);
install_primitive(chip_digital_read);
install_primitive(chip_analog_read);
Expand Down Expand Up @@ -1026,3 +1074,44 @@ bool resolve_external_memory(char *symbol, Memory **val) {
FATAL("Could not find memory %s \n", symbol);
return false;
}

//------------------------------------------------------
// Restore external state when restoring a snapshot
//------------------------------------------------------
void restore_external_state(Module *m,
std::vector<IOStateElement> external_state) {
uint8_t opcode = *m->pc_ptr;
// TODO: Maybe primitives can also be called using the other call
// instructions such as call_indirect
// maybe there should just be a function that checks if a certain function
// is being called that handles all these cases?
if (opcode == 0x10) { // call opcode
uint8_t *pc_copy = m->pc_ptr + 1;
uint32_t fidx = read_LEB_32(&pc_copy);
if (fidx < m->import_count) {
for (auto &primitive : primitives) {
if (!strcmp(primitive.name, m->functions[fidx].import_field)) {
if (primitive.f_reverse) {
debug("Reversing action for primitive %s\n",
primitive.name);
primitive.f_reverse(m, external_state);
}
return;
}
}
}
}
}

//------------------------------------------------------
// Serialize external state into a snapshot
//------------------------------------------------------
std::vector<IOStateElement *> get_io_state(Module *m) {
std::vector<IOStateElement *> ioState;
for (auto &primitive : primitives) {
if (primitive.f_serialize_state) {
primitive.f_serialize_state(ioState);
}
}
return ioState;
}
55 changes: 55 additions & 0 deletions src/Primitives/emulated.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,32 @@ double sensor_emu = 0;
PrimitiveEntry *p = &primitives[prim_index++]; \
p->name = #prim_name; \
p->f = &(prim_name); \
p->f_reverse = nullptr; \
p->f_serialize_state = nullptr; \
} else { \
FATAL("pim_index out of bounds"); \
} \
}

#define install_primitive_reverse(prim_name) \
{ \
PrimitiveEntry *p = &primitives[prim_index - 1]; \
p->f_reverse = &(prim_name##_reverse); \
p->f_serialize_state = &(prim_name##_serialize); \
}

#define def_prim(function_name, type) \
Type function_name##_type = type; \
bool function_name(Module *m)

#define def_prim_reverse(function_name) \
void function_name##_reverse(Module *m, \
std::vector<IOStateElement> external_state)

#define def_prim_serialize(function_name) \
void function_name##_serialize( \
std::vector<IOStateElement *> &external_state)

// TODO: use fp
#define pop_args(n) m->sp -= n
#define get_arg(m, arg) m->stack[(m)->sp - (arg)].value
Expand Down Expand Up @@ -572,4 +589,42 @@ bool resolve_external_memory(char *symbol, Memory **val) {
return false;
}

//------------------------------------------------------
// Restore external state when restoring a snapshot
//------------------------------------------------------
void restore_external_state(Module *m,
std::vector<IOStateElement> external_state) {
uint8_t opcode = *m->pc_ptr;
// TODO: Maybe primitives can also be called using the other call
// instructions such as call_indirect
// maybe there should just be a function that checks if a certain function
// is being called that handles all these cases?
if (opcode == 0x10) { // call opcode
uint8_t *pc_copy = m->pc_ptr + 1;
uint32_t fidx = read_LEB_32(&pc_copy);
if (fidx < m->import_count) {
for (auto &primitive : primitives) {
if (!strcmp(primitive.name, m->functions[fidx].import_field)) {
if (primitive.f_reverse) {
debug("Reversing action for primitive %s\n",
primitive.name);
primitive.f_reverse(m, external_state);
}
return;
}
}
}
}
}

std::vector<IOStateElement *> get_io_state(Module *m) {
std::vector<IOStateElement *> ioState;
for (auto &primitive : primitives) {
if (primitive.f_serialize_state) {
primitive.f_serialize_state(ioState);
}
}
return ioState;
}

#endif // ARDUINO
Loading