diff options
Diffstat (limited to 'lib/pbdrv/drv')
-rw-r--r-- | lib/pbdrv/drv/arduino/include.cmake | 2 | ||||
-rw-r--r-- | lib/pbdrv/drv/arduino/index.dox | 22 | ||||
-rw-r--r-- | lib/pbdrv/drv/arduino/mod.cpp | 19 | ||||
-rw-r--r-- | lib/pbdrv/drv/index.dox | 13 | ||||
-rw-r--r-- | lib/pbdrv/drv/rp2040/include.cmake | 11 | ||||
-rw-r--r-- | lib/pbdrv/drv/rp2040/index.dox | 31 | ||||
-rw-r--r-- | lib/pbdrv/drv/rp2040/mod.c | 49 | ||||
-rw-r--r-- | lib/pbdrv/drv/rp2040/pb-mod.h | 21 |
8 files changed, 141 insertions, 27 deletions
diff --git a/lib/pbdrv/drv/arduino/include.cmake b/lib/pbdrv/drv/arduino/include.cmake index 1e2ff08..5ec1124 100644 --- a/lib/pbdrv/drv/arduino/include.cmake +++ b/lib/pbdrv/drv/arduino/include.cmake @@ -3,7 +3,7 @@ if(NOT DEFINED ARDUINO) endif() target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.cpp") -target_link_arduino_libraries(pbdrv-mod core Wire) +target_link_arduino_libraries(pbdrv-mod PRIVATE core Wire) # freertos is used to defer the handling of i2c messages outside the receive # interrupt service routine diff --git a/lib/pbdrv/drv/arduino/index.dox b/lib/pbdrv/drv/arduino/index.dox index 4c74222..03510dd 100644 --- a/lib/pbdrv/drv/arduino/index.dox +++ b/lib/pbdrv/drv/arduino/index.dox @@ -2,18 +2,24 @@ /** \ingroup pb_drv \defgroup pb_drv_arduino Arduino -\brief Arduino (Arduino-CMake-Toolchain) driver - -This driver is automatically enabled if the variable \c ARDUINO is defined in -your CMakeLists.txt (it is by default when using Arduino-CMake-Toolchain). - -\note This driver automatically includes the -\ref pb_ext_freertos "FreeRTOS extension" for deferring calls to \c -pb_i2c_recv() from the I2C ISR. +\brief Arduino ATmega (w/ Arduino-CMake-Toolchain) driver This driver is known to work with the following MCUs: - ATmega328P (Arduino Uno) - ATmega2560 (Arduino Mega) +\par Usage +- Link the \c pbdrv-mod library with your main executable + +\note This driver is automatically enabled if the variable \c ARDUINO is +defined in your CMakeLists.txt (it is by default when using +Arduino-CMake-Toolchain). + +\note This driver automatically includes the \ref pb_ext_freertos +"FreeRTOS extension" for deferring calls to \c pb_i2c_recv() from the I2C ISR. + +A complete example for this driver is available in the \ref puzzle/dummy +folder. + */ diff --git a/lib/pbdrv/drv/arduino/mod.cpp b/lib/pbdrv/drv/arduino/mod.cpp index 2eef8d5..c381077 100644 --- a/lib/pbdrv/drv/arduino/mod.cpp +++ b/lib/pbdrv/drv/arduino/mod.cpp @@ -1,7 +1,3 @@ -#ifndef ARDUINO -#error This driver only works on the Arduino platform! -#endif - #include <Arduino.h> #include <Wire.h> #include <avr/delay.h> @@ -42,8 +38,17 @@ static void pb_setup() { Wire.onReceive(recv_event); } -/// \ingroup pb_drv_arduino +/** + * \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); @@ -69,6 +74,10 @@ void loop_task() { * \ingroup pb_drv_arduino * \brief Application entrypoint * + * This function overrides the default (weak) implementation of the \c main() + * function in the Arduino framework. No additional setup is required to use + * this driver. + * * \note I should really be able to use Arduino's initVariant function for * this, but I can't seem to get it to link properly using the CMake setup in * this repository. Overriding the main() function seems to work, and the diff --git a/lib/pbdrv/drv/index.dox b/lib/pbdrv/drv/index.dox index 1fe09e2..89b9247 100644 --- a/lib/pbdrv/drv/index.dox +++ b/lib/pbdrv/drv/index.dox @@ -7,19 +7,6 @@ Like \ref pb_ext "extensions", drivers provide platform-specific implementations for various functions used in \ref pbdrv-mod. -Drivers are automatically included based on your build configuration, and you -only need to ensure \c pbdrv-mod is linked with your final executable in order -to use one of the available drivers: - -```cmake -# include pbdrv -add_subdirectory(lib/pbdrv) - -# link pbdrv-mod -target_link_libraries(main pbdrv-mod) - -``` - If there is no existing driver for your target, you may implement the following in order to use \ref pbdrv-mod: diff --git a/lib/pbdrv/drv/rp2040/include.cmake b/lib/pbdrv/drv/rp2040/include.cmake new file mode 100644 index 0000000..6d25e96 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/include.cmake @@ -0,0 +1,11 @@ +if(NOT PICO_PLATFORM STREQUAL "rp2040") + return() +endif() + +target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/mod.c") +target_link_libraries(pbdrv-mod PRIVATE hardware_i2c_headers pico_i2c_slave_headers) +target_include_directories(pbdrv-mod INTERFACE "${CMAKE_CURRENT_LIST_DIR}") + +# pico-stdlib is compatible with C stdlib +include("${CMAKE_CURRENT_LIST_DIR}/../../ext/stdlib/include.cmake") + diff --git a/lib/pbdrv/drv/rp2040/index.dox b/lib/pbdrv/drv/rp2040/index.dox new file mode 100644 index 0000000..eb01d15 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/index.dox @@ -0,0 +1,31 @@ +// vim:ft=doxygen +/** +\ingroup pb_drv +\defgroup pb_drv_rp2040 RP2040 +\brief Raspberry Pi Pico and Pico W driver + +This driver is known to work with the following MCUs: +- Raspberry Pi Pico W + +\note While the RP2040's datasheet claims it supports multi-master +configurations by implementing bus arbitration, it does not natively support +a mode where it is configured as a (multi-)master with a slave address, such +that it can be addressed by other multi-masters. + +\note This driver includes a workaround that uses both I2C peripherals on the +RP2040. To use this driver, make sure you initialize both I2C peripherals, and +connect their respective SDA and SCL pins to the same I2C bus. + +\par Usage +- Link the \c pbdrv-mod library with your main executable +- Call the \c pb_setup() function (from \c <pb-mod.h>) during setup + +\note This driver is automatically enabled if the variable \c PICO_PLATFORM is +equal to \c "rp2040" in your CMakeLists.txt (it is by default when using the +pico-sdk CMake library). + +\note This driver automatically includes the \ref pb_ext_stdlib +"stdlib extension" as the pico-sdk implements the C standard library. + +*/ + diff --git a/lib/pbdrv/drv/rp2040/mod.c b/lib/pbdrv/drv/rp2040/mod.c new file mode 100644 index 0000000..1535da9 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/mod.c @@ -0,0 +1,49 @@ +#include "pb.h" + +#include "pb.h" +#include "pb-types.h" +#include "pb-mod.h" +#include "pb-send.h" +#include "pb-buf.h" + +#include <hardware/i2c.h> +#include <hardware/gpio.h> +#include <pico/i2c_slave.h> + +#define PB_I2C_S i2c0 +#define PB_I2C_M i2c1 + +#define BUF_SIZE 256 + +uint8_t i2c_msg_buf[BUF_SIZE]; +size_t i2c_msg_buf_sz = 0; + +// This function is called from the I2C ISR +static void recv_event(i2c_inst_t *i2c, i2c_slave_event_t event) { + switch (event) { + case I2C_SLAVE_RECEIVE: { + if (i2c_msg_buf_sz == BUF_SIZE) return; + i2c_msg_buf[i2c_msg_buf_sz++] = i2c_read_byte_raw(PB_I2C_S); + break; + } + case I2C_SLAVE_FINISH: { + pb_i2c_recv(i2c_msg_buf, i2c_msg_buf_sz); + i2c_msg_buf_sz = 0; + break; + } + default: break; + } +} + +void pb_setup() { + i2c_init(PB_I2C_S, PB_CLOCK_SPEED_HZ); + i2c_init(PB_I2C_M, PB_CLOCK_SPEED_HZ); + + i2c_slave_init(PB_I2C_S, PB_MOD_ADDR, &recv_event); +} + +__weak void pb_i2c_send(i2c_addr_t addr, const uint8_t * buf, size_t sz) { + // false to write stop condition to i2c bus + i2c_write_timeout_us(PB_I2C_M, addr, buf, sz, false, PB_TIMEOUT_US); +} + diff --git a/lib/pbdrv/drv/rp2040/pb-mod.h b/lib/pbdrv/drv/rp2040/pb-mod.h new file mode 100644 index 0000000..96edc70 --- /dev/null +++ b/lib/pbdrv/drv/rp2040/pb-mod.h @@ -0,0 +1,21 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \ingroup pb_drv_rp2040 + * \brief Puzzle bus driver setup + * + * This function must be called from a setup/init function to initialize the + * I2C peripherals used by this driver. + */ +void pb_setup(); + +#ifdef __cplusplus +} +#endif + +#include "../../pb-mod.h" + |