add new pcio_I2c_slave library (#1205)
* add (slightly modified) pico_i2c_slave library from https://github.com/vmilea/pico_i2c_slave * introduce VTABLE_FIRST_IRQ constant
This commit is contained in:
		@ -43,6 +43,7 @@
 | 
				
			|||||||
 * @{
 | 
					 * @{
 | 
				
			||||||
 * \defgroup pico_async_context pico_async_context
 | 
					 * \defgroup pico_async_context pico_async_context
 | 
				
			||||||
 * \defgroup pico_multicore pico_multicore
 | 
					 * \defgroup pico_multicore pico_multicore
 | 
				
			||||||
 | 
					 * \defgroup pico_i2c_slave pico_i2c_slave
 | 
				
			||||||
 * \defgroup pico_rand pico_rand
 | 
					 * \defgroup pico_rand pico_rand
 | 
				
			||||||
 * \defgroup pico_stdlib pico_stdlib
 | 
					 * \defgroup pico_stdlib pico_stdlib
 | 
				
			||||||
 * \defgroup pico_sync pico_sync
 | 
					 * \defgroup pico_sync pico_sync
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,7 @@
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
 | 
					#define FIRST_USER_IRQ (NUM_IRQS - NUM_USER_IRQS)
 | 
				
			||||||
 | 
					#define VTABLE_FIRST_IRQ 16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -59,6 +59,8 @@ if (NOT PICO_BARE_METAL)
 | 
				
			|||||||
    pico_add_subdirectory(tinyusb)
 | 
					    pico_add_subdirectory(tinyusb)
 | 
				
			||||||
    pico_add_subdirectory(pico_stdio_usb)
 | 
					    pico_add_subdirectory(pico_stdio_usb)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pico_add_subdirectory(pico_i2c_slave)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pico_add_subdirectory(pico_async_context)
 | 
					    pico_add_subdirectory(pico_async_context)
 | 
				
			||||||
    pico_add_subdirectory(pico_cyw43_driver)
 | 
					    pico_add_subdirectory(pico_cyw43_driver)
 | 
				
			||||||
    pico_add_subdirectory(pico_lwip)
 | 
					    pico_add_subdirectory(pico_lwip)
 | 
				
			||||||
 | 
				
			|||||||
@ -153,6 +153,12 @@ static inline i2c_hw_t *i2c_get_hw(i2c_inst_t *i2c) {
 | 
				
			|||||||
    return i2c->hw;
 | 
					    return i2c->hw;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline i2c_inst_t *i2c_get_instance(uint instance) {
 | 
				
			||||||
 | 
					    static_assert(NUM_I2CS == 2, "");
 | 
				
			||||||
 | 
					    invalid_params_if(I2C, instance >= NUM_I2CS);
 | 
				
			||||||
 | 
					    return instance ? i2c1 : i2c0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Attempt to write specified number of bytes to address, blocking until the specified absolute time is reached.
 | 
					/*! \brief Attempt to write specified number of bytes to address, blocking until the specified absolute time is reached.
 | 
				
			||||||
 *  \ingroup hardware_i2c
 | 
					 *  \ingroup hardware_i2c
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
@ -312,6 +318,37 @@ static inline void i2c_read_raw_blocking(i2c_inst_t *i2c, uint8_t *dst, size_t l
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Pop a byte from I2C Rx FIFO.
 | 
				
			||||||
 | 
					 * \ingroup hardware_i2c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function is non-blocking and assumes the Rx FIFO isn't empty.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param i2c I2C instance.
 | 
				
			||||||
 | 
					 * \return uint8_t Byte value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline uint8_t i2c_read_byte_raw(i2c_inst_t *i2c) {
 | 
				
			||||||
 | 
					    i2c_hw_t *hw = i2c_get_hw(i2c);
 | 
				
			||||||
 | 
					    assert(hw->status & I2C_IC_STATUS_RFNE_BITS); // Rx FIFO must not be empty
 | 
				
			||||||
 | 
					    return (uint8_t)hw->data_cmd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Push a byte into I2C Tx FIFO.
 | 
				
			||||||
 | 
					 * \ingroup hardware_i2c
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This function is non-blocking and assumes the Tx FIFO isn't full.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param i2c I2C instance.
 | 
				
			||||||
 | 
					 * \param value Byte value.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void i2c_write_byte_raw(i2c_inst_t *i2c, uint8_t value) {
 | 
				
			||||||
 | 
					    i2c_hw_t *hw = i2c_get_hw(i2c);
 | 
				
			||||||
 | 
					    assert(hw->status & I2C_IC_STATUS_TFNF_BITS); // Tx FIFO must not be full
 | 
				
			||||||
 | 
					    hw->data_cmd = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*! \brief Return the DREQ to use for pacing transfers to/from a particular I2C instance
 | 
					/*! \brief Return the DREQ to use for pacing transfers to/from a particular I2C instance
 | 
				
			||||||
 *  \ingroup hardware_i2c
 | 
					 *  \ingroup hardware_i2c
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ static inline void *remove_thumb_bit(void *addr) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void set_raw_irq_handler_and_unlock(uint num, irq_handler_t handler, uint32_t save) {
 | 
					static void set_raw_irq_handler_and_unlock(uint num, irq_handler_t handler, uint32_t save) {
 | 
				
			||||||
    // update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
 | 
					    // update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
 | 
				
			||||||
    get_vtable()[16 + num] = handler;
 | 
					    get_vtable()[VTABLE_FIRST_IRQ + num] = handler;
 | 
				
			||||||
    __dmb();
 | 
					    __dmb();
 | 
				
			||||||
    spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save);
 | 
					    spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_IRQ), save);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -306,7 +306,7 @@ void irq_remove_handler(uint num, irq_handler_t handler) {
 | 
				
			|||||||
            // Sadly this is not something we can detect.
 | 
					            // Sadly this is not something we can detect.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            uint exception = __get_current_exception();
 | 
					            uint exception = __get_current_exception();
 | 
				
			||||||
            hard_assert(!exception || exception == num + 16);
 | 
					            hard_assert(!exception || exception == num + VTABLE_FIRST_IRQ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            struct irq_handler_chain_slot *prev_slot = NULL;
 | 
					            struct irq_handler_chain_slot *prev_slot = NULL;
 | 
				
			||||||
            struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
 | 
					            struct irq_handler_chain_slot *existing_vtable_slot = remove_thumb_bit(vtable_handler);
 | 
				
			||||||
 | 
				
			|||||||
@ -112,7 +112,7 @@ static inline uint harware_alarm_irq_number(uint alarm_num) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void hardware_alarm_irq_handler(void) {
 | 
					static void hardware_alarm_irq_handler(void) {
 | 
				
			||||||
    // Determine which timer this IRQ is for
 | 
					    // Determine which timer this IRQ is for
 | 
				
			||||||
    uint alarm_num = __get_current_exception() - 16 - TIMER_IRQ_0;
 | 
					    uint alarm_num = __get_current_exception() - VTABLE_FIRST_IRQ - TIMER_IRQ_0;
 | 
				
			||||||
    check_hardware_alarm_num_param(alarm_num);
 | 
					    check_hardware_alarm_num_param(alarm_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hardware_alarm_callback_t callback = NULL;
 | 
					    hardware_alarm_callback_t callback = NULL;
 | 
				
			||||||
 | 
				
			|||||||
@ -280,7 +280,7 @@ static void process_under_lock(async_context_threadsafe_background_t *self) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Low priority interrupt handler to perform background processing
 | 
					// Low priority interrupt handler to perform background processing
 | 
				
			||||||
static void low_priority_irq_handler(void) {
 | 
					static void low_priority_irq_handler(void) {
 | 
				
			||||||
    uint index = __get_current_exception() - 16 - FIRST_USER_IRQ;
 | 
					    uint index = __get_current_exception() - VTABLE_FIRST_IRQ - FIRST_USER_IRQ;
 | 
				
			||||||
    assert(index < count_of(async_contexts_by_user_irq));
 | 
					    assert(index < count_of(async_contexts_by_user_irq));
 | 
				
			||||||
    async_context_threadsafe_background_t *self = async_contexts_by_user_irq[index];
 | 
					    async_context_threadsafe_background_t *self = async_contexts_by_user_irq[index];
 | 
				
			||||||
    if (!self) return;
 | 
					    if (!self) return;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/rp2_common/pico_i2c_slave/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/rp2_common/pico_i2c_slave/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					if (NOT TARGET pico_i2c_slave)
 | 
				
			||||||
 | 
					    pico_add_library(pico_i2c_slave)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    target_sources(pico_i2c_slave INTERFACE
 | 
				
			||||||
 | 
					            ${CMAKE_CURRENT_LIST_DIR}/i2c_slave.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    target_include_directories(pico_i2c_slave_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pico_mirrored_target_link_libraries(pico_i2c_slave INTERFACE hardware_i2c hardware_irq)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
							
								
								
									
										103
									
								
								src/rp2_common/pico_i2c_slave/i2c_slave.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/rp2_common/pico_i2c_slave/i2c_slave.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2021 Valentin Milea <valentin.milea@gmail.com>
 | 
				
			||||||
 | 
					 * Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "pico/i2c_slave.h"
 | 
				
			||||||
 | 
					#include "hardware/irq.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct i2c_slave {
 | 
				
			||||||
 | 
					    i2c_slave_handler_t handler;
 | 
				
			||||||
 | 
					    bool transfer_in_progress;
 | 
				
			||||||
 | 
					} i2c_slave_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static i2c_slave_t i2c_slaves[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline i2c_inst_t *get_hw_instance(const i2c_slave_t *slave) {
 | 
				
			||||||
 | 
					    return i2c_get_instance(slave - i2c_slaves);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __isr __not_in_flash_func(i2c_slave_irq_handler)(void) {
 | 
				
			||||||
 | 
					    uint i2c_index = __get_current_exception() - VTABLE_FIRST_IRQ - I2C0_IRQ;
 | 
				
			||||||
 | 
					    i2c_slave_t *slave = &i2c_slaves[i2c_index];
 | 
				
			||||||
 | 
					    i2c_inst_t *i2c = i2c_get_instance(i2c_index);
 | 
				
			||||||
 | 
					    i2c_hw_t *hw = i2c_get_hw(i2c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t intr_stat = hw->intr_stat;
 | 
				
			||||||
 | 
					    if (intr_stat == 0) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    bool do_finish_transfer = false;
 | 
				
			||||||
 | 
					    if (intr_stat & I2C_IC_INTR_STAT_R_TX_ABRT_BITS) {
 | 
				
			||||||
 | 
					        hw->clr_tx_abrt;
 | 
				
			||||||
 | 
					        do_finish_transfer = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (intr_stat & I2C_IC_INTR_STAT_R_START_DET_BITS) {
 | 
				
			||||||
 | 
					        hw->clr_start_det;
 | 
				
			||||||
 | 
					        do_finish_transfer = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) {
 | 
				
			||||||
 | 
					        hw->clr_stop_det;
 | 
				
			||||||
 | 
					        do_finish_transfer = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (do_finish_transfer && slave->transfer_in_progress) {
 | 
				
			||||||
 | 
					        slave->handler(i2c, I2C_SLAVE_FINISH);
 | 
				
			||||||
 | 
					        slave->transfer_in_progress = false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS) {
 | 
				
			||||||
 | 
					        slave->transfer_in_progress = true;
 | 
				
			||||||
 | 
					        slave->handler(i2c, I2C_SLAVE_RECEIVE);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (intr_stat & I2C_IC_INTR_STAT_R_RD_REQ_BITS) {
 | 
				
			||||||
 | 
					        hw->clr_rd_req;
 | 
				
			||||||
 | 
					        slave->transfer_in_progress = true;
 | 
				
			||||||
 | 
					        slave->handler(i2c, I2C_SLAVE_REQUEST);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void i2c_slave_init(i2c_inst_t *i2c, uint8_t address, i2c_slave_handler_t handler) {
 | 
				
			||||||
 | 
					    assert(i2c == i2c0 || i2c == i2c1);
 | 
				
			||||||
 | 
					    assert(handler != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint i2c_index = i2c_hw_index(i2c);
 | 
				
			||||||
 | 
					    i2c_slave_t *slave = &i2c_slaves[i2c_index];
 | 
				
			||||||
 | 
					    slave->handler = handler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Note: The I2C slave does clock stretching implicitly after a RD_REQ, while the Tx FIFO is empty.
 | 
				
			||||||
 | 
					    // There is also an option to enable clock stretching while the Rx FIFO is full, but we leave it
 | 
				
			||||||
 | 
					    // disabled since the Rx FIFO should never fill up (unless slave->handler() is way too slow).
 | 
				
			||||||
 | 
					    i2c_set_slave_mode(i2c, true, address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    i2c_hw_t *hw = i2c_get_hw(i2c);
 | 
				
			||||||
 | 
					    // unmask necessary interrupts
 | 
				
			||||||
 | 
					    hw->intr_mask =
 | 
				
			||||||
 | 
					            I2C_IC_INTR_MASK_M_RX_FULL_BITS | I2C_IC_INTR_MASK_M_RD_REQ_BITS | I2C_IC_RAW_INTR_STAT_TX_ABRT_BITS |
 | 
				
			||||||
 | 
					            I2C_IC_INTR_MASK_M_STOP_DET_BITS | I2C_IC_INTR_MASK_M_START_DET_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // enable interrupt for current core
 | 
				
			||||||
 | 
					    uint num = I2C0_IRQ + i2c_index;
 | 
				
			||||||
 | 
					    irq_set_exclusive_handler(num, i2c_slave_irq_handler);
 | 
				
			||||||
 | 
					    irq_set_enabled(num, true);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void i2c_slave_deinit(i2c_inst_t *i2c) {
 | 
				
			||||||
 | 
					    assert(i2c == i2c0 || i2c == i2c1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint i2c_index = i2c_hw_index(i2c);
 | 
				
			||||||
 | 
					    i2c_slave_t *slave = &i2c_slaves[i2c_index];
 | 
				
			||||||
 | 
					    assert(slave->handler); // should be called after i2c_slave_init()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    slave->handler = NULL;
 | 
				
			||||||
 | 
					    slave->transfer_in_progress = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint num = I2C0_IRQ + i2c_index;
 | 
				
			||||||
 | 
					    irq_set_enabled(num, false);
 | 
				
			||||||
 | 
					    irq_remove_handler(num, i2c_slave_irq_handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    i2c_hw_t *hw = i2c_get_hw(i2c);
 | 
				
			||||||
 | 
					    hw->intr_mask = I2C_IC_INTR_MASK_RESET;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    i2c_set_slave_mode(i2c, false, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								src/rp2_common/pico_i2c_slave/include/pico/i2c_slave.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/rp2_common/pico_i2c_slave/include/pico/i2c_slave.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2021 Valentin Milea <valentin.milea@gmail.com>
 | 
				
			||||||
 | 
					 * Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SPDX-License-Identifier: BSD-3-Clause
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _PICO_I2C_SLAVE_H_
 | 
				
			||||||
 | 
					#define _PICO_I2C_SLAVE_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "hardware/i2c.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** \file pico/i2c_slave.h
 | 
				
			||||||
 | 
					 * \defgrup pico_i2c_slave pico_i2c_slave
 | 
				
			||||||
 | 
					 * \brief I2C slave helper library, which takes care of hooking the I2C IRQ and calling back the user with I2C events.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief I2C slave event types.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef enum i2c_slave_event_t
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    I2C_SLAVE_RECEIVE, /**< Data from master is available for reading. Slave must read from Rx FIFO. */
 | 
				
			||||||
 | 
					    I2C_SLAVE_REQUEST, /**< Master is requesting data. Slave must write into Tx FIFO. */
 | 
				
			||||||
 | 
					    I2C_SLAVE_FINISH, /**< Master has sent a Stop or Restart signal. Slave may prepare for the next transfer. */
 | 
				
			||||||
 | 
					} i2c_slave_event_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief I2C slave event handler
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * The event handler will run from the I2C ISR, so it should return quickly (under 25 us at 400 kb/s).
 | 
				
			||||||
 | 
					 * Avoid blocking inside the handler and split large data transfers across multiple calls for best results.
 | 
				
			||||||
 | 
					 * When sending data to master, up to `i2c_get_write_available()` bytes can be written without blocking.
 | 
				
			||||||
 | 
					 * When receiving data from master, up to `i2c_get_read_available()` bytes can be read without blocking.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * \param i2c Slave I2C instance.
 | 
				
			||||||
 | 
					 * \param event Event type.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					typedef void (*i2c_slave_handler_t)(i2c_inst_t *i2c, i2c_slave_event_t event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Configure I2C instance for slave mode.
 | 
				
			||||||
 | 
					 * 
 | 
				
			||||||
 | 
					 * \param i2c I2C instance.
 | 
				
			||||||
 | 
					 * \param address 7-bit slave address.
 | 
				
			||||||
 | 
					 * \param handler Called on events from I2C master. It will run from the I2C ISR, on the CPU core
 | 
				
			||||||
 | 
					 *                where the slave was initialized.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void i2c_slave_init(i2c_inst_t *i2c, uint8_t address, i2c_slave_handler_t handler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * \brief Restore I2C instance to master mode.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * \param i2c I2C instance.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void i2c_slave_deinit(i2c_inst_t *i2c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _PICO_I2C_SLAVE_H_
 | 
				
			||||||
@ -30,6 +30,7 @@ target_link_libraries(kitchen_sink_libs INTERFACE
 | 
				
			|||||||
    pico_double
 | 
					    pico_double
 | 
				
			||||||
    pico_fix_rp2040_usb_device_enumeration
 | 
					    pico_fix_rp2040_usb_device_enumeration
 | 
				
			||||||
    pico_float
 | 
					    pico_float
 | 
				
			||||||
 | 
					    pico_i2c_slave
 | 
				
			||||||
    pico_int64_ops
 | 
					    pico_int64_ops
 | 
				
			||||||
    pico_malloc
 | 
					    pico_malloc
 | 
				
			||||||
    pico_mem_ops
 | 
					    pico_mem_ops
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,7 @@
 | 
				
			|||||||
#include "pico/fix/rp2040_usb_device_enumeration.h"
 | 
					#include "pico/fix/rp2040_usb_device_enumeration.h"
 | 
				
			||||||
#include "pico/float.h"
 | 
					#include "pico/float.h"
 | 
				
			||||||
#include "pico/int64_ops.h"
 | 
					#include "pico/int64_ops.h"
 | 
				
			||||||
 | 
					#include "pico/i2c_slave.h"
 | 
				
			||||||
#include "pico/malloc.h"
 | 
					#include "pico/malloc.h"
 | 
				
			||||||
#include "pico/multicore.h"
 | 
					#include "pico/multicore.h"
 | 
				
			||||||
#include "pico/printf.h"
 | 
					#include "pico/printf.h"
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user