User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Pico as I2C slave (solved)

Sun Feb 14, 2021 11:44 pm

Has anyone had any joy I2C reading data from a Pico when the Pico is an I2C slave?

I can I2C write data to the Pico okay (Pico reports the proper received data) but if I try an I2C read from the Pico the I2C bus hangs.
Last edited by joan on Sat Feb 20, 2021 8:51 am, edited 1 time in total.

User avatar
penguintutor
Posts: 399
Joined: Tue May 08, 2012 9:11 am
Location: UK

Re: Pico as I2C slave

Mon Feb 15, 2021 5:29 pm

I have recently got this working. I've created a video here:
Video: Raspberry Pi to Pico and Arduino using I2C

And more details (including code download) here:
Using i2c between Raspberry Pi, Pico and Arduino

I had to use specific request types from the Raspberry Pi (Using SMBus on Python only worked with certain commands).

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave

Mon Feb 15, 2021 5:54 pm

Thanks for that. It looks good.

It almost does what I am trying to do. I want to sort of replicate the way the I2C slave works on the Pi. I want to be able to send/receive in a non-blocking way by using the FIFO.

It's fine at the Pico slave rx end as it will quite happily fill the rx FIFO when a master sends data via a write request. The data can then be read from the rx FIFO at a later time.

I hoped to do the same at the tx end by pre-filling the tx FiFO with data which would be held pending a read request from the master. That's the part I can't get working. When the read request comes in the system seems to flush data from the tx FIFO (rather than transmitting it). The bus then hangs.

smithg400
Posts: 152
Joined: Sat Dec 24, 2011 3:37 pm

Re: Pico as I2C slave

Fri Feb 19, 2021 3:15 pm

Not sure if you've got any further, but I've been playing with creating an I2C slave over the last few days and have only just seen your post. Thought you might find my approach at least interesting.

Purely as a test, I've implemented a 256 byte I2C RAM using my Pico. It is all interrupt driven, so once the system has been setup, the main routine has nothing to do.

The first byte of any write is treated as the address to write to, subsequent bytes (if any) are written to the ram, with the address incrementing after each byte.
A read takes data from the ram from the current address and again increments the address so you can read blocks of ram

To show it's use, using the command line tools, here are some example commands:

Code: Select all

> i2cset -y 1 0x30 49     # Set ram address to 49
> i2cget -y 1 0x30        # Reads data from address 49
> i2cget -y 1 0x30        # Reads data from address 50
> i2cset -y 1 0x30 78 23  # Writes data (23) to address 78
Using the block writes and reads from the python smbus library it is possible to read or write blocks of up to 32 bytes at a time

Note that the address automatically wraps round from address 255 to 0

Code: Select all

/******************************************************************************************
 * Example program for use of I2C slave
 * This example acts as a 256byte RAM
******************************************************************************************/

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/irq.h"

// define I2C addresses of slave
#define I2C0_SLAVE_ADDR 0x30

// GPIO pins to use for I2C
#define GPIO_SDA0 12
#define GPIO_SCK0 13

// define base address of I2C controller hardware
#define I2C0_BASE 0x40044000

// define the hardware registers used
volatile uint32_t * const I2C0_DATA_CMD       = (volatile uint32_t * const)(I2C0_BASE + 0x10);
volatile uint32_t * const I2C0_INTR_STAT      = (volatile uint32_t * const)(I2C0_BASE + 0x2c);
volatile uint32_t * const I2C0_INTR_MASK      = (volatile uint32_t * const)(I2C0_BASE + 0x30);
volatile uint32_t * const I2C0_CLR_RD_REQ     = (volatile uint32_t * const)(I2C0_BASE + 0x50);

// Declare the bits in the registers we use
#define I2C_DATA_CMD_FIRST_BYTE 0x00000800
#define I2C_DATA_CMD_DATA       0x000000ff
#define I2C_INTR_STAT_READ_REQ  0x00000020
#define I2C_INTR_STAT_RX_FULL   0x00000004
#define I2C_INTR_MASK_READ_REQ  0x00000020
#define I2C_INTR_MASK_RX_FULL   0x00000004

// define address to be used for RAM accesses
// N.B. Address auto increments, as stored in 8 bit value it automatically rolls round when reaches 255
uint8_t ram_addr;
// define storage for data of RAM
uint8_t ram[256];

// Interrupt handler implements the RAM
void i2c0_irq_handler() {
    // Get interrupt status
    uint32_t status = *I2C0_INTR_STAT;
    // Check to see if we have received data from the I2C master
    if (status & I2C_INTR_STAT_RX_FULL) {
        // Read the data (this will clear the interrupt)
        uint32_t value = *I2C0_DATA_CMD;
        // Check if this is the 1st byte we have received
        if (value & I2C_DATA_CMD_FIRST_BYTE) {
            // If so treat it as the address to use
            ram_addr = (uint8_t)(value & I2C_DATA_CMD_DATA);
        } else {
            // If not 1st byte then store the data in the RAM
            // and increment the address to point to next byte
            ram[ram_addr] = (uint8_t)(value & I2C_DATA_CMD_DATA);
            ram_addr++;
        }
    }
    // Check to see if the I2C master is requesting data from us
    if (status & I2C_INTR_STAT_READ_REQ) {
        // Write the data from the current address in RAM
        *I2C0_DATA_CMD = (uint32_t)ram[ram_addr];
        // Clear the interrupt
        *I2C0_CLR_RD_REQ;
        // Increment the address
        ram_addr++;
    }
}

// Main loop - initilises system and then loops while interrupts get on with processing the data
int main() {

    // Setup I2C0
    i2c_init(i2c0, 100 * 1000);
    i2c_set_slave_mode(i2c0, true, I2C0_SLAVE_ADDR);
    gpio_set_function(GPIO_SDA0, GPIO_FUNC_I2C);
    gpio_set_function(GPIO_SCK0, GPIO_FUNC_I2C);
    gpio_pull_up(GPIO_SDA0);
    gpio_pull_up(GPIO_SCK0);

    // Initialise the address to use for ram to 0
    ram_addr = 0;

    // Enable the interrupts we want
    *I2C0_INTR_MASK = (I2C_INTR_MASK_READ_REQ | I2C_INTR_MASK_RX_FULL);

    // Set up the interrupt handlers
    irq_set_exclusive_handler(I2C0_IRQ, i2c0_irq_handler);
    // Enable I2C interrupts
    irq_set_enabled(I2C0_IRQ, true);

    // Do nothing in main loop
    while (true) {
        tight_loop_contents();
    }
    return 0;
}
Hope it helps

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave

Fri Feb 19, 2021 4:32 pm

@ smithg400

Thanks for that. I have tried numerous approaches and all have failed. Your code looks promising. All I get with my interrupt code at the moment is a system hang beyond my ability to debug.

cleverca22
Posts: 6272
Joined: Sat Aug 18, 2012 2:33 pm

Re: Pico as I2C slave

Fri Feb 19, 2021 5:14 pm

joan wrote:
Fri Feb 19, 2021 4:32 pm
@ smithg400

Thanks for that. I have tried numerous approaches and all have failed. Your code looks promising. All I get with my interrupt code at the moment is a system hang beyond my ability to debug.
give openocd a try, its pretty simple to setup and lets you get a backtrace out of the pico at any time

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave

Fri Feb 19, 2021 5:23 pm

@smithg400

Thank you. God only knows how much of my time your code has saved. My code now works. I seemed to have been doing everything correctly apart from requesting the proper interrupts in the first place!

@cleverca22

It does show the level of frustration I was having. I did solder up the debug pins and use OpenOCD. Unfortunately I have only used gdb once or twice in my life and I was not up to that debug task.

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 31340
Joined: Sat Jul 30, 2011 7:41 pm

Re: Pico as I2C slave

Fri Feb 19, 2021 6:08 pm

Hi Joan,

is there a gap in the docs here that needs to be filled?
Principal Software Engineer at Raspberry Pi Ltd.
Working in the Applications Team.

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave

Fri Feb 19, 2021 6:45 pm

jamesh wrote:
Fri Feb 19, 2021 6:08 pm
Hi Joan,

is there a gap in the docs here that needs to be filled?
I couldn't really comment. You can't hope to cover every aspect with which an individual might have problems. I'd put my problem here down to myself.

smithg400 didn't seem to have a problem.

smithg400
Posts: 152
Joined: Sat Dec 24, 2011 3:37 pm

Re: Pico as I2C slave

Fri Feb 19, 2021 7:33 pm

smithg400 didn't seem to have a problem
I wouldn't exactly say that. If anything I think the SDK is lacking something when it comes to supporting slave mode. As you can see I found it easier to drive the hardware directly (once I'd allowed the SDK to configure slave mode) than use the SDK for the transmission and reception. Is there a reason why there isn't an example of slave mode in pico-examples?! One would be very useful.

25+ years of working in the telecomms industry and spending some of my time decoding manuals for HDLC controllers and driving them with the likes of 8051 microcontrollers and Z80 CPUs obviously helped with the RP2040 hardware documentation, however I haven't fully got my head round how the FIFOs work with I2C and would like to incorporate the DMA controller, but that is a fight for another day.

Glad you found my example useful.

P.S. I did have an earlier version which left the interrupts disabled and instead I polled the value in the IC_RAW_INTR_STAT register rather than checking the value in the IC_INTR_STAT register, that worked OK but then I moved to using interrupts on a step to getting DMA working.

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave

Fri Feb 19, 2021 8:47 pm

I had no problem using the i2C FIFO for received data. Just set slave mode and the FIFO is automatically filled when data is written to the slave address.

The problem with the send side is that you don't seem to be able to pre-fill the output buffer. It's counted as an error if the output buffer has contents when the read request arrives.

I did attempt to use DMA to fill the output buffer. Not successfully on my part.

I was testing with I2C1. I think the DMA interrupts are already set up for I2C (according to the source code for i2c_init).

Code: Select all

void i2cDMA(i2c_inst_t *i2c, int channel, int count, uint8_t *buf)
{
   int i;
   int dma_write=1;
   dma_channel_config c_write;

   //dma_channel_abort(dma_write);

   for (i=0;i<count;i++) myI2cBuf[i] = buf[i];

   // configure write DMA

   c_write = dma_channel_get_default_config(dma_write);
   channel_config_set_transfer_data_size(&c_write, DMA_SIZE_8);
   channel_config_set_read_increment(&c_write, true);
   channel_config_set_write_increment(&c_write, false);
   channel_config_set_dreq(&c_write, DREQ_I2C1_TX);

   dma_channel_configure(dma_write, &c_write,
      &i2c->hw->data_cmd, // Destinatinon pointer
      myI2cBuf,           // Source pointer
      count,              // Number of transfers
      false);

   dma_channel_start(dma_write);
}

Zerog
Posts: 3
Joined: Thu Sep 10, 2015 12:46 pm

Re: Pico as I2C slave

Mon Feb 22, 2021 7:56 pm

jamesh wrote:
Fri Feb 19, 2021 6:08 pm
Hi Joan,

is there a gap in the docs here that needs to be filled?
I thing that smithg400's code is a first real working i2c slave example. Add it as a official example (if smithg400 agree). Or add more info into SDK methods, because just call i2c_write_raw_blocking() didn't work.

smithg400
Posts: 152
Joined: Sat Dec 24, 2011 3:37 pm

Re: Pico as I2C slave (solved)

Tue Feb 23, 2021 8:55 am

I have a modified version, using the SDK header files rather than my own #define statements etc. which I'll tidy up and post. If the foundation would like to use that version as an example then I've no problem with that - It would be an honour! :)

smithg400
Posts: 152
Joined: Sat Dec 24, 2011 3:37 pm

Re: Pico as I2C slave (solved)

Tue Feb 23, 2021 9:18 pm

Updated code using SDK names for registers and fields - also uses newer I2C terms controller/peripheral instead of master/slave

Code: Select all

/**
 * Example program for basic use of pico as an I2C peripheral (previously known as I2C slave)
 * 
 * This example allows the pico to act as a 256byte RAM
 * 
 * Author: Graham Smith (graham@smithg.co.uk)
 */


// Usage:
//
// When writing data to the pico the first data byte updates the current address to be used when writing or reading from the RAM
// Subsequent data bytes contain data that is written to the ram at the current address and following locations (current address auto increments)
//
// When reading data from the pico the first data byte returned will be from the ram storage located at current address
// Subsequent bytes will be returned from the following ram locations (again current address auto increments)
//
// N.B. if the current address reaches 255, it will autoincrement to 0 after next read / write


#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/irq.h"

// define I2C addresses to be used for this peripheral
#define I2C0_PERIPHERAL_ADDR 0x30

// GPIO pins to use for I2C
#define GPIO_SDA0 12
#define GPIO_SCK0 13


// ram_addr is the current address to be used when writing / reading the RAM
// N.B. the address auto increments, as stored in 8 bit value it automatically rolls round when reaches 255
uint8_t ram_addr = 0;

// ram is the storage for the RAM data
uint8_t ram[256];


// Interrupt handler implements the RAM
void i2c0_irq_handler() {

    // Get interrupt status
    uint32_t status = i2c0->hw->intr_stat;

    // Check to see if we have received data from the I2C controller
    if (status & I2C_IC_INTR_STAT_R_RX_FULL_BITS) {

        // Read the data (this will clear the interrupt)
        uint32_t value = i2c0->hw->data_cmd;

        // Check if this is the 1st byte we have received
        if (value & I2C_IC_DATA_CMD_FIRST_DATA_BYTE_BITS) {

            // If so treat it as the address to use
            ram_addr = (uint8_t)(value & I2C_IC_DATA_CMD_DAT_BITS);

        } else {
            // If not 1st byte then store the data in the RAM
            // and increment the address to point to next byte
            ram[ram_addr] = (uint8_t)(value & I2C_IC_DATA_CMD_DAT_BITS);
            ram_addr++;
        }
    }

    // Check to see if the I2C controller is requesting data from the RAM
    if (status & I2C_IC_INTR_STAT_R_RD_REQ_BITS) {

        // Write the data from the current address in RAM
        i2c0->hw->data_cmd = (uint32_t)ram[ram_addr];

        // Clear the interrupt
        i2c0->hw->clr_rd_req;

        // Increment the address
        ram_addr++;
    }
}


// Main loop - initilises system and then loops while interrupts get on with processing the data
int main() {

    // Setup I2C0 as slave (peripheral)
    i2c_init(i2c0, 100 * 1000);
    i2c_set_slave_mode(i2c0, true, I2C0_PERIPHERAL_ADDR);

    // Setup GPIO pins to use and add pull up resistors
    gpio_set_function(GPIO_SDA0, GPIO_FUNC_I2C);
    gpio_set_function(GPIO_SCK0, GPIO_FUNC_I2C);
    gpio_pull_up(GPIO_SDA0);
    gpio_pull_up(GPIO_SCK0);

    // Enable the I2C interrupts we want to process
    i2c0->hw->intr_mask = (I2C_IC_INTR_MASK_M_RD_REQ_BITS | I2C_IC_INTR_MASK_M_RX_FULL_BITS);

    // Set up the interrupt handler to service I2C interrupts
    irq_set_exclusive_handler(I2C0_IRQ, i2c0_irq_handler);

    // Enable I2C interrupt
    irq_set_enabled(I2C0_IRQ, true);

    // Do nothing in main loop
    while (true) {
        tight_loop_contents();
    }
    return 0;
}

silverglade303
Posts: 8
Joined: Sun Mar 14, 2021 4:45 pm

Re: Pico as I2C slave (solved)

Wed Apr 14, 2021 2:49 am

I followed this example and mine just hangs at "irq_set_enabled(I2C1_IRQ, true);" I have I2C0 doing something else and that is working perfectly. If I comment out that line I can see that the pico is replying correctly with the ACK to the master but the interrupt is never triggered.

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave (solved)

Wed Apr 14, 2021 6:49 am

You have incorrectly followed the example.

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Tue May 04, 2021 6:29 pm

Hi, I am trying to work out a way to use pico as helper for rpi (for real-time stuff) and pico as i2c peripheral seems good candidate. @smithg400's 1st example (when he made defines for i2c hw registers) works fine for me. (i did have problems w/ refined example that i will try to duplicate later, but now moving forward w/ original).

I used i2cset/get/write utilities to verify.

Now I'd like to write my own C code to do what the utilities accomplish. I'll search for examples. @smithg400 if you proceed to FIFO and DMA enhancement on the pico side i hope you will post in this thread.

** QUESTIONS ** is it a reasonable approach to use this ramdisk code as basis of general interface between rpi and pico much in the way of linux old school 'shared-memory'? Any suggestions about how to be safe about using the ram buffer as shared memory?

EduardH
Posts: 61
Joined: Fri Sep 04, 2015 8:10 am

Re: Pico as I2C slave (solved)

Thu May 13, 2021 11:48 am

Hello,

I spent a lot of time finding out why the Rpi master / I2c slave didn't work. The controller is an Rpi4B, the periferal the Pico. I folowed the main lines of the demo made by Penguintutor. Writing to the periferal, works fine. After a read the bus hangs. At first glance, my Rpi program was suspected. Although, after replacing the pico by an i2c integrated circuit, the Rpi (controller) worked fine.

This morning I have downloaded the Penguintutor example with the Python program on the Rpi4. This works! I am looking for some C code that could replace the Python in the working example. It seems it has something to do with SMbus.
Any hint for writing a C program that cam replace the python code in the demo will help.

Sincerely,

Eduard

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Thu May 13, 2021 4:46 pm

@EduardH,
this C code on rpi https://gist.github.com/JamesDunne/9b7 ... 23f47beb7
and the code by smithg400 in this thread is working very good for me. I had already lowered my bit speed on the pi to 100kbps so i can't say yes or no about ops @ 400kbps.

I first tried ops just using internal pull ups, that was a no-go. After adding one set of ~3k ohm pullups (caution, only to 3.3v) all was good. I have been slamming it with a fix of the library above and bash driven calls to the i2c utilities (i2cset, i2cget, i2cdetect, i2cput) for a few days, can't seem to break it. My test setup is one rpi4 "controller" and three pico "peripherals". This morning i tried extending the library to make 10byte long General Call Address transactions. Much to my amazement, the pico's acknowledged the GCA transaction. Finally found in the rp2040 a register setting that configures that behavior, defaults to acknowledgement, nice.

My end goal is "multi-master" with bunches of picos. Some say this is crazy talk, we shall see.

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Fri May 14, 2021 12:38 pm

For completeness for anyone reading this thread;

in my previous post i indicated i was in pursuit of a multi-master solution to distributed computing. my intent was for small systems (robots of various sizes) that would have rpi as processor for non-real-time tasks and many picos for real-time-tasks. i've built similar using canbus for peer-to-peer comm. i had hoped to do same with multi-master i2c to reduce cost. My first experiments toward this goal have been encouraging with single rpi4 as controller and three picos as peripherals.

I finally read the broadcom datasheet ( BCM2835 ARM Peripherals) for the i2c (they call it BSC) and saw this;
" single master only operation "
ugh... the dream remains illusive <i have sad>

but wait... i see rumors rpi4 has a i2c-slave ... i like the worker's paradise topology, all the worker picos (configured as master) controlling the chairman of the party. <i have hope>

GPIO 10: I2C_Slave_SDA
GPIO 11: I2C_Slave_SCL

User avatar
joan
Posts: 15997
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Pico as I2C slave (solved)

Fri May 14, 2021 3:26 pm

@monkeyfork

If the Pi is the master it is the controller. So isn't single master (Pi) and multiple slaves (Picos) what you want? That means the Pi interrogates the Picos to get their progress.

I do not see how making the Pi the slave will help you. The bus is still single master. Only one Pico (the new master in your system) will be able to talk to the Pi. The other Picos will have to be slaves to the Pico master.

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Fri May 14, 2021 5:18 pm

@joan, thanks for input. i'll admit i know a lot more about canbus than i2c but what i'd LIKE is a i2c-net/bus/whatever that acts in a similar fashion like canbus in that nodes can do the publish/subscribe thing to move data and requests around. However, canbus engine chips and differential line drivers can double the cost of a node given what the pico has done to pricing.

But neither pico nor rpi can do canbus without extra chips and additional board real estate. (maybe the pico's pio can someday do canbus but differential line drivers would still have to be added)

As for the rpi being a slave(peripheral) from everything i read slaves do not have a part in multi-master arbitration. it should be totally transparent for a slave. So, i'm still holding out hope that the pico i2c engine (DW-apb-i2c) has finally got arbitration right and pico may indeed be able of multi-master ( it sure looks like it reading the rp2040 datasheet). I've read that a pico can be master __OR__ slave but it sure looks like to be a pico could be _usually_ slave and periodically a master (quick reprogramming of i2c engine) to "publish".

It also looks like the GCA (general call address) mechanism could be used in multi-master to publish network-variables by nodes.

So, for now, I'll pursue both;
1) rpi as i2c controller + lot's of picos as i2c peripherals
2) lots of picos as i2c controllers and 1 rpi as benevolent autocrat who dutifully listens to all his/her workers.

i've found some cpp that purports to accomplish rpi as i2c peripheral https://raspberrypi.stackexchange.com/q ... -i2c-slave. It compiles, woohoo... that's next up in the test queue.

reynoldsbd
Posts: 1
Joined: Thu May 27, 2021 3:00 pm

Re: Pico as I2C slave (solved)

Thu May 27, 2021 10:56 pm

Thanks smithg400 for the awesome template!

Note that if you want to do anything particularly time consuming within the ISR, consider setting IC_CON.RX_FIFO_FULL_HLD_CTRL to enable slave clock stretching.

Code: Select all

int main()
{
    // Setup I2C0 as slave (peripheral)
    i2c_init(i2c0, 100 * 1000);
    i2c_set_slave_mode(i2c0, true, I2C0_PERIPHERAL_ADDR);
    
    // Enable slave clock stretching
    i2c0->hw->enable = 0;
    hw_set_bits(&i2c0->hw->con, I2C_IC_CON_RX_FIFO_FULL_HLD_CTRL_BITS);
    i2c0->hw->enable = 1;
    
    // ...
}
This instructs DW_apb_i2c to hold SCL low while the RX FIFO is full, preventing the master from transmitting more bytes (and overrunning the FIFO) until the ISR has time to handle things.

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Thu Jun 03, 2021 6:02 pm

@reynoldsbd I have added the clock stretch to the most excellent example provided by @smithg400 and plan to test soon. So far i've only been sending a max of 16byte packets to pico-responder but definitely see use cases that i'd like that much larger.

my goal is to make a rpi + (many)pico 'network' for robotics. i am having reasonable success in making rpi3-controller co-exist with multiple pico-controllers and pico-responders. The rpi3-controller is not broken by other controllers on same net but will probably cause chaos if there is ever a collision as it is not supposed to be able to handle arbitration. i plan to attempt a scheme wherein a rpi3(4) would transmit a GCA message at the top of every second which would maybe be basis of a time triggered contention managing scheme.

i am having one problem that seems to be outside of my present troubleshooting skills. When either the rpi or a pico-controller transmit a GCA i am having difficulty getting byte#2 of the message. The pico behaves appropriately to the GCA address of 0x00 and receives the "first byte" (that i am using for message type). But somehow i'm losing the 2nd byte. All other byte rx'd ok.

I'm doing this in C and using SWD and the very nice OpenOCD/GDB debugging setup. However, using that in single step scenarios screws with the timing of when RX-FULL happens.

Any ideas _anyone_?
<EDIT 04jun2021> found problem with receiving a long GCA (general call address, ie broadcast) message. simple logic error, all ok now with receiving GCAs. will pursue concept of using GCAs for the basis of publish/subscribe mechanism for rpi broadcasting to bunch of picos, picos-config-as-controllers talking to picos-config-as-responders _AND_ rpi(3/4) talking to bunch of picos individually via specific addresses.

monkeyfork
Posts: 136
Joined: Tue Oct 29, 2013 10:14 am
Location: orlando

Re: Pico as I2C slave (solved)

Sat Jun 05, 2021 10:08 pm

maybe someone could tell me where the "new topic" button is for the forum? i'll put this here in somewhat related topic for now but would like to start a topic on rpi + many-pico i2c networks.

today i proved a concept to myself. I've used both i2c0 and i2c1 (parallel wired) on one pico to accomplish both "controller" and "responder" in same pico. On same i2c network is a rpi3 connected to the default i2c pins 3,5 and other pico config'd as controllers or responders.

The i2c-combo pico generates GCA (General Call Address) broadcast messages that are rx'd by other pico-responders on the network (but not the rpi3 as it's main channel is supposedly is i2c-controller ONLY and i2c slave-i2c appears to be funky so i'm not trying to incorporate it yet).

The reason for wanting pico nodes to be capable of controller behavior is to build toward publish/subscribe methods of passing data around the i2c-network.

The obvious place this can fail is contention with rpi3 as it is not advertised at being capable of multi-master contention arbitration. However, i have proven (not rigorously enough yet) that having other controllers transmit does not bother the rpi3 in any way i can yet detect.
I have implemented from the rpi a time-tick GCA at the top of every second. The tick is being received by my combo-picos and i hope to use the tick to make a time guard band that will prohibit transmission by a pico-controller to avoid contention with the rpi (as well as provide way
to sync all picos roughly within 300usec, meh).


so... I think there is HUGE need for a rpi + many-pico networks. Canbus is my scalpel of choice but i only have the hammer of i2c that is essentially FREE (cost of 2 pullup resistors).

please feel free to throw rocks or poo at this idea but when you do, please tell me where the new-topic button is hidden in clear view))

<< EDIT 06JUN2021 0700 EDT >>
(never mind, i found the 'new topic' button, " RPi + many-Pico I2C controller/responder AND peer-to-peer " is new topic under "other")

Return to “General”