diff options
Diffstat (limited to 'lib/pbdrv/drv/arduino/mod.cpp')
-rw-r--r-- | lib/pbdrv/drv/arduino/mod.cpp | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index d2a6402..c381077 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -1,22 +1,33 @@ -#ifndef ARDUINO -#error This driver only works on the Arduino platform! -#endif - #include <Arduino.h> #include <Wire.h> #include <avr/delay.h> +#include <FreeRTOS.h> +#include <timers.h> +#include <task.h> + #include "../../pb.h" #include "../../pb-mod.h" #include "../../pb-types.h" +#include "../../pb-buf.h" +#include "../../pb-mem.h" + +static void async_pb_i2c_recv(void * _msg, uint32_t _) { + pb_buf_t * msg = (pb_buf_t *) _msg; + pb_i2c_recv((uint8_t *) msg->data, msg->size); + pb_buf_free(msg); + pb_free(msg); +} static void recv_event(int bytes) { - uint8_t data[bytes]; - size_t sz = 0; + pb_buf_t * msg = (pb_buf_t *) pb_malloc(sizeof(pb_buf_t)); + msg->data = (char *) pb_malloc(bytes); + msg->size = 0; while (Wire.available()) - data[sz++] = Wire.read(); + msg->data[msg->size++] = Wire.read(); - pb_i2c_recv(data, sz); + // defer pb_i2c_recv call + xTimerPendFunctionCallFromISR(async_pb_i2c_recv, msg, 0, NULL); } static void pb_setup() { @@ -27,7 +38,17 @@ static void pb_setup() { Wire.onReceive(recv_event); } +/** + * \ingroup pb_drv_arduino + * \warning This function includes a hard-coded 10ms delay before sending. This + * is to work around a weird issue where the Arduino pulls both SDA and SCL low + * while attempting to initiate an I2C transmission. We were able to verify + * that the Arduino correctly handles bus arbitration under a test scenario + * with 2 Uno's, but ran into issues while integrating the Arduino's with the + * RP2040. + */ __weak void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { + vTaskDelay(10 / portTICK_PERIOD_MS); // prevent bus collisions Wire.beginTransmission((int) addr); Wire.write(buf, sz); Wire.endTransmission(true); @@ -41,6 +62,14 @@ extern void loop(void); //! Arduino internal initialization void init(void); +//! FreeRTOS loop task +void loop_task() { + for(;;) { + loop(); + if (serialEventRun) serialEventRun(); + } +} + /** * \ingroup pb_drv_arduino * \brief Application entrypoint @@ -59,10 +88,8 @@ int main(void) { init(); // call arduino internal setup setup(); // call regular arduino setup pb_setup(); // call pbdrv-mod setup - for(;;) { - loop(); - if (serialEventRun) serialEventRun(); - } + xTaskCreate((TaskFunction_t) loop_task, "loop", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); + vTaskStartScheduler(); // start freertos scheduler return 0; } |