Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

undefined reference to `i2c_start' when trying to use mbed I2C #28

Closed
nicklasb opened this issue Apr 27, 2023 · 20 comments
Closed

undefined reference to `i2c_start' when trying to use mbed I2C #28

nicklasb opened this issue Apr 27, 2023 · 20 comments

Comments

@nicklasb
Copy link

nicklasb commented Apr 27, 2023

Hi!

I am having problems with using the event based implementation in wire.h, mainly I have problems getting the slave/peripheral on an Raspberry Pi Pico W (Arduino) replying to the ESP32 master/controllers request. All other directions work but that doesn't. Also the interrupt-event-based implementation makes the timing difficult and a more generalized implementation messy.

So now I am trying to use the mbed I2C/I2Cslave implementation which seems quite nifty (no sure what Wire.h actually brings except from the interrupt-events and some minor abstractions) but something seem to be missing.

I am getting this error when building:

/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: /.platformio/packages/framework-arduino-mbed/variants/RASPBERRY_PI_PICO/libs/libmbed.a(I2C.o): in function `mbed::I2C::start()':
I2C.cpp:(.text._ZN4mbed3I2C5startEv+0xc): undefined reference to `i2c_start'

Any ideas?

@maxgerhardt
Copy link
Owner

platformio.ini is what eaxctly?

@nicklasb
Copy link
Author

Hi!

@maxgerhardt, its like below:

[platformio]
src_dir = src
test_dir = test

[env]
test_framework = unity
monitor_raw = yes

------
Other environments, hopefully irrelevant (and works)
------

[env:RaspberryPi_Pico]
#platform = raspberrypi
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = pico
framework = arduino
lib_extra_dirs = components, test
test_framework= custom
upload_protocol = picotool
lib_deps = 
  ${env.lib_deps}
  Wire

@maxgerhardt
Copy link
Owner

maxgerhardt commented May 1, 2023

I can't reproduce this with an I2C slave sketch

#include <Arduino.h>
#include <Wire.h>
void I2C_ReveiceCB(int numBytes)
{
  int I2C_OnOff = Wire.read();                      
  if (I2C_OnOff == 1)
  {
   digitalWrite(LED_BUILTIN, HIGH);                 
  }
  else if (I2C_OnOff == 0)
  {
   digitalWrite(LED_BUILTIN, LOW);                 
  } 
}

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Wire.begin(1);
  Wire.onReceive(I2C_ReveiceCB);
}

void loop() { delay(1000); }
CONFIGURATION: https://docs.platformio.org/page/boards/raspberrypi/pico.html
PLATFORM: Raspberry Pi RP2040 (1.7.0+sha.20c7dbf) > Raspberry Pi Pico
HARDWARE: RP2040 133MHz, 264KB RAM, 2MB Flash
DEBUG: Current (blackmagic) External (blackmagic, cmsis-dap, jlink, picoprobe, raspberrypi-swd)
PACKAGES:
 - framework-arduino-mbed @ 4.0.2
 - tool-rp2040tools @ 1.0.2
 - toolchain-gccarmnoneeabi @ 1.90301.200702 (9.3.1)
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 42 compatible libraries
Scanning dependencies...
Dependency Graph
|-- Wire
Building in release mode
Compiling .pio\build\RaspberryPi_Pico\src\main.cpp.o
Retrieving maximum program size .pio\build\RaspberryPi_Pico\firmware.elf
Flash size: 2.00MB
Sketch size: 2.00MB
Filesystem size: 0.00MB
Maximium Sketch size: 2093056 EEPROM start: 0x101ff000 Filesystem start: 0x101ff000 Filesystem end: 0x101ff000
Checking size .pio\build\RaspberryPi_Pico\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  15.3% (used 41332 bytes from 270336 bytes)
Flash: [          ]   0.2% (used 4062 bytes from 2093056 bytes)
=============================================================================== [SUCCESS] Took 5.78 seconds ===============================================================================

@nicklasb
Copy link
Author

nicklasb commented May 1, 2023

Hi!

I realize that I might not have been clear; I use the mbed I2C.h/I2Cslave.h implementation, not Wire.h.
I do not use Wire.h because i to not want to use the event-based architecture, it doesn't blend with my own queue handling with events on requests inside events.
Also Wire.h doesn't seem to work properly when writing in slave requests (at least not on the RPI Pico W, on STM32 it seems even worse).

So I am instead using i2c_start and other of
.platformio/packages/framework-arduino-mbed/cores/arduino/mbed/hal/include/hal/i2c_api.h .

But the implementation of i2c_start seems to be missing. It is commonly used in other contexts, and it seems Wire.h also uses it in some way, but have some own implementation, which seem hidden.

Additionally, by going lower level, I might also find out what is wrong with Wire.h inside requests.

@maxgerhardt
Copy link
Owner

Can you post a minimal piece of code that reproduces the compiler error?

You might just have a problem as simple as forgetting to extern "C" { #include ".../i2c_api.h"}.

@nicklasb
Copy link
Author

nicklasb commented May 1, 2023

I am realizing that I am having trouble resetting everything to that state, I just moved all MCU:s around here and did some inventive branching. :-)
But you are right, it might be something like that, I will try that, thanks!
I'll be back in a while!

@nicklasb
Copy link
Author

nicklasb commented May 3, 2023

Ok, now for some reason the RPI Pico won't give a serial connection in pio test with unity for some reason.
It uploads but then time outs.
TimeoutError: Could not automatically find serial port for the Raspberry Pi Pico board based on the declared HWIDs=['2E8A:00C0'] TimeoutError: Could not automatically find serial port based on the known UART bridges

I will try and solve that and then get back on this one.

@maxgerhardt
Copy link
Owner

Non-existing USB serial port could also be an indication that the (test) firmware straight up crashed the board. Does it still work in an absolute minimal project?

@nicklasb
Copy link
Author

nicklasb commented May 3, 2023

Yeah, I am looking into that now.
Edit: Made it work in a minimal projekt, you were right. Trying to find the issue.

@nicklasb
Copy link
Author

nicklasb commented May 3, 2023

@maxgerhardt
Actually the minimal project didn't work, it seems like it ran on an ESP32 I had, it just looked as the RPI ran it, it said that it was the RPI Pico environment, but in actuality, it was the ESP32 environment.
Do you know about some super-basic example that runs unity tests on the RPI Pico, perhaps?

I just remembered that running unit testing on the RPI was problematic, and that I had to use a custom runner because the mbed runner conflicted.

@maxgerhardt
Copy link
Owner

maxgerhardt commented May 3, 2023

With the Arduino-Pico core, which is the entire point of this repo, it works without problems when you wait for Serial connection to be established

grafik

Just create test/test_embedded/test_example.cpp per

#include <Arduino.h>
#include <unity.h>

void setUp(void) {
    // set stuff up here
}

void tearDown(void) {
    // clean stuff up here
}

int function_under_test(int a, int b) {
    return a + b;
}

void test_calculator_addition(void) {
    TEST_ASSERT_EQUAL(32, function_under_test(25, 7));
}

void setup() {
    UNITY_BEGIN();
    // wait for serial monitor to be connected, however long it may take.
    while(!Serial) delay(10);
    RUN_TEST(test_calculator_addition);
    UNITY_END();
}

void loop() {
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
}
[env:pico]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
board = rpipico
framework = arduino
board_build.filesystem_size = 1m

@maxgerhardt
Copy link
Owner

Let me double check mbed, because I know there was platformio/platformio-core#3980.

@nicklasb
Copy link
Author

nicklasb commented May 3, 2023

That's where it was! I have fought with so many platforms and boards lately that I've started to mix them up. :-)

@maxgerhardt
Copy link
Owner

Wow I may have Alzheimers, the Pico in Arduino-Pico and ArduinoCore-mbed unit testing core issues we've already discussed there last month, so it should still work.

@nicklasb
Copy link
Author

nicklasb commented May 3, 2023

OK. For some reason, that fix seems to have stopped working for me.
Trying to find out what have changed.

@nicklasb
Copy link
Author

nicklasb commented May 5, 2023

It was parts of the testing suites that caused it to crash. Also the RPI Pico W seems to crash my other modules, not sure how it does it yet, power draw is one possibility.

Anyway, back on the subject; I still get the undefined reference to i2c_start when I call mbed::I2C start();

#include "mbed/mbed.h"
#include "mbed_wait_api.h"

i2c_master = new I2C(PN_DEF(CONFIG_I2C_SDA_IO), PN_DEF(CONFIG_I2C_SCL_IO));
i2c_master->start();

I have tried without start(), but it doesn't seem to send things properly then.
The mbed examples in the code doesn't mention start(), perhaps something implicitly calls it, and then there is something different, perhaps the GPIO configs.

Basically I am trying to use I2C.h in .platformio/framework-arduino-mbed/cores/arduino/mbed/drivers/include/drivers/I2C.h
There is also the i2c_api, but I can't find any examples for that or make it work properly.

Edit: Interestingly, stop() seems to be implemented.

@maxgerhardt
Copy link
Owner

maxgerhardt commented May 5, 2023

Yeah I can reproduce that error.

#include <Arduino.h>
#include "mbed/mbed.h"
#include "mbed_wait_api.h"
using namespace mbed;

void setup() {
  I2C* i2c_master = new I2C(p8, p9); //GP8, GP9
  i2c_master->start();
}

void loop() {

}
[env]
platform = https://github.com/maxgerhardt/platform-raspberrypi.git
framework = arduino
board_build.filesystem_size = 1m

[env:pico_arduino_mbed]
board = pico

You can see the ArduinoCore-mbed's Wire library using the start() API

https://github.com/arduino/ArduinoCore-mbed/blob/80310080316bee7d0ff5c72392554dbaa29a7f11/libraries/Wire/Wire.cpp#L35-L43

When DEVICE_i2CSLAVE is defined and that is indeed the case for a Pico.

https://github.com/arduino/ArduinoCore-mbed/blob/80310080316bee7d0ff5c72392554dbaa29a7f11/variants/RASPBERRY_PI_PICO/defines.txt#L7

So the issue is clear form the C++ code above: The I2C class (for I2C masters) does not have an implemented start() method, and it's also not needed for I2C communication since the Wire class can do fine without it.

void setup() {
  I2C* i2c_master = new I2C(p8, p9); //GP8, GP9
  uint8_t data[] = {0x13, 0x37};
  i2c_master->write(0xAB, (const char*) data, (int) sizeof(data));
}

For I2C salves, the I2CSlaveclass must be used, which doesn't have a start() method anyways, but an address() method instead. There it just needs receive() per code.

void setup() {
  I2CSlave* i2c_slave = new I2CSlave(p8, p9); //GP8, GP9
  i2c_slave->address(0x12);
}

@nicklasb
Copy link
Author

nicklasb commented May 5, 2023

You can see the ArduinoCore-mbed's Wire library using the start() API

That is not that API, that is thread.start() I believe?
Also, it is the slave code you are pointing at, so it would not use start()?

So the issue is clear form the C++ code above: The I2C class (for I2C masters) does not have an implemented start() method, and it's also not needed for I2C communication since the Wire class can do fine without it.

Actually I haven't gotten the RPI Pico to work properly with Wire now for some reason.
But especially I have no need for (and don't want to use) the callback model that the thread uses, I have my own threading model.

@maxgerhardt
Copy link
Owner

You can see the ArduinoCore-mbed's Wire library using the start() API

That is not that API, that is thread.start() I believe?

Right, that's a remnant from the edit, I thought that in the beginning but recognized otherwise afterwards. The Wire library is not calling into any I2C/I2CSlave classes's start method. But if it's called on I2C it indeed produces a linker error.

And since you got Wire working I think we can close the issue.

@nicklasb
Copy link
Author

nicklasb commented May 5, 2023

I actually haven't got that working, the slave responses aren't reaching the master, however that is probably another issue, this is about me not being able to use wire for my purposes and therefore using the mbed implementation.

I understand that you might not feel that is a part of the offering, so to say, but if there is no way forward, there is no point in having it open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants