chipKIT® Development Platform

Inspired by Arduino™

cihpkit issues on linux Mint 13

Created Sat, 11 Jun 2016 18:35:17 +0000 by bperrybap


bperrybap

Sat, 11 Jun 2016 18:35:17 +0000

The following issues prevent building and uploading code using Linux Mint 13 Linux mint 13 is an LTS release that is still supported until april 2017. [url]https://www.linuxmint.com/download_all.php[/url]

If you try to use the MPIDE package mpide-0150-linux32-20150820 it doesn't work as it sets the ARDUINO version to 19 (off topic by why 19? mpide-0023-linux32-20120903 used 23, why isn't it using 150? to indicate 1.5 APIs? ) The issues is that the ARDUINO value is less than 100 so any code that compile time detects arduino pre 1.x vs 1.x, fails on the pic32 boards since the pic32 core has 1.x Print class API functions even though the ARDUINO define says the Arduino core is pre 1.x Even stranger is that the AVR core included in MPIDE is using a pre 1.x API core. So MPIDE is pretty broken.

Using the chipKIT core on the Arduino IDE doesn't solve the problem either. While the chipKIT core does allow the code to be built using the Arduino IDE, the image can't be uploaded to the board because the pic32prog can't run. The linux pic32prog included in the chipKIT core requires using libudev.so.1 and it isn't available on linux Mint 13. So you get the following error: pic32prog: error while loading shared libraries: libudev.so.1: cannot open shared object file: No such file or directory

I tried to trick it by creating a symlink to the existing libudev library but then you get: /home/bill/.arduino15/packages/chipKIT/tools/pic32prog/v2.0.220-pic32gcc/pic32prog: /lib/i386-linux-gnu/libudev.so.1: no version information available (required by /home/bill/.arduino15/packages/chipKIT/tools/pic32prog/v2.0.220-pic32gcc/pic32prog)

/home/bill/.arduino15/packages/chipKIT/tools/pic32prog/v2.0.220-pic32gcc/pic32prog: /lib/i386-linux-gnu/libc.so.6: version `GLIBC_2.17' not found (required by /home/bill/.arduino15/packages/chipKIT/tools/pic32prog/v2.0.220-pic32gcc/pic32prog)

It looks like MPIDE was not using it but rather some patched version of avrdude. Could pic32prog be tweaked to not require the newer libudev?

--- bill


majenko

Sat, 11 Jun 2016 19:02:18 +0000

LTS means that Ubuntu will continue to provide patches for it. It doesn't mean that it will magically upgrade itself to support all the current third party software. Pic32prog is compiled to run on the current versions of debian and Ubuntu based operating systems, not ones that are very old a even if Ubuntu still provide patches for them.

If you need different libraries to run a piece of software then it is up to you to build and install that software. That is the beauty of open source. Just download the source code to libusb1 and compile it. Installing binaries from a newer operating system will not work. Linux has moved on somewhat since then.

Sent from my SM-T555 using Tapatalk


majenko

Sat, 11 Jun 2016 19:04:47 +0000

Oh, and MPIDE is deprecated. You shouldn't be using it any more. It's only provided for old code. The AVR support in it has never worked and should be ignored.

Sent from my SM-T555 using Tapatalk


majenko

Sat, 11 Jun 2016 19:06:54 +0000

One more thing: compiling pic32prog from source for your aged operating system, once you have all the needed libraries installed from source, will also most likely be needed.

Sent from my SM-T555 using Tapatalk


majenko

Sat, 11 Jun 2016 19:08:29 +0000

Effectively you are running the equivalent of Windows XP and wondering why you can't run Edge on it.

Sent from my SM-T555 using Tapatalk


bperrybap

Sat, 11 Jun 2016 21:00:22 +0000

Well, I highly disagree. The XP analogy is way off base. We are talking about a linux LTS release that is still supported. Not some crappy Windoze OS..... that has not been supported for many years. This isn't an IDE issue, this is a chipKIT core issue. None of the other 3rd party cores I'm using have any issues, including Teensy which does not use avrdude. It seems kind of foolish to just totally write off an entire LTS linux release.

In the past 8 years, I've only had a situation like this (where there was no easy patch or way to install an update from a repo to make it work) happen one other time with a 3rd party s/w package and I worked with the vendor to resolve it.

Shared libraries have created so many issues and I've fought with them and been burned by them for decades. I've seen many cases where developers jump to newer versions when the older libraries would continue to work. Weren't you even recently fighting with some shared library libusb issues in pic32prog yourself... ;) (Oh, the joy of shared libraries....)

Sounds like I'm going to have to go off and do some building from sources to make it work. You know I really want to like the chipkit stuff and the h/w is far superior than most of the Arduino boards including boards like DUE, but even after playing with an UNO32 for more than 4 years, I still run into issues when trying to use it with Arduino s/w that could never be resolved by the typical Arduino user.

--- bill


bperrybap

Sat, 11 Jun 2016 21:45:06 +0000

now the configure for pic32prog is bitching about libusb-1.0 not being found, when it is definitely installed. Arg.... what a pain.


bperrybap

Sun, 12 Jun 2016 00:39:19 +0000

so I decided to put the mint13 rebuild on the back burner for a while and use mint17 by mounting my mint13 sketchbook. That works, however, uploads are not reliable and I'm seeing i2c issues with the chipkit core using an UNO32 on IDE 1.6.9. There seems to be some sort of issue with the chipkit core when you open a new window for a sketch. During the upload attempt, the uno32 leds flicker and upload fails claiming it cant find a device. The only way to resolve it is to completely exit the IDE, and unplug the board and plug it back in and bring the IDE back up.

For the i2c issue, something is tripping up the ic2 support. Not yet sure what is going on but the i2c master (uno32) keeps spewing out a start and the slave address.

I do some auto probing and perhaps that is triggering something. It all works fine on many different other boards and cores across many different i2c lcd interface chips. I'll track it down. It may be a while as I don't really want to be working on tracking down i2c issues right now.

--- bill


majenko

Sun, 12 Jun 2016 08:19:30 +0000

It's very much like XP. Discounting the fact that XP is a huge rancid pile of badger vomit. It's an older operating system which people are still using and, until recently, was still supported. But because it is a number of versions of out of date a proportion of modern software will not run on it.

As a Linux developer you do not get a choice as to what versions you link against when it comes to shared libraries, especially system level ones like libc etc. The only thing you can do is to compile the software on an older version of an operating system and hope there is upwards compatibility. Since we don't compile pic32prog it is down to whatever operating system Serge is running. And chances are that is something pretty current.

When you install a library in Linux it usually comes in at least two parts; the binary and the development parts. You need to install the libusb 1 "-dev" package in order to compile software that uses it.

My work recently with it had to do with the removal of libusb 0.9 which was also required in addition to libusb 1.0 for just one adapter. That adapter has now been rewritten to use the libusb 1 API which is imposed on us by the use of hidapi for all the other USB based adapters. It was a bit stupid having have the two, so now it just needs the one.

I have experienced similar frustrations running Debian in the past before they brought out Jessie. Their stubborn refusal to upgrade core libraries to current versions meant that many precompiled packages for Ubuntu had no hope of ever running on it. I ended up upgrading to the unstable development branch of debian in order to run modern software. Since Jessie thought it has become much more compatible. Until the next big step in system libraries...

FTDI interfaces have always been a bit of a bugbear. They seriously broke the windows drivers a while back and special measures have had to be put in place in the Arduino IDE and even in pic32prog. There is always a chance that those may be affecting the automatic DTR operation in Linux. It's an easy fix though:

$ stty -F /dev/ttyUSB0 hupcl

That should get it working again without having to unplug everything and close down the IDE.

Sent from my SM-T555 using Tapatalk


majenko

Sun, 12 Jun 2016 08:20:52 +0000

I2C: you do have pull-up resistors on your SDA and SCL lines don't you?

Sent from my SM-T555 using Tapatalk


majenko

Sun, 12 Jun 2016 11:24:46 +0000

I have just installed a VM of Linux Mint 13. It has libusb 1 available, however it looks to be a rather old version (1.0.9), so you will need to upgrade it. I have just built it from source using the latest Debian Jessie source package (1.0.19). It takes a while to install all the build dependencies (it needs doxygen which has to install all of LaTeX in order to build the documentation), so I have made a "precise" repository for it. Both 32 and 64 bit versions are available.

// Add to /etc/apt/sources.list:
deb http://majenko.co.uk/debian precise main
// Get the key:
$ wget -O - -q http://majenko.co.uk/debian/key.asc | sudo apt-key add -
OK
// Update apt:
$ sudo apt-get update
// Upgrade if libusb is already installed (if you don't do a dist-upgrade it keeps libusb back because it wants to install an extra package libusb-1.0-doc):
$ sudo apt-get dist-upgrade
// Or if it's not then install it:
$ sudo apt-get install libusb-1.0-0-dev

If you don't want to go through all that you can manually download and install the .deb files for 1.0.19:

  • [url]http://majenko.co.uk/debian/pool/main/libu/libusb-1.0/[/url]

Now install the other dependencies you need for building:

$ sudo apt-get install git build-essential autoconf libtool libudev-dev

You should now be able to build pic32prog:

$ git clone https://github.com/sergev/pic32prog.git
...
$ cd pic32prog
$ make

You should now have a "pic32prog" binary in the current directory. You just need to copy that one over the one installed by chipkit-core. However, if you are using UECIDE 0.8.9-pre(x) you can just place it somewhere in your $PATH and use the "System Installed PIC32Prog" programmer which I have just created.

Alternatively, once you have libusb-1.0-0 version 1.0.19 installed, you can use one of the binaries attached to this post which I compiled on Mint 13.


bperrybap

Sun, 12 Jun 2016 16:25:20 +0000

I2C: you do have pull-up resistors on your SDA and SCL lines don't you?

Of course. I'm the one that exposed using the wire code after re-initalization (calling begin() again) was causing a hard hang and tracked it down due to the h/w getting falsely confused over clock stretching after the h/w was reinitialized. So yes, I'm familiar with i2c. --- bill


majenko

Sun, 12 Jun 2016 16:30:18 +0000

That's OK then. I just have to make sure of these things - many Arduino users don't know about pullups on I2C since the Arduino boards by default use the internal pullups, which really is very nasty. I suspected you probably did know more than enough to have pullups, but if I hadn't asked and in the end it turned out you didn't have them we'd both feel daft ;)

So can you post some example code that demonstrates the issue you are seeing?


bperrybap

Sun, 12 Jun 2016 17:00:32 +0000

So can you post some example code that demonstrates the issue you are seeing?

Sure, once I track it down and isolate it down to a small repeatable example. I always like to fully understand the issue and often the fix and/or work arounds before reporting it.

The whole mint 13 thing is because I have older machine that I'm still using for some development until I fully cut things over to some new h/w. But it is part of a much larger cutover involving much more than just this single machine & OS. The systemd nightmare that has cropped up the past few years, along with the GTK2/GTK3 gnome2/gnome3 mess along with the recent desktop wars has really made a mess of linux (at least the debian based ones) over the past few years. I do have other other machines running newer versions and often use VMs for development and testing across many different OSes but wanted to bring up that it seemed very odd have a commandline tool not work on such a mainstream LTS OS, especially since neither the Arduino IDE nor any other Arduino core has this issue/limitation.

That and there seems to be some pic32prog uploading issues even on newer Mint versions (17.1) where everything "works". It seems to be related to opening multiple IDE windows and possibly aggravated by switching between different boards/cores - which I happen to do quite often during my testing.

I'll track down the issues and post appropriate findings as either new threads or git issues, it is just that I'm in the final stages of trying to push out a new set of libraries and didn't want to get bogged down and dragged into toolset issues.


majenko

Sun, 12 Jun 2016 17:25:22 +0000

Well, you have all the tools you need there to get it working on Mint 13. Incidentally, the same pic32prog binary cannot run on both mint 13 and anything newer. The libraries on Mint 13 are just too old. It complains about not finding libudev.so.0 since libudev is now on 1.5.0 - a considerable increase from 0.whatever.itwas.

pic32prog is more than just a serial STK500V2 protocol uploader. It also deals with a number of USB based programmers and other bootloaders, so the USB support is kind of integral to it. Yes, it could probably be re-written in huge chunks to not use some of the libraries, but you're still likely to run into similar problems with not having a library that it needs that's a new enough version.

The systemd nightmare that has cropped up the past few years,

I used to think so. Now, though, after building an ARM Linux distro from Jessie base and implemented a number of systemd targets and services for it, I find it a very nice clean system. I love it. It takes some getting used to, but it's really nicely integrated. It works really well.

along with the GTK2/GTK3 gnome2/gnome3 mess along with the recent desktop wars has really made a mess of linux (at least the debian based ones) over the past few years.

That's why I run Debian. You don't suffer from that kind of thing when you're using the distro that all the other systems that are fighting between themselves are based on. Yes, it can be a bit sluggish with updates, but you don't get the stupidity that you get with some - especially how Ubuntu keep breaking package dependencies with their idiotic version extensions and requiring precise version numbers in their packages. Plus Debian doesn't impose a desktop on you. You just install the one you want to use. At the moment I'm using KDE since it works well with my dual video cards. It's not my favourite, but it works.

That and there seems to be some pic32prog uploading issues even on newer Mint versions (17.1) where everything "works". It seems to be related to opening multiple IDE windows and possibly aggravated by switching between different boards/cores - which I happen to do quite often during my testing.

Is that the locking up the port thing you mentioned earlier? Does the stty command unlock it for you? It'd be interesting to know if it is clobbering the hupcl setting, and to track down just where it's coming from. It may be something from deep inside Java though. It's not something I seem to see with UECIDE, so it may be specific to the Arduino IDE. Maybe something to help get around the complete ****up they made with FTDI based boards in 1.6.8.


bperrybap

Sun, 12 Jun 2016 20:14:19 +0000

Well, you have all the tools you need there to get it working on Mint 13. Incidentally, the same pic32prog binary cannot run on both pic32prog is more than just a serial STK500V2 protocol uploader. It also deals with a number of USB based programmers and other bootloaders, so the USB support is kind of integral to it. Yes, it could probably be re-written in huge chunks to not use some of the libraries, but you're still likely to run into similar problems with not having a library that it needs that's a new enough version.

avrdude also does more than serial transfers and uses libusb as well, but it doesn't have this issue. I can run the avrdude binary on multiple platforms and even build avrdude from sources and not have issues like this.

I used to think so. Now, though, after building an ARM Linux distro from Jessie base and implemented a number of systemd targets and services for it, I find it a very nice clean system. I love it. It takes some getting used to, but it's really nicely integrated. It works really well.

systemd has some really nice features but from a security standpoint it is just plain scary. Just like SELinux. While they do make some things simpler and have interesting new management features and security capabilities they also push large amounts of trust out of the kernel and into userspace processes, and both make it trivial to hide back-doors that are easy to install and exploit and yet difficult to detect since they both include "useful" configuration options/capabilities that look secure and offer great management capabilities but can be easily silently compromised from the network, without ever touching the machine or any of its files or settings. They both allow malicious privileged processes or malicious network actors to be able to do things that can be used compromise security in ways that could never be done before. i.e. from a functional stand point it doesn't matter where code runs (user space or kernel) but from an overall security standpoint it can make a big difference. but all that is way off topic.

Is that the locking up the port thing you mentioned earlier? Does the stty command unlock it for you? It'd be interesting to know if it is clobbering the hupcl setting, and to track down just where it's coming from. It may be something from deep inside Java though. It's not something I seem to see with UECIDE, so it may be specific to the Arduino IDE. Maybe something to help get around the complete ****up they made with FTDI based boards in 1.6.8.

So I tracked this down a bit more. the stty command doesn't help in this case, it merely resets the target chipKIT board. When in this state, during the upload, there is some traffic going to the UNO32 and ld1 blinks 3 times then pic32prog reports: "No Target Found" It appears to be related to serial output. Here is a minimal sample sketch that triggers this issue. // test for pic32prog upload issue

void setup()
{
    delay(5);
    Serial.begin(9600);
}

void loop()
{
    Serial.println("Hello, World");
    Serial.println("-------------------------------------------------");
    delay(1000);
}

upload the sketch and let it run for a few seconds. You will see ld2 blink each time the data squirts out of the pic32. However after about 4 iterations, something changes (maybe the FTDI usb buffer fills) and the led ld2 stops blinking. At this point uploads will fail. The only way out of this, is to:

  • pull the cable, re-attach it
  • start another upload after the "no target found" error while ld4 is still blinking In either case above you must do an upload while ld4 is still blinking before the sketch has run and fills up buffers inside the FTDI chip. If you wait until the ld4 is no longer blinking and ld2 has stopped blinking, you can never upload a sketch and you will get the "No Target Found" error. NOTE: pressing reset on the board does not fix this.

Of curious interest is that If you set the baud rate to 115200 it does not fail.

It is looking like there is some kind of issue in pic32prog with the way it handles the port. Maybe it doesn't flush out the old FTDI buffered serial data correctly? I don't know, but that should be enough to replicate it and track it down.

On a Arduino AVR Uno board I have that uses the FTDI chip, the transmit led behaves the same but avrdude does not have this issue. avrdude can reset and upload the AVR Uno board just fine even after the FTDI transmit led has stopped blinking.

--- bill


majenko

Sun, 12 Jun 2016 20:32:49 +0000

This definitely has something to do with the control of the DTR signal. I don't see it in UECIDE becuase the IDE itself manually toggles DTR and all is well.

If you run pic32prog manually, the first time it uploads properly. However it seems to then leave the DTR in a bad state and it won't reset the board from then on.

Using the stty -F /dev/ttyUSB0 hupcl command resets the port to the right state, and pic32prog will work again - once.

I need to take a look and see what it is doing with the serial port to see why the DTR is getting locked out like that.


majenko

Sun, 12 Jun 2016 20:41:42 +0000

Found a bug that meant the serial port's settings weren't getting restored properly under some circumstances. PR submitted.


majenko

Sun, 12 Jun 2016 20:44:44 +0000

I guess more libraries could be statically compiled into pic32prog instead of relying on dynamic libraries - that's probably what avrdude does.

The only reason you need to have a more up to date libusb1 to compile pic32prog is that it happens to use some particularly low-level calls that aren't in the older version. This is specifically for a bit-banged FT232 based ICSP programmer. It was that which was using libusb0 before, and upgrading it to libusb1 had to use some functions that had only recently been added.


majenko

Sun, 12 Jun 2016 20:48:45 +0000

The only thing that can't be statically linked, it seems, is libudev - and that makes sense, since it is tied into the operating system at a low level and if you try using the wrong version then all hell will break loose.


bperrybap

Mon, 13 Jun 2016 00:11:02 +0000

I looked here for the issue: [url]https://github.com/sergev/pic32prog/issues[/url] but didn't see a new issue. Is the repo somewhere else?

It seems odd that it is a DTR handling issue since I see the board always getting reset. The failure seems to occur when the FTDI chip has been given a bunch of bytes with before pic32prog is run.

For the time being, I've got a wrapper script that does a retry if the pic32prog upload fails and that works since the first upload attempt resets the board and second starts before the sketch has a time to push out any serial data since the boot-loader is so slow at starting up the application code.

--- bill


bperrybap

Mon, 13 Jun 2016 05:25:08 +0000

So I tracked down the I2C issue. note: this has nothing to do with Mint13 but since i mentioned it earlier, I thought I do a followup.

After many hours with a logic analyzer, here is what happening. MPIDE 0023 works. MPIDE 0150 and the latest chipkit core both have an issue but break slightly differently. (all 3 have different code in this area, with the 0023 code being an entirely different low level twowire code)

It turns out if you call Wire.beginTransmission(address) and then call Wire.endTransmission() If you then call Wire.beginTransmission(address) again, with no delay, things scew up. The reason to do this is when probing the i2c bus for devices. The endTransmission() returns the ACK/NACK status so you can tell if there is device there with that address. From experimentation there needs to be a delay of at least 20us between the endTransmission() and the next beginTransmission() The 0150 MPIDE Wire code seems to get stuck sending out the same address over and over again. The latest Wire code in the Arduino core, in beginTransmission() checks the bus status and then aborts thinking someone else has the bus. I don't believe this is a slew rate issue since when doing back to back data transfers there is only 17us between each byte.

There is nothing in the i2c spec that mandates any sort of delay here so I'm not sure why the delay is needed. Maybe the pic32 i2c system is trying to give other masters more time to jump in? In any case it isn't obvious that there needs to be a delay here as no other cores require this.

Not sure if this is really a bug or if it is pic32 i2c h/w limitation that needs to be documented.

--- bill


majenko

Mon, 13 Jun 2016 08:49:04 +0000

Which board are you using for this? It may be something specific in the silicon of the chip on that board. I have a large range of boards here that I can test it on to see if it's something in the core, or something in the chip.

Also, what I2C device(s) do you have connected up? It may be something on the bus that's interfering in some way and holding the clock line low for a short period when it shouldn't, or causing noise on the data line making the master think there's a collision.


majenko

Mon, 13 Jun 2016 08:53:58 +0000

I looked here for the issue: [url]https://github.com/sergev/pic32prog/issues[/url] but didn't see a new issue. Is the repo somewhere else? It seems odd that it is a DTR handling issue since I see the board always getting reset. The failure seems to occur when the FTDI chip has been given a bunch of bytes with before pic32prog is run. For the time being, I've got a wrapper script that does a retry if the pic32prog upload fails and that works since the first upload attempt resets the board and second starts before the sketch has a time to push out any serial data since the boot-loader is so slow at starting up the application code. --- bill

It's a pull request, not an issue: https://github.com/sergev/pic32prog/pull/43

Simply, when a new baud rate was being selected, the current terminal status was being saved. It shouldn't have been. The normal course of action is you open the serial port, save the termios data somewhere, put in place your own settings, do whatever you want on serial, then put back the settings that you saved and close the port. When selecting an alternate baud rate the current settings were being saved again. That would overwrite the real saved settings with the current custom settings, so when the port was closed the wrong settings were being put back leaving the port in a bad state.

By opening the port and DTR not being asserted it cleared out the FTDI's buffers and allowed the LEDs to blink again briefly giving the appearance of a reset. I confirmed it wasn't resetting on my oscilloscope - there was no low blip on the reset line after the first use of pic32prog.


bperrybap

Mon, 13 Jun 2016 16:38:08 +0000

Which board are you using for this? It may be something specific in the silicon of the chip on that board. I have a large range of boards here that I can test it on to see if it's something in the core, or something in the chip. Also, what I2C device(s) do you have connected up? It may be something on the bus that's interfering in some way and holding the clock line low for a short period when it shouldn't, or causing noise on the data line making the master think there's a collision.

I'm using an UNO32 serial # D402405 purchased in Dec 2011. I'm testing with PCF8574 and MCP23008 devices. But for what is going on, they really are not involved with bus.

I didn't see anything looking out of place looking on the clock or data lines. See the attached analyzer shots of with and without the delay. The sck clock is only 100khz and analyser sample rate is 24Mhz. You can see the time between the stop and the next start.

The code running is attempting to discover devices by probing addresses starting at address 0x20 and incrementing by 1 Without the delay you will see what looks like addresses skipping, but in fact what is happening is that the code in beginTransmission() is rejecting requests for a period of time and so the requests for those addresses are silently dropped on the floor since the function is a void function. The other code as a 100us delay after the endTransmission() before next beginTransmission().

Different versions of the code hand beginTransmission() differently, here is the latest beginTransmission()

void TwoWire::beginTransmission(uint8_t address)
{
    DTWI::I2C_STATUS i2cStatus = di2c.getStatus();

    // if someone else has the bus, then we won't get it; get out
    if(i2cStatus.fBusInUse  && !i2cStatus.fMyBus)
    {
        return;
    }
   
    // we only want to loop on this with a repeated start
    // otherwise it will pass on the first try 
    while(!di2c.startMasterWrite(address) && di2c.getStatus().fMyBus);
}

What is happening is that for about 20us after a previous endTransmission() that if statement aborts the master start setup by returning. I'm not sure why, but from a larger perspective, it seems bad to have a function that can behave two different ways, one of them a fatal error and not return any status. Given that the Arduino version is a void, it creates a portability issue if the chipKIT code were to return a status. Wouldn't it be better to spin here either forever or perhaps with a timeout? so that it "just works" rather than just silently aborting/failing.

--- bill


majenko

Mon, 13 Jun 2016 17:19:59 +0000

I guess we need to narrow it down to which of those two terms is causing the negative result - is it that it thinks the bus is in use (fBusInUse) or that it's not the owner of the bus (fMyBus)?

The former is simple the state of the S bit in the I2CxSTAT register - a flag that says if a start bit has been seen. The latter is slightly more complex, being:

fMyBus          = fI2COn && !fBusError && fBusInUse && curStateFreeze != I2C_IDLE;

A fBusError is if the "curStateFreeze" (whatever that is) is equal to I2C_BUS_ERRORm or the BCL bit in I2CxSTAT register being true (BCL is Bus CoLlision). So it has to be turned on, not an error, in use, and not idle for the bus to be considered "mine". So if it turns out to think it's not "mine" then we'd need to then dig deeper to see which of those 4 terms is saying the wrong thing.

So I'd start with splitting that "if" into two separate ones and performing some form of debugging (Serial print, light an LED, whatever) to see which of them is triggering it.


bperrybap

Mon, 13 Jun 2016 17:25:29 +0000

In the i2c spec: [url]http://www.nxp.com/documents/user_manual/UM10204.pdf#G1659003[/url] table 10 page 48 the min bus free time tBUF between stop and start for standard mode (100Khz) is only 4.7us but you can insert an additional delay of 15us, and the Wire code will still have the issue.

--- bill


majenko

Mon, 13 Jun 2016 18:11:37 +0000

Ok, using a WiFire Rev C (the newest one with the least silicon bugs) I am seeing exactly what you describe.

#include <Wire.h>

void setup() {
    Wire.begin();
}

void loop() {
    for (int i = 20; i < 60; i++) {
        Wire.beginTransmission(i);
        Wire.endTransmission();
    }
}

It skips and skips and skips, to the extent that the addresses appear almost random. Add 20µs delay into the very beginning of beginTransmission() and you get a perfect incrementing of addresses.

So if it is something in the silicon then it's something that has been in the silicon since way back when and has never been either spotted or fixed in the numerous copy-and-pastings of that logic block in the designs since then.

So now to debug...


bperrybap

Mon, 13 Jun 2016 18:30:06 +0000

From the comment it looks like there are some h/w issues that are attempting to be worked around.

So here is the state of the flags when it occurs: TwoWire begin abort: curStateFreeze:0, fBusInUse:1, fBusError:0, fI2COn:1, fMyBus:0, curStateFreeze!=I2C_IDLE:0

I don't understand enough about the h/w and how the state machine works (without spending more time than I want to ) to be able able to comment much further.

The older MPIDE wire code didn't have this issue, but then it was different code and it didn't do all these checks so maybe multi master didn't work on that older code.

--- bill


majenko

Mon, 13 Jun 2016 18:32:50 +0000

OK, I think I see what is happening here actually...

It's not a case of delaying between transfers, but actually a case of delaying during transfers. I think the reason it's failing is because the new beginTransfer() is being called whilst the previous one is still happening.. The state I2C_IDLE is set in the interrupt routine when the .P flag is set (STOP condition detected). Since that's interrupt driven it's asynchronous, and there is no blocking waiting for the previous one to finish before we start the next one.

So I think the problem is actually going to be in endTransmission that isn't properly detecting that the transmission is still in progress and waiting for it to finish properly.

Looking at the return value of endTransmission() it's returning 2 every time with nothing on the bus:

// if not my bus, then the beginMaster failed and we either had
    // a collision or the slave acked, in either case report a NACK from the slave
    if(!di2c.getStatus().fMyBus)
    {
        return(2);
    }

So it looks like it thinks it doesn't own the bus. But why? Let's break the fMyBus down and take a look...

Ok. By adding some more checking for the individual parts in that if, it looks like fBusError is being set. So that is either a collision (I doubt it) or the current state being I2C_BUS_ERROR. I can not (yet) fathom the logic that is setting I2C_BUS_ERROR (it is very cryptic). I need to dig into interrupt registers to work it out.

Oh, and I can definitely confirm that commenting out that entire "if" cures the problem.


majenko

Mon, 13 Jun 2016 18:37:33 +0000

Oh hang on, Heisenberg's rearing his ugly head. Ignore (for the moment) my comments about that "If" block - the act of measuring the effect changed the effect. I need to dig more.


bperrybap

Mon, 13 Jun 2016 18:42:13 +0000

I wonder if this delay they use in the DTWI DTWIscanner example is in there because of this same issue:

for(address = 8; address < 127; address++ ) 
	{
		// The DTWIscanner uses the return value of
		// the DTWI0.stopMaster() to see if
		// a device did acknowledge to the address.
		dtwi0.startMasterWrite(address);
		delay(10);
		if(!dtwi0.stopMaster())
		{
			Serial.print("I2C device found at address 0x");
			if (address<16) Serial.print("0");
			Serial.print(address,HEX);
			Serial.println("  !");
			nDevices++;
		}
	}

I don't understand why a delay would be needed. --- bill


majenko

Mon, 13 Jun 2016 18:43:39 +0000

OK, yes, it is definitely to do with that bit of code. I have changed it now on mine to do a di2c.stopMaster() when a bus error is detected during Wire.endTransmission().

// if not my bus, then the beginMaster failed and we either had
    // a collision or the slave acked, in either case report a NACK from the slave
    if (!i2cStatus.fBusError) { // We didn't get an ACK, so let's flush and return
        while(!di2c.stopMaster());
        return 2;
    }

    if (!i2cStatus.fBusInUse) { // The bus is being used by someone else. Just return.
        return(2);
    }

    // Catch-all for other possible causes.
    if(!i2cStatus.fMyBus)
    {
        return(2);
    }

That cures this problem, but what other effects it would have I really don't know.


majenko

Mon, 13 Jun 2016 18:46:58 +0000

Ok, back tracking a little here, I realised I had some test logic backwards (?!?!!!!). It's the fBusInUse flag that's making it fail.


majenko

Mon, 13 Jun 2016 19:00:43 +0000

Argh! This is brain melting!

Ok, fMyBus is saying false because the mode is idle. Therefore it's just returning without ending the master mode properly. It's saying it's idle because ... well, that's the puzzle now. Trying to find where in this mess the state is being set to IDLE when we get a NACK.