diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pbdrv/CMakeLists.txt | 6 | ||||
-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 | ||||
-rw-r--r-- | lib/pbdrv/ext/freertos/include.cmake | 4 | ||||
-rw-r--r-- | lib/pbdrv/ext/freertos/index.dox | 2 | ||||
-rw-r--r-- | lib/pbdrv/ext/freertos/pb-mod.c | 10 | ||||
-rw-r--r-- | lib/pbdrv/index.dox | 13 | ||||
-rw-r--r-- | lib/pbdrv/pb-mod.h | 8 | ||||
-rw-r--r-- | lib/pbdrv/pb-route.c | 3 | ||||
-rw-r--r-- | lib/pbdrv/pb-types.h | 6 |
16 files changed, 157 insertions, 63 deletions
diff --git a/lib/pbdrv/CMakeLists.txt b/lib/pbdrv/CMakeLists.txt index 998ed4d..903a3b4 100644 --- a/lib/pbdrv/CMakeLists.txt +++ b/lib/pbdrv/CMakeLists.txt @@ -23,7 +23,7 @@ add_library(pbdrv STATIC pb-buf.c ) target_include_directories(pbdrv SYSTEM INTERFACE .) -target_link_libraries(pbdrv mpack) +target_link_libraries(pbdrv PRIVATE mpack) # puzzle bus *module* specific code add_library(pbdrv-mod OBJECT @@ -32,9 +32,9 @@ add_library(pbdrv-mod OBJECT pb-route.c ) target_include_directories(pbdrv-mod SYSTEM INTERFACE .) -target_link_libraries(pbdrv-mod pbdrv) +target_link_libraries(pbdrv-mod PUBLIC pbdrv) # puzzle bus drivers include(drv/arduino/include.cmake) -# include(drv/rp2040/include.cmake) # please see /main/pbdrv.h +include(drv/rp2040/include.cmake) 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" + diff --git a/lib/pbdrv/ext/freertos/include.cmake b/lib/pbdrv/ext/freertos/include.cmake index e7ab7fd..e205c8f 100644 --- a/lib/pbdrv/ext/freertos/include.cmake +++ b/lib/pbdrv/ext/freertos/include.cmake @@ -1,9 +1,7 @@ target_sources(pbdrv PRIVATE "${CMAKE_CURRENT_LIST_DIR}/pb-mem.c") -target_link_libraries(pbdrv +target_link_libraries(pbdrv PUBLIC freertos_kernel freertos_kernel_include freertos_config ) -target_sources(pbdrv-mod PRIVATE "${CMAKE_CURRENT_LIST_DIR}/pb-mod.c") - diff --git a/lib/pbdrv/ext/freertos/index.dox b/lib/pbdrv/ext/freertos/index.dox index dfa45ff..7d72918 100644 --- a/lib/pbdrv/ext/freertos/index.dox +++ b/lib/pbdrv/ext/freertos/index.dox @@ -2,5 +2,5 @@ /** \ingroup pb_ext \defgroup pb_ext_freertos FreeRTOS -\brief FreeRTOS memory management and scheduler-based delay +\brief FreeRTOS memory management */ diff --git a/lib/pbdrv/ext/freertos/pb-mod.c b/lib/pbdrv/ext/freertos/pb-mod.c deleted file mode 100644 index 5c0aa36..0000000 --- a/lib/pbdrv/ext/freertos/pb-mod.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <FreeRTOS.h> -#include <task.h> - -#include "../../pb-types.h" - -/// \ingroup pb_ext_freertos -__weak void pb_mod_blocking_delay_ms(unsigned long ms) { - vTaskDelay(ms / portTICK_PERIOD_MS); -} - diff --git a/lib/pbdrv/index.dox b/lib/pbdrv/index.dox index eb0fd63..8ddcb6a 100644 --- a/lib/pbdrv/index.dox +++ b/lib/pbdrv/index.dox @@ -11,8 +11,9 @@ themselves. For a complete puzzle module driver, please see \ref pbdrv-mod. If you order to use \ref pbdrv, you need to include this folder in your CMakeLists.txt file, include the \ref pb_ext "extension" for your target -platform, and link the \c pbdrv library with your executable: +platform, and link the \c pbdrv library with your executable. +\par Example ```cmake # include pbdrv add_subdirectory(lib/pbdrv) @@ -35,14 +36,10 @@ using an existing \ref pb_drv "driver", or (partially) implementing the driver functions. Like \ref pbdrv, \ref pbdrv-mod can be used by including this folder in your -CMakeLists.txt file and linking the library with your executable. A notable -difference with \ref pbdrv-mod is that you do not need to include an extension. -\ref pb_ext "Extensions" are still used by \ref pbdrv-mod, but they are -included automatically by the target platform's \ref pb_drv "driver". The -appropriate \ref pb_drv "driver" to load is also automatically detected. - -Example: +CMakeLists.txt file and linking the library with your executable. Please see +the \ref pb_drv "drivers" page for target-specific usage instructions. +\par Example ```cmake # include pbdrv add_subdirectory(lib/pbdrv) diff --git a/lib/pbdrv/pb-mod.h b/lib/pbdrv/pb-mod.h index 3869e55..91e1d1f 100644 --- a/lib/pbdrv/pb-mod.h +++ b/lib/pbdrv/pb-mod.h @@ -24,14 +24,6 @@ extern const char * PB_MOD_NAME; */ extern const i2c_addr_t PB_MOD_ADDR; -/** - * \brief Platform-specific blocking delay function - * - * FIXME: this entire function should be removed (see handover: RP2040 I2C - * limitations) - */ -void pb_mod_blocking_delay_ms(unsigned long ms); - /// \} /** diff --git a/lib/pbdrv/pb-route.c b/lib/pbdrv/pb-route.c index f5c32d6..5a7bd67 100644 --- a/lib/pbdrv/pb-route.c +++ b/lib/pbdrv/pb-route.c @@ -93,9 +93,6 @@ __weak void pb_route_cmd_magic_req(pb_msg_t * msg) { // // return early if magic doesn't match if (pb_memcmp(cmd->magic, pb_cmd_magic_req, sizeof(pb_cmd_magic_req)) != 0) return; - // FIXME: this should be removed (see handover: RP2040 I2C limitations) - pb_mod_blocking_delay_ms(2000); - pb_buf_t buf = pb_send_magic_res(); pb_send_reply(msg, &buf); pb_buf_free(&buf); diff --git a/lib/pbdrv/pb-types.h b/lib/pbdrv/pb-types.h index ef3df54..44b590b 100644 --- a/lib/pbdrv/pb-types.h +++ b/lib/pbdrv/pb-types.h @@ -131,6 +131,12 @@ typedef struct { pb_global_state_t state; //!< global state } pb_cmd_state_t; +//! PB_MOD_STATE data +typedef struct { + i2c_addr_t sender; //!< i2c address of sender + pb_global_state_t state; //!< global state +} pb_puzzle_module_t; + //! \ref PB_CMD_MAGIC data typedef struct { char * magic; //!< magic value |