-
Notifications
You must be signed in to change notification settings - Fork 11
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 references when using TwoWire classes #22
Comments
Hey @TheZoq2, check out the contents of You'll see something like this: #[repr(C)]
pub struct TwoWire {
pub _base: Stream,
pub __bindgen_anon_1: TwoWire_I2C_Hardware_t,
pub port: *mut KINETIS_I2C_t,
pub hardware: *const TwoWire_I2C_Hardware_t,
pub rxBuffer: [u8; 32usize],
pub rxBufferIndex: u8,
pub rxBufferLength: u8,
pub txAddress: u8,
pub txBuffer: [u8; 33usize],
pub txBufferIndex: u8,
pub txBufferLength: u8,
pub transmitting: u8,
pub slave_mode: u8,
pub irqcount: u8,
pub sda_pin_index: u8,
pub scl_pin_index: u8,
pub user_onRequest: ::core::option::Option<unsafe extern "C" fn()>,
pub user_onReceive: ::core::option::Option<unsafe extern "C" fn(arg1:
c_types::c_int)>,
}
// ...
impl TwoWire {
#[inline]
pub unsafe fn begin(&mut self) { TwoWire_begin(self) }
#[inline]
pub unsafe fn begin1(&mut self, address: u8) {
TwoWire_begin1(self, address)
}
#[inline]
pub unsafe fn begin2(&mut self, address: c_types::c_int) {
TwoWire_begin2(self, address)
}
// ...
#[inline]
pub unsafe fn new(myport: *mut KINETIS_I2C_t,
myhardware: *const TwoWire_I2C_Hardware_t) -> Self {
let mut __bindgen_tmp = ::core::mem::uninitialized();
TwoWire_TwoWire(&mut __bindgen_tmp, myport, myhardware);
__bindgen_tmp
}
} Based on this, I think you will need something like this: unsafe {
// you need to replace the "..." here with something
let mut i = bindings::KINETIS_I2C_t{ ... };
let mut hw = bindings::TwoWire_I2C_Hardware_t{ ... };
// something like this, not 100% sure about the syntax here
let mut x = bindings::TwoWire::new(&mut i, &mut hw);
x.begin();
// ...
} Let me know if this helps. |
Also to clarify, in the Arduino environment, they create an instance of the TwoWire class "implicitly". I just looked at the source, and I saw this in #ifdef WIRE_IMPLEMENT_WIRE // This is set for the Teensy 3.x family
TwoWire Wire(KINETIS_I2C0, TwoWire::i2c0_hardware);
void i2c0_isr(void) { Wire.isr(); }
#endif This means that the C++ class is creating an instance of extern TwoWire Wire;
// ...
Wire.begin(); I'm not sure how to do that in Rust (if it is possible). If you can't find a way to do it, you can follow my instructions in the message above on how to create a new instance of TwoWire in rust. The C++ code is helpful to tell you what to put in those #define KINETIS_I2C0 (*(KINETIS_I2C_t *)0x40066000) const TwoWire::I2C_Hardware_t TwoWire::i2c0_hardware = {
SIM_SCGC4, SIM_SCGC4_I2C0,
#if defined(__MKL26Z64__) || defined(__MK20DX128__) || defined(__MK20DX256__)
18, 17, 255, 255, 255,
2, 2, 0, 0, 0,
19, 16, 255, 255, 255,
2, 2, 0, 0, 0,
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
18, 17, 34, 8, 48,
2, 2, 5, 7, 2,
19, 16, 33, 7, 47,
2, 2, 5, 7, 2,
#endif
IRQ_I2C0
}; |
Oh. Derp. From extern "C" {
#[link_name = "Wire"]
pub static mut Wire: TwoWire;
} That would do it. Try this: pub fn begin_master()
{
unsafe {
bindings::Wire.begin();
}
} |
Okay. I've come full circle. I think I now understand your actual question. I've also decided to stop answering questions at 1am. I don't know why the linker is having an issue with a missing I still think making a new instance as I described above would work, but probably shouldn't be necessary. I will shut up now until I have time to actually test my suggestions locally. Sorry for blowing up your inbox with notifications. Hopefully some of this actually helped, and I wasn't just telling you things you already know :) |
Yep, GCC stripping them out sounds like a pretty good theory. Also, it's not just
I'll look into that and see if I can figure it out.
No worries about the spam, it gave me some ideas about things to try. Though you could always edit the message if you think people are annoyed by the spam :P Edit: I'm not sure how to properly initialize the two_wire class. Specifically, i'm not sure how to set the _base member. |
I did some more thinking and testing about this and I'm not sure if the issue is with the Wire constants. Wouldn't the linker complain about Also, I noticed that the SPI functions in the crate have the same issue. let spi = teensy3::spi::Spi{};
spi.begin(); I also tested unsafe {
bindings::SPIClass_begin();
} Which gives the same error:
In the bindings.rs file it seems like bindgen generates functions for all methods of a class and prefixes them with extern "C" {
#[link_name = "begin"]
pub fn SPI2Class_begin();
} To me, the |
@TheZoq2 Did you ever get further along with this? I'm attempting to integrate OctoWS2811 and having very similar problems |
I did not, I lost interest in using rust on teensys for a while and then
started using it on a "blue pill" board instead
…On Fri, 11 May 2018, 22:44 Patrick Brown, ***@***.***> wrote:
@TheZoq2 <https://github.com/TheZoq2> Did you ever get further along with
this? I'm attempting to integrate OctoWS2811 and having very similar
problems
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#22 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFERLaEyfg9TpXpAKURKhOl9LFPa7WH7ks5txfhGgaJpZM4NKfou>
.
|
Alright, thanks for the response! |
I am trying to use get i2c communication to work but i'm getting a linker error when I use any of the functions.
In the compiled documentation, I have found the struct
teensy3_sys::TwoWire
which I assume is generated from the arduinoTwoWire
class defined inhardware/teensy/avr/Wire
orhardware/arduino/avr/libraries/Wire/
I have also found
bindings::Wire
,bindings::Wire1
andbindings::Wire2
. They all have the following type signatureI assume they are the same instances of TwoWire you use in regular arduino code.
Because of this, I assume that the following code should compile and work fine
However, if I add a call to
begin_master
to my main program, I get the following linker error:I also tried
bindings::TwoWire_begin(&mut bindings::Wire1);
which gives me the same error.Looking at the arduino source, I don't see why there would be a function called
begin
, if anythign it should beTwoWire::begin
. I also don't see bindings for the internal c code that TwoWire wraps aroundlibraries/Wire/src/utility/twi.c
.This is when trying to compile for teensy3.5, I have not tried 3.2
The text was updated successfully, but these errors were encountered: