PDA

View Full Version : Teensyduino 1.20 Released



Paul
10-08-2014, 05:06 AM
Teensyduino 1.20 has been officially released.

http://www.pjrc.com/teensy/td_download.html

duff
10-08-2014, 02:57 PM
just a reminder, can detachInterruptVector be added to the next Teensyduino version?

jitter
10-08-2014, 09:11 PM
Just installed the 1.20 version.

Should the USB host shield library be fetched externally? I haven't seen it being included in the installer.

Nantonos
10-09-2014, 02:00 PM
Yes, and you should put it inside your sketches/libraries folder.

xxxajk
10-09-2014, 06:10 PM
@jitter:
Good to see out UHS library is in demand.

Just a sneak-leak here, the next version of it is currently in-progress, and will be totally amazing.
You will be even able to support your very own devices with either a special additional driver library provided by yourself, or directly within a sketch.
Reduced code footprint.
Ability to use different SEI (Session Engine Implementation) -- e.g. the teensys own USB port. 1.20 should have the ability now if the code I requested to be pulled in was indeed pulled in, but I have been so busy writing the new UHS code I haven't had the opportunity to check.
If this is not the case, we can just do this next time, and perhaps Paul will include this new version.
However, I'm in no real hurry at this point to verify that is the situation anyway, since the new code has not even been parsed in any compiler yet.

xxxajk
10-09-2014, 08:24 PM
Paul:

Only one warning in 1.20:

/opt/arduino-1.0.6/libraries/Wire/Wire.cpp: In member function 'uint8_t TwoWire::requestFrom(uint8_t, uint8_t, uint8_t)':
/opt/arduino-1.0.6/libraries/Wire/Wire.cpp:349:10: warning: variable 'tmp' set but not used [-Wunused-but-set-variable]


:-) minor IMHO. Something for the next version.

PaulStoffregen
10-10-2014, 12:47 AM
If this is not the case, we can just do this next time, and perhaps Paul will include this new version.


Yes, I'd love to include an updated UHS lib with the Teensyduino 1.21 installer. I've been averaging a new version every 3-4 months, so the time frame would probably be in January.

Long term, I'd really also like to help with integrating Teensy 3.1's USB host mode with the library, especially if you're moving to a new design that allows a nice hardware abstraction. Realistically, to develop code by USB, some sort of special USB mux will likely be needed. Maybe it's time to think about what a first gen USB mux board might look like?

xxxajk
10-11-2014, 03:11 AM
Yes, I'd love to include an updated UHS lib with the Teensyduino 1.21 installer. I've been averaging a new version every 3-4 months, so the time frame would probably be in January.

That's fine. No drivers have been ported to the newer version yet, except hub, and that isn't even tested yet.
I just now (as of this posting)got enumeration to work properly for the MAX chip.


Long term, I'd really also like to help with integrating Teensy 3.1's USB host mode with the library, especially if you're moving to a new design that allows a nice hardware abstraction. Realistically, to develop code by USB, some sort of special USB mux will likely be needed. Maybe it's time to think about what a first gen USB mux board might look like?

No 'mux' board is needed. The Freescale OTG features can be supported on-the-fly.
It is pretty easy to rework the teensy 3.x to support the vbus switch right on the board too.
I also already have host cables for micro USB.
One could simply upload new code via a thumb drive or SDcard, or heck, SPI or even I2C instead via another uC. No real need to limit to just the teensy 3 loader code since we can program right in-place from code copied to RAM.

xxxajk
10-12-2014, 04:23 AM
One more bug.... won't affect anyone but me, because the code is not released into the public, and I'm holding off until it actually compiles without error.
Basically you forgot an #ifdef statement....
I'll post a pull request on github (when I get to it).
I Also believe that the whole USB handling needs to be separated into an optional library later on so we can support different modes of OTG. It is more-or-less mandatory in order to be able to get at the internals.
Here's the compile error message, it is the only part that fails (did a make -k to examine all compile paths):
/opt/Arduino/hardware/teensy/cores/teensy3/yield.cpp: In function 'void yield()':
/opt/Arduino/hardware/teensy/cores/teensy3/yield.cpp:43:6: error: 'Serial' was not declared in this scope
/opt/Arduino/hardware/teensy/cores/teensy3/yield.cpp:43:38: error: 'serialEvent' was not declared in this scope

OOPS! "USB_SERIAL" isn't defined, and therefore there is no "Serial" class ;-)

Here's a quick 'patch' for this for anyone who wants to do a quick test to verify if it affects them. It shouldn't affect any normal sketch via the IDE.

File /opt/Arduino/hardware/teensy/cores/teensy3/yield.cpp

/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2014 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "core_pins.h"
#include "HardwareSerial.h"
#include "usb_serial.h"
#include "usb_seremu.h"

void yield(void) __attribute__ ((weak));
void yield(void)
{
static uint8_t running=0;

if (running) return; // TODO: does this need to be atomic?
running = 1;
#ifdef USB_SERIAL
if (Serial.available()) serialEvent();
#endif
if (Serial1.available()) serialEvent1();
if (Serial2.available()) serialEvent2();
if (Serial3.available()) serialEvent3();
running = 0;
};

xxxajk
10-12-2014, 08:14 AM
I made a better patch and a pull request on github.
https://github.com/PaulStoffregen/cores/pull/37

xxxajk
10-15-2014, 02:22 PM
Hey Paul, I found a pretty nasty bug in the SPI library. It does not save the interrupt state atomically.

Original method:

inline static void beginTransaction(SPISettings settings) {
if (interruptMode > 0) {
#ifdef SPI_AVR_EIMSK
if (interruptMode == 1) {
interruptSave = SPI_AVR_EIMSK;
SPI_AVR_EIMSK &= ~interruptMask;
} else
#endif
{
interruptSave = SREG;
cli();
}
}
#ifdef SPI_TRANSACTION_MISMATCH_LED
if (inTransactionFlag) {
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
}
inTransactionFlag = 1;
#endif
SPCR = settings.spcr;
SPSR = settings.spsr;
}


Here is the better version...
It saves SREG to a private variable *first* then, the ***SHARED*** interruptSave variable AFTER the cli(), and thus is atomic.
The original above will race if you try to do beginTransaction from outside the isr, from a sketch, for example.


inline static void beginTransaction(SPISettings settings) {
if (interruptMode > 0) {
#ifdef SPI_AVR_EIMSK
if (interruptMode == 1) {
interruptSave = SPI_AVR_EIMSK;
SPI_AVR_EIMSK &= ~interruptMask;
} else
#endif
{
uint8_t x = SREG;
cli();
interruptSave = x;
}
}
#ifdef SPI_TRANSACTION_MISMATCH_LED
if (inTransactionFlag) {
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
}
inTransactionFlag = 1;
#endif
SPCR = settings.spcr;
SPSR = settings.spsr;
}


Hope you update this soon. :-)

PaulStoffregen
10-15-2014, 03:07 PM
Do you think the interruptMode == 1 case also needs to be done with all interrupts disabled?

PaulStoffregen
10-15-2014, 03:17 PM
Yes, I believe you're right.

If the interrupt occurs exactly between the write to interruptSave and cli(), then the interrupt will overwrite interruptSave and when control returns to the main program, it will execute the cli(), do a complete transaction, and then erroneously restore SREG with the value the ISR's transaction saved into interruptSave.

I'm pretty impressed you found this! Thanks.

Looking at this a bit more, it seems the same might be able to happen in the EIMSK code. Maybe? If the interrupt occurs after interruptSave is written, but before EIMSK is written, when the non-interrupt transaction completes last, it could end up restoring EIMSK with the ISR's saved copy.

Maybe something like this is needed? Any thoughts?



if (interruptMode == 1) {
uint8_t tmp = SREG;
cli();
interruptSave = SPI_AVR_EIMSK;
SPI_AVR_EIMSK &= ~interruptMask;
SREG = tmp;
} else

xxxajk
10-15-2014, 03:56 PM
Yes, I believe you're right.

If the interrupt occurs exactly between the write to interruptSave and cli(), then the interrupt will overwrite interruptSave and when control returns to the main program, it will execute the cli(), do a complete transaction, and then erroneously restore SREG with the value the ISR's transaction saved into interruptSave.

I'm pretty impressed you found this! Thanks.

You are quite welcome :cool:
Why are you impressed that I found it anyway?
I wrote my code, was experiencing a race in my code, and odd serial behavior. I instantly suspected it was the transaction locking.
Basically, the interrupt pin was acting very strange and had huge LOW pulses that should never be happening.
One look and it was pretty obvious what was going on. If you ever looked at my xmem2 library, you'd know I am very familiar with ISRs and parallel tasking, even with using multiple CPU...
Now....
I think this snag merits a new release. It is a major boo-boo.
How will the average user get the fix?
Are you going to do a quick-fix release? And if you do, can you pull in my git pull request too, which fixes my one last barrier from releasing some really awesome teensy 3.x code/libraries?



Looking at this a bit more, it seems the same might be able to happen in the EIMSK code. Maybe? If the interrupt occurs after interruptSave is written, but before EIMSK is written, when the non-interrupt transaction completes last, it could end up restoring EIMSK with the ISR's saved copy.

Maybe something like this is needed? Any thoughts?



if (interruptMode == 1) {
uint8_t tmp = SREG;
cli();
interruptSave = SPI_AVR_EIMSK;
SPI_AVR_EIMSK &= ~interruptMask;
SREG = tmp;
} else


It could only if the ISR did an sei(); someplace before access.
I pass the magic 255 value to use the "block everybody' method, and it works almost as well as my spinlocks that I use in my xmem library.
The difference is that the spinlocks don't turn off interrupts for more than just a couple of instructions, where as the cli() idea just prevents all ISR from executing.

Since what I am doing on SPI tends to be brief (Max3421e USB Host Shield, using a real interrupt now!), I have not experienced any dropped serial characters or other funny business now that I have fixed this issue.

PaulStoffregen
10-15-2014, 04:36 PM
Are you using an external interrupt pin with attachInterrupt()?

PaulStoffregen
10-15-2014, 04:42 PM
For a time-frame, I'll get this merged on github either later today or early tomorrow.

This probably does merit an early 1.21 release. At this moment, no published library calls SPI.usingInterrupt() with any number greater than the external interrupt numbers.

Realistically, I don't see 1.21 happening before mid-November to early December. I am juggling a LOT of stuff and currently working on a couple high priority tasks that got delayed by the audio library.

xxxajk
10-15-2014, 05:22 PM
Yes, I am using attachInterrupt, why?

xxxajk
10-15-2014, 05:29 PM
Here is the relevant bits of code I am using to do the attachment, the settings for spi to do the transaction stuff are in the constructor...



...(SNIP!)...
SPI.begin();
#endif

SPI.usingInterrupt(255);

pinMode(irq, INPUT);
UHS_PIN_WRITE(irq, HIGH);
pinMode(ss, OUTPUT);
UHS_PIN_WRITE(ss, HIGH);

...(SNIP!)...


#if USB_HOST_SHIELD_USE_ISR
// Attach ISR to service IRQ from MAX3421e
// supports only pins 2 and 3 int0 and int1 for avr
cli();
#ifdef __AVR__
if(irq == 2) {
ISReven = this;
attachInterrupt(INT_FOR_PIN2, call_ISReven, LOW); // avr
} else if(irq == 2) {
ISRodd = this;
attachInterrupt(INT_FOR_PIN3, call_ISRodd, LOW); // avr
} else {
sei();
return (-2); // -2 means not able to assign ISR
}
#else
// Everybody else should be able to use any pin

....(SNIP!)....

#endif
sei();
#endif

xxxajk
10-16-2014, 03:50 PM
One thing that to this day kind of urks me is that there is no easy way to just say 'attachInterrupt(pin, handler, condition);' for _ALL_ boards, not just non-avr.
The avr ends up as a special case. This is silly.

I realize this is a bit of a rant, but I am wondering if we now need to push the arduino team into using a better interrupt scheme. Perhaps if done with Teensyduino as an example use-case, we can show that not only does it work, but that it can bring all libraries that use an interrupt to coexist together in harmony...

What should be done is that you do this by pin number, period. If an attempt to attach to a pin that can't generate an irq, it should return false, to indicate failure.
Failure should also include if it is the entire port, unless there is abstraction above it to handle it for you. I'm certain that this can be done transparently, since you can just mask off any pin that has a real direct IRQ.

I also know you (Paul) are a busy guy, and I'm willing to do the leg work on this sort of thing if you are willing to incorporate it into the next version of Teensyduino. It will totally help me because I will be able to release libraries that use an ISR and won't conflict. I already have one in the wild that does this, but it can only operate on an AVR due to this restriction, and I would love to add more libraries to my collection, and share them, but I can't without conflicts.

In conclusion, I do realize there are pinChangeInt libraries... it is a nice idea, but there are overlaps between the entire port and a single int in some cases, and I am not certain if those particular cases are handled correctly. It is also avr centric. Worse, no two libraries that use interrupt pins agree on what way to attach to these interrupts. I know I can do better than this, and it is a shame that the Arduino team did not have the foresight to do this properly.

Let me know if you are willing to entertain this idea, and then I can show the Arduino team how it can be done in a superior way, and hope that they will bite.

xxxajk
10-16-2014, 05:51 PM
By the way, speaking of using/abusing cli();, wouldn't it have been better to disable other hardware interfering interrupts instead?
For example, to allow millis, serial, etc to continue to operate.
Yes I understand you can do this per-driver for pin interrupts. You can't do it for timers, or other internal hardware IRQ.
In the case of 'from a hardware IRQ' there should be a way to specify that, and add it to the list of things to disable. Timers are one such case.
If you do it that way, you don't need to use cli() to disable all ISRs, and any non-offending ISR can just hit as needed.

xxxajk
10-16-2014, 06:13 PM
By the way, Just by looking at it, I think the arm versions also need atomic protection ;-) I've not tested this yet, but I will be doing so fairly soon

xxxajk
10-16-2014, 07:36 PM
I'm reworking the SPI library, as it has a lot of problems and waste, all while keeping it compatible. Testing will be done with our super secret host library, and I'll share the source with you once it is done.
Most importantly, there are a pile of atomicity problems in many places.
I also have some additional good things to add. If you can hand this off upstream to the Arduino team that would be awesome.
It might be bundled with our library when it is released in any case, because I really don't like it when things go wrong, and I'm sure others do not either.

PaulStoffregen
10-17-2014, 11:03 AM
I realize this is a bit of a rant, but I am wondering if we now need to push the arduino team into using a better interrupt scheme.


Actually, I pushed for this several months ago. Many people did support the idea of attachInterruptToPin(), but ultimately it was rejected.

But we did get a digitalPinToInterrupt() macro. It's officially released in 1.0.6 and 1.5.8. :)



#if USB_HOST_SHIELD_USE_ISR
// Attach ISR to service IRQ from MAX3421e
cli();
#ifdef digitalPinToInterrupt
int n = digitalPinToInterrupt(irq);
if (n == NOT_AN_INTERRUPT) return (-2);
ISReven = this;
attachInterrupt(n, call_ISReven, LOW);
#else
// ugly fallback code for Arduino 1.0.5 & earlier...
// supports only pins 2 and 3 int0 and int1 for avr
#endif
sei();
#endif


The other nice thing about digitalPinToInterrupt() is it gives you the number to pass into SPI.usingInterrupt().

PaulStoffregen
10-17-2014, 11:06 AM
Also, sorry about the delay. I've committed the fix to GitHub, so it's now queued for Teensyduino 1.21.

If any libraries or sketches are published with SPI.usingInterrupt(255), or if you need to release this new version of UHS, and end users end up hitting this problem, at the very least I'll push out 1.21-rc1 early to give people a path to get the fix easily installed.

PaulStoffregen
10-17-2014, 11:10 AM
Regarding more fixes to the SPI library, yes, but please let me know what you're up to. Even if I can't respond rapidly, it'll be a lot easier than a huge pile of changes developed over many weeks, but I see them all at once.

I'm hoping you can try the code above, or something similar with digitalPinToInterrupt(), in your private UHS branch? I'm still a little concerned there might be a race condition in the case where SPI.usingInterrupt() gets a normal integer. Even if you stay with SPI.usingInterrupt(255), I hope you'll give it a try to see if the same problem happens?

The normal interrupt numbers are probably also a better solution for UHS to play nicely with other libraries. It avoids global interrupt disable, for much better compatibility with libraries like Servo and SoftwareSerial, which require very low interrupt latency.

xxxajk
10-17-2014, 01:22 PM
I'm already in contact with Chris, and I'll be emailing you soon the new SIP.cpp and SPI.h files in a couple of hours. I need to do more testing first. You will have to do testing for Due, which I don't own. I need to also finish the Due fixes as well.

xxxajk
10-17-2014, 02:55 PM
as far as digitalPinToInterrupt() thanks for the tip. The new library will require 1.0.6 or better anyway.

xxxajk
10-17-2014, 03:04 PM
Oh by the way, the gui uploader now works properly. Thanks! I don't know if you have had reports of it working well, consider this one....

xxxajk
10-17-2014, 03:51 PM
Looks like there is a bug with attachInterrupt(). The ISR is expecting to be ran with interrupts off (like it does on the AVR). Any chance to fix this?

PaulStoffregen
10-17-2014, 03:56 PM
I don't understand what you mean by "The ISR is expecting to be ran with interrupts off". Maybe explain in a little more detail?

PaulStoffregen
10-17-2014, 04:41 PM
Maybe you're looking at the PRIMASK bit, which is manipulated by cli() and __disable_irq()?

On AVR, the GIE bit is the only global mechanism which controls whether interrupts can occur. Of course, each interrupt has to be enabled within its peripheral, but just that 1 bit enables and disables all interrupts that are enabled within their peripheral hardware.

ARM Cortex-M4 has a much more advanced system. PRIMASK can be used to prevent all interrupts from happening, so in that respect it's similar to AVR. But when you use sei() or __enable_irq() to clear PRIMASK, that does NOT necessarily allow all configured interrupts to occur. ARM has more stuff that controls which interrupt can happen.

The ARM core has a seldom accessed register called ICSR, which automatically get updated with the new priority level of an interrupt. Normally nobody writes code to access it, since it automatically manages itself. Suppose a pin change interrupt occurs and your function is running, because you used attachInterrupt. It will be running at the default priority level, which is 128. Even though PRIMASK is clear (allowing all interrupts), the setting in ICSR will always mask all other interrupts configured at 128 and lower priority (higher numbers are lower priority levels).

On AVR, the processor clear the GIE bit as it starts executing your interrupt. If it didn't, then your interrupt could interrupt itself, and all others could too, which would lead to chaos.

On ARM, the processor updates ICSR as it starts executing your interrupt. It does NOT change PRIMASK, because its interrupt system is very different from the simplistic one on AVR. So while your interrupt runs, if you look only at PRIMASK and apply experience with AVR, it might seem as if things are going horribly wrong. In fact, that's how ARM works. ICSR is the normal mechanism for managing which interrupts can happen, not PRIMASK.

ARM also has 2 bits that control each interrupt. On AVR, there's only 1 per interrupt, inside the peripheral itself. Most of the peripherals have a bit that controls whether that will generate interrupts, but there's also a 2nd bit inside the CPU core for every interrupt. AVR has nothing like this. On ARM, there's a few bits in the CPU for every interrupt, that enable/disable it, independently of the bit inside the peripheral itself. There's also a bit that tells whether the interrupt is pending and hasn't run yet. AVR has such a bit for each interrupt, but they're not memory mapped so you can't access them. On ARM, all those bits are in registers. There's also bits to force any interrupt to become pending, and to clear the pending status. There's also a bit to track if the interrupt is actually running, which adds another layer of protections to prevent the core from every running 2 instances of the same ISR (which normally couldn't happen anyway due to the priority scheme, but could if you reconfigured the priority at runtime in wreckless ways).

Anyway, the long-winded point is the ARM interrupt controller is much more sophisticated than AVR's. Things like PRIMASK provide similar capability to disable interrupts temporarily, but they're not perfectly equivalent to AVR.

xxxajk
10-18-2014, 01:40 AM
Argh. Yes, I am aware it is much more complex. Yes, I am using PRIMASK. I thought that primask blocks the current level and irq.

PaulStoffregen
10-18-2014, 01:57 AM
Yes, PRIMASK blocks everything except faults.

PRIMASK should only be used for very brief interrupt disable, without calling other functions. The other features, like raising base priority or masking specific interrupts should be used if you need to disable an interrupt for longer times.

xxxajk
10-18-2014, 02:05 AM
Basically the trouble is that the user sketch interferes with the isr, since they both want access to parts at the same time.
Also, on avr arduinos, when an isr is entered from attachinterrupt, it is expecting to have irq's off...
I do have to call a few other parts too...
Basically the code I am using is something like this:

void someisr(void) {

[critical code]

if (we are not already in something critical flags) {
interrupts();
[does a pile of non-critical code]

}

On avr it is expecting cli to have been done for you...

PaulStoffregen
10-18-2014, 02:13 AM
Is the interference only due to both wanting to access the SPI port?

xxxajk
10-18-2014, 02:25 AM
The case happens when I am in the bottom half, and a re-entrant irq hits and starts to use SPI too, which is the intention, and this works fine on the avr.
I'll email you the current SPI.cpp and SPI.h so you can take a look at it. That said, attachInterrupt does need to do noInterrupts() as early as possible. It is expected behavior, which happens to be automatically done on the AVR.

PaulStoffregen
10-18-2014, 02:45 AM
When you say "re-entrant irq", do you mean the USB chip asserts its INT pin again and the function runs again, recursively, while a previous copy is still running?

xxxajk
10-18-2014, 02:47 AM
Yes, The top half is fully intended to be allowed to run when an irq is generated by the bottom half, which enables interrupts.

PaulStoffregen
10-18-2014, 02:49 AM
I'm afraid this type of approach is nearly impossible on ARM. The hardware manages interrupts and it's designed to prevent the same ISR from running again until it's completed the previous run.

xxxajk
10-18-2014, 03:08 AM
Here is the code, with parts muted....


void MAX3421E_HOST::ISRTask(void) //USB state machine
{
{
uint8_t HIRQ_sendback = 0x00;
uint8_t HIRQALL = regRd(rHIRQ); //determine interrupt source
uint8_t HIRQ = HIRQALL & IRQ_CHECK_MASK;
[ this section does what it needs to do based on the HIRQ value....]
}
if(!disabled) {
Disable(); // sets disabled to true
// Enable interrupts
interrupts();
switch(usb_task_state) {
[This section does various state machine operations, some controlled from the top half]
}
// Disable interrupts
noInterrupts();
Enable(); // sets disabled to false
}
}



Note also that the code expects that irq is disabled at the end, this is how they would be on an avr...
I tried working around this by adding noInterrupts() at the top, and interrupts() at the bottom, and while the avr could care less either way, it is either too late for the arm (unlikely) or something else is happening... I have not looked into the code in the teensy3 core yet, but are you disabling the pin or something?

xxxajk
10-18-2014, 03:09 AM
I'm afraid this type of approach is nearly impossible on ARM. The hardware manages interrupts and it's designed to prevent the same ISR from running again until it's completed the previous run.

Argh, got an idea for this then?

xxxajk
10-18-2014, 03:15 AM
What if you...
cli();
push helper_stub_address
return

and the stub...
calls the isr that is attached
sei();
ret <-- this should return back to the place we got interrupted from

Of course you would have to push/pop registers, and this is just the terse form.

xxxajk
10-18-2014, 03:19 AM
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471g/Bgbeacfi.html

xxxajk
10-18-2014, 03:24 AM
So I'm guessing this is my problem....

xxxajk
10-18-2014, 03:52 AM
I believe I know how I can solve this in my own code... I know exactly where it occurs :-)

xxxajk
10-18-2014, 04:18 AM
Read passed, Read 500 sectors in 1000ms
Test complete.

Thanks for explaining the inability to reenter ISRs, I've fixed it so that it works now. This means that the code I sent you passes my tests as atomically correct.

xxxajk
10-18-2014, 08:48 AM
I have a few extra bits-and-chunks I want to clean up in the code i emailed to you. I can post here a zip file containing the replacement files within a couple of hours.
.

xxxajk
10-19-2014, 02:39 AM
Here is what I tested, and works rock solid. I really abused things in order to make certain that corruption won't happen.


Teensy++ 2.0 PASS
Teensy 3.0 PASS
Teensy 3.1 PASS
Arduino UNO PASS
Arduino Duemilanove PASS
Arduino Diecimila PASS
Arduino Mega PASS
Arduino Mega 2560 PASS
Digilent Uno-32 NOT COMPATIBLE


Boards not listed are not owned by me, thus are not tested.

pictographer
10-19-2014, 08:05 PM
Installed OS X Yosemite Version 10.10. The Arduino IDE wouldn't run until I installed a legacy Java update JavaForOSX2014-001.dmg. After that I was able to flash a T3.1 with the blink example with no problems.

jcarruthers
10-20-2014, 03:35 PM
Installed OS X Yosemite Version 10.10. The Arduino IDE wouldn't run until I installed a legacy Java update JavaForOSX2014-001.dmg. After that I was able to flash a T3.1 with the blink example with no problems.

Same for me - all working well.

In fact I think the uploader works better? Or am I just imagining that? Sometimes before I'd have to click on the Teensyduino app for it to upload to the board after the Arduino IDE had tried x number of times and failed.

xxxajk
10-21-2014, 01:09 PM
The uploader works as it should now on Linux too. I think Paul nailed the problem finally.

manitou
10-31-2014, 06:00 PM
Hmmm, not sure which release this might have happened in, but under 1.20, this program no longer compiles for teensy 3
https://github.com/manitou48/teensy3/blob/master/lowvolt.ino
it can't find the PMC_LVDSC* variables. I tried including kinetis.h (the symbols seem to be defined there now), but that didn't help ???

PaulStoffregen
10-31-2014, 06:14 PM
Opps, sorry, somehow a typo got into the code.

Fixed on github.

https://github.com/PaulStoffregen/cores/commit/e8f5c6ee40ab007ccd3005a8648fad831d13ddc0

Frank B
11-03-2014, 01:05 PM
I need help with the new "FASTRUN" Feature, how can i use it ?
Could you please provide an example ?

PaulStoffregen
11-03-2014, 05:17 PM
Here's an example. A rather silly one, since you'd want to use FASTRUN on functions that matter for performance.



FASTRUN void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}


Sometimes FASTRUN can help a lot, especially when running at faster clock speeds (eg, overclocking stuff that's disabled by default in boards.txt), but more often than not it gives little to no benefit, for a lot of extra RAM usage, when used on functions that don't matter for performance.

Frank B
11-03-2014, 06:33 PM
Thank you!

Different topic: While experementing with GCC 4.8.3, i got this warning:


C:\Arduino\libraries\Audio\effect_fade.cpp:31:22: warning: type of 'fader_table' does not match original declaration [enabled by default]
extern const int16_t fader_table[256];
^
C:\Arduino\libraries\Audio\data_waveforms.c:81:15: note: previously declared here
const int16_t fader_table[257] = {

Nantonos
11-05-2014, 08:46 AM
Here's an example. A rather silly one, since you'd want to use FASTRUN on functions that matter for performance.



FASTRUN void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}


Sometimes FASTRUN can help a lot, especially when running at faster clock speeds (eg, overclocking stuff that's disabled by default in boards.txt), but more often than not it gives little to no benefit, for a lot of extra RAM usage, when used on functions that don't matter for performance.

Thanks for the example. How does it make things faster, inlining to avoid call and return overhead?

MichaelMeissner
11-05-2014, 11:39 AM
Thanks for the example. How does it make things faster, inlining to avoid call and return overhead?
No, the FASTRUN macro uses an __attribute__ to put the code for the function into the .fastrun data section, instead of the the .text section. The linker script puts the .fastrun section into the read/write SRAM instead of the read-only FLASH memory that normally the code goes into. I would imagine the trade off is SRAM is much faster to reference, but by using it, you have less data for your data. Because it is in read/write memory, you also run the risk of something that writes outside of its bounds changing the code.

PaulStoffregen
11-05-2014, 12:08 PM
The RAM is faster than Flash.

Nantonos
11-05-2014, 06:13 PM
Thanks, that makes sense.

BrianC
11-29-2014, 12:59 AM
In the new SPI library in 1.20, is it possible to change


#elif defined(__arm__) && defined(TEENSYDUINO)

to this?


#elif defined(__arm__) && defined(CORE_TEENSY)


I'm running sublime text 3 with the Stino plugin, and for some reason, TEENSYDUINO is not defined, but CORE_TEENSY is.
In the previous version of the SPI libraries, CORE_TEENSY is used instead of TEENSYDUINO.

Otherwise, upon compiling, the whole section for the Teensy 3.x is not used and I get all these errors with SPIClass is not defined etc.

I have manually changed this, but it'd be great if it could be added to the next release.

Thanks.

xxxajk
12-07-2014, 01:00 PM
Hey Paul, Any chance of bundling the teensy_loader_cli under hardware/tools/ ?? This would be very handy.

PaulStoffregen
12-07-2014, 01:15 PM
I'm not really maintaining teensy_loader_cli.

xxxajk
12-07-2014, 05:22 PM
Why not? Any particular reason?

Jake
01-13-2016, 01:52 AM
You may want to include the FASTRUN discussion above in the Wiki when it comes.

And can it be used in conjunction with static inline void function()? An example of static inline is shown at https://forum.pjrc.com/threads/24573-Speed-of-digitalRead-and-digitalWrite-with-Teensy3-0

Frank B
01-14-2016, 09:25 PM
I don't know what the compiler would do, but inlining a "FASTRUN"-Function (which means that it should run in the RAM) to code which is in the FLASH would be pretty obscure...

Frank B
01-14-2016, 09:52 PM
This is the definition:


#define FASTRUN __attribute__ ((section(".fastrun"), noinline, noclone ))

You'll notice the "noinline" :)