New I2C library for Teensy3

I have been compiling codes with i2c_t3 with no problem for Teensy 3.0 board type, but if I switch to Teensy 3.1 board type I get errors of the type:
'C:\Users\chris\Documents\Teensy_6_12_13\arduino-1.0.5/master.ino:326: undefined reference to `i2c_t3::beginTransmission(unsigned char)'

For example, I try to compile the example Master.ino in the i2c_t3 library. It compiles fine with Teensy 3.0, but I get the errors using Teensy 3.1 type. (No changes to the code itself at all.)
I am using the V6b library and Arduino 1.0.5.

Is there something else that needs to be switched for use with Teensy 3.1?
 

Attachments

  • master.ino
    16.3 KB · Views: 136
Last edited:
I need to do non-blocking write then read requests to an ic2 client (I am the master) in order to read the value of a register on the client.
I have looked at the various methods and the code, and I see that the low level code is capable of doing a transmit followed by a receive, but I can only see how to do a general request (i.e. address the client's address with the read bit set) not how to set up a write of the address (with read bit) and the register number followed by a receive. Is this possible, if so how, if not what is the simplest way to do a register read in a non-blocking fashion?

The way I2C works, is that in receive operation it sends the target address with the READ bit set, then on the next byte the direction reverses and the master can receive data from the slave. There is no such "extended" READ operation which combines a multi-byte write, and then the READ. However you can achieve this using a two-step process as follows.

If the device requires setting up a register address or such, then you do that by first sending a WRITE command with the settings (register address, subcommands, etc), using the I2C_NOSTOP flag, then the READ command to capture the response. The preceding I2C_NOSTOP flag will cause the subsequent READ command to send a Repeated-START (without an intervening STOP), and the device will recognize the WRITE + READ operation as a single continuous operation.

The method Swap_File shows above is correct for doing this using entirely non-blocking operations (non-blocking WRITE (with I2C_NOSTOP), wait for done, then non-blocking READ, wait for done, then read Rx buffer).

Try something like that first. If you still have problems, send what device type you are trying to talk to along with a link to the datasheet. We can probably code up a routine for it in short order.
 
I have been compiling codes with i2c_t3 with no problem for Teensy 3.0 board type, but if I switch to Teensy 3.1 board type I get errors of the type:
'C:\Users\chris\Documents\Teensy_6_12_13\arduino-1.0.5/master.ino:326: undefined reference to `i2c_t3::beginTransmission(unsigned char)'

For example, I try to compile the example Master.ino in the i2c_t3 library. It compiles fine with Teensy 3.0, but I get the errors using Teensy 3.1 type. (No changes to the code itself at all.)
I am using the V6b library and Arduino 1.0.5.

Is there something else that needs to be switched for use with Teensy 3.1?

You need to list what kind of build environment you are using, it is Teenyduino (what version?) and Arduino? Is it Eclipse, or some Makefile or such. For Teensyduino+Arduino, I don't think I've seen build errors as long as the pulldown menu options are set correctly. For other build environments it is more complicated and you need to have the linker and symbols setup correctly.
 
I ended up accidentally using this library. I had breadboarded a circuit with the MCP23017 I2C expander, using the Adafruit library; this worked. I then laid out a PCB and it was more convenient to use the alternate I2C pins. I had somehow imagined that setSDA and setSCL were already implemented, oops. Its now working with i2c_t3 instead of Wire. I had to make a hacked copy of the Adafruit library (just a rename, different include, and changed
Code:
Wire.begin();
to
Code:
Wire.begin(I2C_MASTER, 0x00, I2C_PINS_16_17, I2C_PULLUP_EXT, I2C_RATE_400);
.
 
Incidentally the MCP23017 is supposed to work at 100kHz, 400kHz, and 1.7Mhz. I briefly tried
Code:
Wire.begin(I2C_MASTER, 0x00, I2C_PINS_16_17, I2C_PULLUP_EXT, I2C_RATE_1500);
without success. I'm using external 2k2 pullups, maybe that speed needs smaller ones.
 
Incidentally the MCP23017 is supposed to work at 100kHz, 400kHz, and 1.7Mhz. I briefly tried
Code:
Wire.begin(I2C_MASTER, 0x00, I2C_PINS_16_17, I2C_PULLUP_EXT, I2C_RATE_1500);
without success. I'm using external 2k2 pullups, maybe that speed needs smaller ones.

Yes the speeds are very dependent on wiring and pullups. If your devices have strong pulldown capability you can get aggressive and remove the external pullups and switch it to internal pullups (very low resistance ~200 ohms). I've run back-to-back T3s using internal pullups only, and I can get the 2.4MHz freq to run.

Also there are many freq settings between 400k and 1.5M, so you can iterate through the settings to see if an intermediate freq will work.
 
All,

I'm preparing an update for this library. It isn't done yet, I'm working on it now, but one of the recurring themes in the thread is that of renaming the library (for those that don't like names to be a jumble of letters/numbers/underscores). I'm ok with that. I'm looking for input as to the preferred name. The following are previous suggestions:

Definitely prefer "FastWire" for the library name. Am currently using this library in my TeensyNet Project, and will be using "FastWire" for my library. Already tested both I2C channels with 24LC512s and MCP23017s.

if you name it "WireFast" or some other name where the first 4 characters are "Wire", then it'll show up next to Wire in the File > Examples menu, and in alphabetically ordered lists on websites. Seems like that might help people see there's an alternative.

FastWire has a negative in that there are already some Arduino libs using that name (for AVR I think). WireFast seems unused, although I didn't look hard. Could also sub thesaurus words for "fast", something like hyperWire.

Anyway open to suggestions (if nothing else maybe I'll just add some more letters/numbers/underscores to i2c_t3).
 
Since it is currently limited to use with the Teensy 3.1 I would suggest TeensyWire.h to make it clear that this is a Teensy-only Wire.h-like library. It could also be Teensy3.1Wire.h but that is a bit cumbersome!
 
Here is a teaser on the upcoming lib, these begin() lines have a couple new elements which some might spot. Analyzer plots go with the respective lines. Of interest is the bottom wave in each plot. That indicates I2C ISR activity. Also of interest is how similar the SDA/SCL waves are. Regardless of control method the I2C peripheral appears to be bottlenecking the throughput. This is likely the highest I2C performance that these interfaces can manage.

I have other improvements also, but I'm still testing it all, so no release just yet.

Code:
[B]Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_3000, I2C_OP_MODE_ISR);
[/B]
screenshot.390.jpg

Code:
[B]Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_3000, I2C_OP_MODE_DMA);
[/B]
screenshot.389.jpg
 
I would actually not change the name. This library has already made a name for itself ;-)
Looking forward to new version!
 
All, I've uploaded the new v7 library, and modified the top post accordingly. I'll try to summarize the changes here.

Clocking

The library now supports all Teensyduino F_BUS frequencies: 60MHz, 56MHz, 48MHz, 36MHz, 24MHz, 16MHz, 8MHz, 4MHz, 2MHz
In addition new rates have been added: I2C_RATE_1800, I2C_RATE_2800, I2C_RATE_3000

The supported rates depend on the F_BUS setting which in turn depends on the F_CPU setting. The current F_CPU -> F_BUS mapping (Teensyduino 1.21), is as follows. For a given F_BUS, if an unsupported rate is given, then the highest freq available is used (since unsupported rates fall off from the high end).

Code:
                                             I2C_RATE (MHz)
F_CPU    F_BUS    3000 2800 2400 2000 1800 1500 1200 1000  800  600  400  300  200  100
-----    -----    ---------------------------------------------------------------------
 168M     56M            y    y    y    y    y    y    y    y    y    y    y    y    y
 144M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
 120M     60M       y    y    y    y    y    y    y    y    y    y    y    y    y    y
  96M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
  72M     36M                           y    y    y    y    y    y    y    y    y    y
  48M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
  24M     24M                                     y    y    y    y    y    y    y    y
  16M     16M                                               y    y    y    y    y    y
   8M      8M                                                         y    y    y    y
   4M      4M                                                                   y    y
   2M      2M                                                                        y

The rates are not directly equivalent to SCL clock speeds. I've measured the SCL rates for the 48/56/60MHz F_BUS speeds on a logic analyzer (refer to notes in .cpp file, setRate function), and the results are inconsistent. The peripheral limits the actual SCL speeds to well below the theoretical speeds. To get a better idea of throughput I've measured the transfer time for a 128 byte transfer across different F_CPU / F_BUS / I2C_RATE combinations (specifically the interesting overclock speeds). This is shown below.

screenshot.391.jpg

A few takeaways here, are:
1) To the first order, it doesn't really matter what F_CPU / F_BUS combination you use, for a given I2C_RATE the variation is only slight.
2) The 48MHz bus speed seems to work slightly better than the irregular 56MHz / 60MHz speeds.
3) The F_CPU appears to be more important than F_BUS, as the peak performance is at the 144MHz / 48MHz corner.
4) The difference from standard 100kHz Arduino rate to the peak rate is about 10x. Likewise from standard 400kHz rate to peak rate is about 2.5x.


New Operating Modes

Old versions of the library were exclusively interrupt based. There are now two new modes of operation: DMA and Immediate. These modes are only for Master operation.

The library supports DMA mode transfers for Master send and receive. DMA mode has little to no effect on I2C operating speed, however it does greatly reduce the number of ISR calls needed to service the I2C. You can observe this in the following captures, whereby the bottom plot in each indicates the ISR activity.

Interrupt Mode:
screenshot.397.jpg

DMA Mode:
screenshot.396.jpg

The gain that can be expected from this depends on a particular applications traffic. For many applications it may be marginal. On a 256 byte transfer at 400kHz, I've measured about a 10% increase in available CPU time when using DMA. So for a large background task such as driving a display, or using I2C as a networking channel, it may be beneficial. For small message, intermittent traffic such as sensors, there may be little benefit.

Unfortunately there is no DMA mode for Slave operation. I'll elaborate a bit on this and other DMA .. issues .. below.

Also, in cases of unavailable DMA channels, the library is configured to automatically fall back to standard interrupt mode.

The other new mode is Immediate. In this mode the ISR is not used, the call will loop and wait for the I2C operations to complete. As such this mode is always blocking regardless of call. Configuring for Immediate mode essentially makes the library operate the same as the standard Wire library. However this mode is also utilized in special cases involving priority (see next).


Priority Escalation

Since the library is generally configured to be interrupt based, there is always the problem of someone launching I2C calls from inside a higher-priority interrupt, thereby blocking the I2C ISR. To fix this, prior to engaging the ISR, the library will first try to determine the priority of the calling function, and if necessary it will adjust the I2C priority to a high enough level to exceed that of the calling function. If this is not possible (eg. calling function has a priority of zero), then it will revert to Immediate mode. As such it should not be possible to block the I2C from running.


New Functions

The following functions have been added to support the above features:
1) Added new begin() functions to allow setting the initial operating mode. This just adds an operating mode argument to the existing functions. If the mode argument is not specified then begin() calls will default to ISR mode (same as previous behavior):
  • begin(i2c_mode mode, uint8_t address, i2c_pins pins, i2c_pullup pullup, i2c_rate rate, i2c_op_mode opMode) - Master or Single-address Slave
  • begin(i2c_mode mode, uint8_t address1, uint8_t address2, i2c_pins pins, i2c_pullup pullup, i2c_rate rate, i2c_op_mode opMode) - Address-range Slave
  • whereby i2c_op_mode can take the following values: I2C_OP_MODE_ISR, I2C_OP_MODE_DMA, I2C_OP_MODE_IMM
2) Added new functions:
  • uint8_t setOpMode(i2c_op_mode opMode) - used to change operating mode on the fly (only allowed when bus is idle)
  • void sendTransmission() - non-blocking Tx with implicit I2C_STOP, added for symmetry with endTransmission()
  • uint8_t setRate(uint32_t busFreq, i2c_rate rate) - used to set I2C clock dividers to get desired rate. busFreq allows devices which alter their running frequency to recalibrate the I2C rates to the new freq. This form uses an i2c_rate enum argument.
  • uint8_t setRate(uint32_t busFreq, uint32_t i2cFreq) - used to set I2C clock dividers to get desired SCL freq. busFreq allows devices which alter their running frequency to recalibrate the I2C rates to the new freq. This form uses a uint32_t frequency argument (quantized to nearest i2c_rate based on empirical measurements)
3) Added new Wire compatibility functions (mostly uint8_t type casts):
  • void setClock(uint32_t i2cFreq) - (note: this is actually a degenerate form of setRate() with busFreq == F_BUS)
  • uint8_t endTransmission(uint8_t sendStop)
  • uint8_t requestFrom(uint8_t addr, uint8_t len)
  • uint8_t requestFrom(uint8_t addr, uint8_t len, uint8_t sendStop)

Fixes and Cleanup
  • Some bug fixes were done in Slave range code and in arbitration (note: arbitration has never been vetted on this library, it is on my to-do list).
  • Removed the I2C1 defines as they are redundant now that kinetis.h has them
  • Completely removed all debug code and the rbuf dependency
  • Cleaned and reworked the examples to simplify the code, test new things, and eliminate debug. In the examples I tried to group the Wire calls into a tight block so it is obvious which commands are being used.
  • Added an interrupt example to test running I2C from inside an ISR.

To-Do
1) When I get some time I'm going to investigate the interesting anti-lockup technique that Swap_File posted in #173: https://forum.pjrc.com/threads/21680-New-I2C-library-for-Teensy3?p=58368&viewfull=1#post58368
2) Verify arbitration


Other DMA Stuff

Ok, so now on the topic of DMA I have to rant a bit:

Unless I am missing a magic bit setting somewhere (which really should not exist because it would have to be labelled "Breaks I2C Protocol Bit"), the DMA implementation with this I2C peripheral is absolute ****. You see, one of the fundamental elements of the I2C protocol is the notion of an Acknowledge bit. When you talk to a Slave you will either get a ACK or a NACK. When Slaves have a problem or if they don't exist you get a NACK. When you get a NACK you STOP what you're doing. Now DMA sets up an automated transfer from point A to point B. You would think if you were in the business of moving things from point A to point B and you got a NACK you would STOP. Perhaps something that would result in a DMA error yes? NO!! this DMA system will happily blast out whatever you told it to regardless of the ACK/NACK responses.

Is this a problem? Technically (ideally) NO. For well constructed Slaves if they don't recognize their address at the beginning of the message they should ignore the entire message - even if it involves a string of 1000 bytes and 1000 NACKs. More importantly though, for the Master device it tosses the entire notion of verified transmission out the window - the Master in this case can only know if the message was sent, not if it was received.

To circumvent this pile, I've implemented the following workaround - when in DMA mode, the first and last bytes of the messages are sent via ISR-based routines. The bulk of the message in the middle is sent via DMA. The reason for this is that if the first byte (address) NACKs then you know the Slave doesn't exist, and it will STOP immediately. The last byte can also generate a NACK, which would tell you if the Slave died or had some kind of error somewhere between the address and the end of the message. There might be corner cases which are not caught, but for most cases it should work well enough. However, to mitigate the overhead of this nonsense I've set the minimum overall message length to 5 bytes when in DMA mode, eg. Address (ISR) - 3 bytes data (DMA) - last byte data (ISR). Messages below that size will automatically transfer in ISR mode, even if DMA mode is configured. That's for Master Tx mode, and for Master Rx mode a similar approach is used.

Slave mode is a different story. I am unable to figure out a way to make Slave mode work with DMA. Slave Tx/Rx transmissions are indeterminate in size, and DMA blocks normal ISR code from running, so there is no apparent way to terminate a transfer. Stupidly, even major bus events like a STOP do not trigger an ISR interrupt when DMA is active. In theory a similar fix to the rising-SDA hack used by the normal ISR Slave Rx code could be used to terminate a transfer, but at that point you are running an ISR on every byte, so where is the benefit of DMA versus the normal ISR code? Because of this, Slave mode will only work in ISR mode regardless of requested mode in begin() or setOpMode().

Another caveat - Timeouts may behave erratically when using DMA. This is because the DMA bulk transfer doesn't trigger the ISR, so it never gets a chance to detect the timeout condition and exit early. It may detect the timeout on the last byte when the ISR re-engages, but depending on bulk transfer length it could be any amount of time.

Note that I'm not trying to dissuade anyone from using DMA mode (I use it myself), and when it works it could be of some benefit, and really it is essentially free so why not. However just be aware there are workarounds in play (similar to Slave mode hack). So report any problems you have.
 
Brian, first of all, thanks for this awesome library.

I have a couple questions regarding using only the internal pullups of the Teesny. In several of your posts, you mentioned it's okay to use the internal pullups as long as the slaves are "strong" enough to drive the line low. How do you determine if the slave is capable of pulling the line low with the internal pullup?

The reason I'm asking is that I have a couple of IMU breakouts that all share the same slave address. I'm using an A/D multiplexer to connect them all to the same I2C bus. The problem is that all the breakouts were designed to be directly connected to the bus without a mux inbetween (they all have on board pull-ups). When I use the bus in external pullup mode (since the boards have pull ups), it doesn't work when they are connected through the mux. Wire.endTransmission hangs, and looking at the code, I assume it's because the line is not being pulled up so it thinks there is a bus contention. However, if I use the bus in internal pullup mode, everything works just fine. I'm just wondering if the internal pull-ups are sufficient or should I get some 2.2k resistors to pull the lines up even with the on-board pull-ups on the IMUs.
 
All, I've uploaded the new v7 library, and modified the top post accordingly. I'll try to summarize the changes here.

Clocking

The library now supports all Teensyduino F_BUS frequencies: 60MHz, 56MHz, 48MHz, 36MHz, 24MHz, 16MHz, 8MHz, 4MHz, 2MHz
In addition new rates have been added: I2C_RATE_1800, I2C_RATE_2800, I2C_RATE_3000

The supported rates depend on the F_BUS setting which in turn depends on the F_CPU setting. The current F_CPU -> F_BUS mapping (Teensyduino 1.21), is as follows. For a given F_BUS, if an unsupported rate is given, then the highest freq available is used (since unsupported rates fall off from the high end).

Code:
                                             I2C_RATE (MHz)
F_CPU    F_BUS    3000 2800 2400 2000 1800 1500 1200 1000  800  600  400  300  200  100
-----    -----    ---------------------------------------------------------------------
 168M     56M            y    y    y    y    y    y    y    y    y    y    y    y    y
 144M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
 120M     60M       y    y    y    y    y    y    y    y    y    y    y    y    y    y
  96M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
  72M     36M                           y    y    y    y    y    y    y    y    y    y
  48M     48M                 y    y    y    y    y    y    y    y    y    y    y    y
  24M     24M                                     y    y    y    y    y    y    y    y
  16M     16M                                               y    y    y    y    y    y
   8M      8M                                                         y    y    y    y
   4M      4M                                                                   y    y
   2M      2M                                                                        y

Does your library assume that F_BUS and F_CPU always have the relations listed in your table? Or is that just what Teensy 3.1 uses?

Asking because Teensy3-LC will apparently have F_CPU 48M and F_BUS 24M (where Teensy 3.1 would have 48M). I'm hoping that since F_BUS 24M is already supported, things will just work with the new board.
 
In several of your posts, you mentioned it's okay to use the internal pullups as long as the slaves are "strong" enough to drive the line low. How do you determine if the slave is capable of pulling the line low with the internal pullup?

Well the short answer is if it works then you are good.

The technical answer has to do with the pulldown strength of the slave device. Slaves generally pull the bus low through an NMOS device. The NMOS device is sized to pull down a particular current at the SDA low voltage. So for instance in a datasheet it might say the SDA can sink 5mA at 0.3V (I'm just pulling numbers out of air here, there are minimum requirements given by the I2C spec, and specific numbers sometimes given in the device datasheet). So Ohm's law gives us R = V/I = 300mV/5mA = 60 ohms for the NMOS on-impedance.

So using that, do a resistor divide with the pullup device (parallel combination them if there are multiple) and pullup voltage, and you get the minimum SDA voltage that a slave can pull. If you know the low switching point of the T3 and the slave then you will know if they will recognize the SDA low signal.

Now for the T3 the internal pullups are something like 200 ohms. This is an unnaturally low impedance for an I2C pullup. The above example slave could only pull SDA down to something like 23% of SDA pullup voltage. However for real slaves many will oversize the pulldown device (because it's easy to do) and the true switching point is generally much higher than the input-low given by the spec. So in practice the T3 pullup device usually works ok.

The reason I'm asking is that I have a couple of IMU breakouts that all share the same slave address. I'm using an A/D multiplexer to connect them all to the same I2C bus. The problem is that all the breakouts were designed to be directly connected to the bus without a mux inbetween (they all have on board pull-ups). When I use the bus in external pullup mode (since the boards have pull ups), it doesn't work when they are connected through the mux. Wire.endTransmission hangs, and looking at the code, I assume it's because the line is not being pulled up so it thinks there is a bus contention. However, if I use the bus in internal pullup mode, everything works just fine. I'm just wondering if the internal pull-ups are sufficient or should I get some 2.2k resistors to pull the lines up even with the on-board pull-ups on the IMUs.

This might be because there is no pullup on the T3 side of the mux. Both the Master and Slaves need to see a pullup device. If each of your Slaves has a pullup, but the mux blocks the T3 from seeing it, then it won't work.

The only penalty of T3 pullups versus 2.2k (if they both work), is that the T3 will have a higher current draw during SDA/SCL low periods. This is normally a transient current, but if the bus gets stuck then you might get a current of 3.3V / 200 ohms = 16.5mA. If your Slave can handle sinking that then it should be ok.
 
Does your library assume that F_BUS and F_CPU always have the relations listed in your table? Or is that just what Teensy 3.1 uses?

Asking because Teensy3-LC will apparently have F_CPU 48M and F_BUS 24M (where Teensy 3.1 would have 48M). I'm hoping that since F_BUS 24M is already supported, things will just work with the new board.

At the moment it is hardcoded based on F_BUS only. That is F_CPU is defined which gives F_BUS, but the code only looks at F_BUS. However the F_BUS to SCL ratios are fixed, so if the new part has a different divider scheme then there will need to be additional code to handle that.
 
sorry i'm still trying to wrap my head around all of this, and I have a question: if i just want to send the analogRead input from one pin attached to the slave teensy to the master teensy, do i need to use a Tx pin in addition to the SCL and SDA pins or can I just send that info over the SCL and SDA pins? sorry I've been trying to understand how this all works and I can't seem to find any entry points.

Does anyone have any simple examples using this lib for 1 slave teensy sending analogread info to a master teensy? I can't seem to figure out how to it

Or, is there anyway to use the old wire library with the SCL1 and SDA1 pins on the teensy 3? it appears that you can only use the default pins with the old library and i need to use those pins for other things atm :p
 
Last edited:
The best thing is if you post a schematic of what you have wired to what. I know what nox771 means but a schematic would help us to provide the reference points to help your understanding.
No you don't need a TX pin. You can send the info directly over I2C. Nick Gammon has written a library called I2C_Anything.h and you'll find that and a whole lot more I2C info on his web page
 
scratch this, sorry. I retooled the original wire master and slave sketches to do what needed. Sorry to be a bother!
but thanks for the tip on that webpage :D
 
At the moment it is hardcoded based on F_BUS only. That is F_CPU is defined which gives F_BUS, but the code only looks at F_BUS. However the F_BUS to SCL ratios are fixed, so if the new part has a different divider scheme then there will need to be additional code to handle that.

Okay. From what Paul said in the announce thread, Teensy3-LC does not support much/any overclocking. We also don't know how low it will clock.

For now, an ifdef for the Teensy3-LC and a hardcoded F_BUS of 24M rather than one computed from F_CPU would get this lib working with Teensy3-LC. From what you said above, it seems that the current code would deliver an F_BUS that is 2x too large. I will ask on the announce thread what the best symbol would be for that test.
 
For now, you can assume F_BUS is always 24 MHz.

Teensy-LC can't use faster F_BUS, because the flash memory also runs from F_BUS. There no separate divider for the flash. F_BUS is divided down from F_CPU, not directly from the PLL like on Teensy 3.0 & 3.1. The USB clock is fixed at F_PLL divided by 2, so the PLL must be exactly 96 MHz for USB to work. All of these less flexible clock configuration settings work together to really limit our options for overclocking. F_CPU at 96 MHz with F_BUS at 24 MHz might be possible, maybe, but I don't see any other options that would still allow the USB to work.

This chip does have some really intriguing possibilities for low power. More of the peripherals are designed to be able to work in stop mode or very low power modes. The DMA engine can also work in limited ways with the clock stopped, and generate interrupts for wakeup when a DMA buffer has been fully transferred.

Like with Teensy 3.0 & 3.1, my top priority is going to be getting all the Arduino functionality and libraries working first. Support for low speed modes (without USB) will come later.

The good news is I2C is pretty much identical to Teensy 3.1, except for F_BUS being 24 MHz when the CPU is at 48 MHz.
 
I see some code in the recently renamed kinetis.h
Code:
#elif (F_CPU == 48000000)
#define F_PLL 96000000
#if defined(KINETISK)
#define F_BUS 48000000
#elif defined(KINETISL)
#define F_BUS 24000000
#endif
Maybe something similar would be a good fit for this library?

Paul, point taken about compat with the standard Arduino Wire library being first priority as a the most widely deployed lowest common denominator. But especially with two I2C on the T3LC, having this more powerful I2C library also working soonish seems very desireable.

Also, my point in the post above about limited overclocking was not a criticism. Rather, it was pointing out that handling the F_CPU=48M, F_BUS=24M case would cover most if not all of the options, thus making support more tractable.
 
Last edited:
Sorry for the delay. Just moved and was offline for a few days. I'll try to get the dual I2C working as soon as I can get to work with it. From Paul's comments it sounds like the changes will be minimal. Although some of the new modes like DMA might depend on the DMA header/library working. Interrupt based sounds like it should work.
 
Hi,
I just wonder if I didn't see it while reading this thread or if I just don't understand it or if it really isn't asked and answered yet...

I need a very simple wire master function that reads from a slave (in my case 6 bytes), but does not get blocked if the slave crashes (or is to slow for any other reason)
Is there a chance to use a wire.read() for a given time?

I actually use the standard wire lib to connect two teensy3.1 chips, one working as an intelligent sensor multiplexer(slave) and one as master.
I simply want the master to ask the slave for new sensor data but don't bother (still saying so) if the connection fails or drops or locks.

Thanks for your help!
Roland
 
Hi,
I need a very simple wire master function that reads from a slave (in my case 6 bytes), but does not get blocked if the slave crashes (or is to slow for any other reason)
Is there a chance to use a wire.read() for a given time?
Roland

There are timeout functions which you can try. These require more extended forms of the function calls. Instead of this:
Code:
Wire.endTransmission();
you will need to call it like this:
Code:
Wire.endTransmission([COLOR=#008000]i2c_stop, timeout[/COLOR]);
whereby i2c_stop == I2C_STOP or I2C_NOSTOP and timeout is given in microseconds.

Similarly for the receiving call, instead of this:
Code:
Wire.requestFrom(address, length);
you will need to call it like this:
Code:
Wire.requestFrom(address, length, [COLOR=#008000]i2c_stop, timeout[/COLOR]);
where the arguments are the same as above.

On the top post if you scroll down you will see descriptions of these functions if you need more info.
 
Back
Top