Are you sure that no thread switches can occur while the threads are executing non-reentrant code? The easiest way to do that is to set the TeensyThreads timeslice to a very large value so that thread switches occur...
I was wrong. Sorry about that. The change that I made affected the printing, but not the allocation. Maybe this is okay. I'm really not sure. Have you tried it in your application?
Your design sounds reasonable in terms of having the serial port i/o and the LED blinking in separate threads. You say the main thread and comm thread are asynchronous, but are they completely independent, or do they...
You haven't said how many threads you have or what they do, but it may be fairly easy to do an initial test by converting the threads that use malloc/new/String to ordinary functions and call them in a loop from your...
You might be trying to print some non-printable characters that are doing unexpected things. Are you sure ASCII 31-91 are all printable? Make sure, modify if necessary, and try replacing:
Serial.print((uint8_t)c);...
Victor, your program does run correctly, but if I simply comment out the checking for stack corruption, it does not run at all. This is what I have seen over and over with this issue. A working program will "break" with...
Hi Victor. My phone does not show message numbers, so I’m not sure which one you mean. Is it the one with mutexes? I will try it later. If new uses malloc(), you can switch all allocations to tinyalloc by simply writing...
I think we’ve shown that malloc is not reliable from threads other than main on T3. Let’s talk about why you need String in more than one thread. There is no reason to use multiple threads for anything that is logically...
I think that's correct. It's not just TeensyThreads, but rather any RTOS with a stack per task. And T4.x is okay because it uses smalloc() rather than malloc?
I tried this malloc alternative...
I tried a few more things, including having the thread stacks on the stack of the main thread, and I think the fundamental problem is the same. If you call malloc() with different stack pointers, you can overwrite...
Doing some or occasional malloc from main thread seems to “unlock” the heap for malloc by the other threads, but I don’t think it’s meant to work that way, and it works only “accidentally”. It never makes sense for top...
It seems like even if it works, it's not going to work as expected when the stack pointer for all threads other than the main thread is below the top of the heap. Can you comment on that? One of your first suggestions...
I had the same experience. Made a small, valid change to a working program, and the program stopped working completely. What I think I see in the test results are that malloc() only works (for some undefined time) after...
I guess I don't understand this part. In my test program (update below), the blocks are allocated in order from lowest to highest address, but with some failures among threads other than the main thread. Error pattern...
malloc() will report that no memory is available if the requested allocation will collide with the stack, as defined by the value of the stack pointer at the time of the call to malloc(). With TeensyThreads, each thread...
Yes, many pitfalls. It seems like dynamic allocation will work only if it is limited to the main thread, where the stack pointer is the system stack pointer. Probably a good idea to also limit Strings and printing to...
malloc() works as expected in the main thread (loop), but not in the thread created via addThread(). Something to do with that thread's stack having been allocated from the heap?
I also ran the code on 3.5 and got the error. If I move the malloc() code from the thread function to loop(), it runs okay there until memory is exhausted, so there is something about how threads and malloc() interact....
I think I began using the library below to reduce code size associated with printf(), but the documentation makes a point to that it is not only small, but also thread-safe and does not use malloc().
...
Others know more about this than me, but I think the short answer is the T4 processor is a lot more complex than the one on UNO or DUE. See section 28.2 of the processor reference manual for a description of the ARM M7...
@luni, it looks to me like the new setPeriod() in your fixFTM branch will do what you want. Because you have FTMEN=0 in the FTMx_MODE registers, and you are using output compare, writes to the CV registers take effect...
I checked the source code, and it looks like setPeriod() is not implemented for FTM, so that may explain why that function is not doing what you want. It looks like t1.trigger() will do what you want, i.e. stop the...
With a PeriodicTimer, the timer starts when you call begin(), so you could call t1.begin() in the hw_interrupt function instead of in setup(), and then stop the timer after 10 calls to timer_callback(). I think the...
Installed IDE 2.0 for the first time last week (rc9) on Windows 7 64-bit. Today when I started IDE 2.0, it notified me that rc9.1 was available. Download/install was fully automatic, so that was pretty impressive. I can...
You're welcome. Yes, it seems a good idea to be able to modify the output pulse width and also to be able to reinitialize the input period measurement. In this case we can do that with a single command, but if you ever...
Hi Biff. Here's an update that does a couple of new things. It processes serial input from the Arduino console and looks for valid numerical characters. When newline is found (user hits enter), the input string is...
Not sure if one is preferred. Either should work.
memset() is a standard library function, defined as shown below. The address (s) is type void*, value (c) is type int, and size (n) is size_t and is the number of...
Thanks very much for the info. I've seen preallocation mentioned in that other thread, so I'll have to read about it. Good luck at Salt Lake, and let us know how it goes.
You're welcome. I was kinda glad to have a reason to understand the FTM module better. The way that I ended up doing it is not obvious in looking at the code. FTM0 ch4 (pin 6) does input capture on rising edges, and...
Thanks for the insights. Just a great application and must be a lot of fun to see it all work. There are some recent threads discussing best practice for SD logging, and that's something I need to do in my application...
Please try this one. I might have been in the middle of a change when I did my last copy/paste. I confirmed that this builds for T3.2, though I'm testing on T3.5
...
Okay. Try this one, which (I think) sync's the output pulse on each rising edge of the input. However, if you do single triggers, you will likely get output pulses in between your input pulses. This program assumes a...
@Biff, I figured out how to use the COMBINE mode PWM on two FTM channels to generate the output signal without interrupts. The code below does that, and you can set the output width from 1% (or even less) to 99% (or...
Very cool. Can you tell us a little about the hardware and software? I'm curious what is the control frequency, how many analog I/O, whether you are using on-board ADC or external, etc.
I'm guessing that's because you're really close to the boundary between OK and too short. I'm not sure exactly what variables exist from one run to the next, but I do think it's possible that the same value could fall...
@joe, trying the 5% duty cycle works well at 50 kHz (see first figure below). But if I increase the frequency to 55 kHz, the duty cycle breaks, and becomes closer to 100% (see second figure below). Any idea why?...
@Biff, glad that's working for you. The method I had hoped to get down to 2% on the output was to use the COMBINE feature to couple together two FTM channels to produce both the rising and falling edges of the output...
Here's a bug fix for the version that uses FTM input capture and output compare. The fix is that variable "input_period" must be 16-bit unsigned to avoid error on roll-over of the 16-bit FTM counter. This version works...
Updated version w/ more and better comments and elimination of a few "magic number" constants. Use variable "output_width_pct" to set output width as % of input period.
EDIT: On further reading of the FTM chapter in...
Here is a program that does what you want, as I understand it. It uses 3 pins
- pin 3 is 50 kHz PWM to simulate the 50 kHz input signal
- pin 9 is the input signal (FTM0 ch2) and does input capture on RISING edge
-...
That helps. Tomorrow I'll take a shot at using FTM for both input (input capture on rising edge only) and output (output compare for rising/falling edges of output). We should only need the rising edge of the input...
You said previously that the output rising edge could be at the same time or soon after the input rising edge. And now you're saying the output pulse width depends on something other than the input pulse width. Does...
I take your sentence above to mean that the RISING edge of the output pulse can start "any time after the (rising edge of the) input pulse". Can you say something about the requirements for the output pulse width?...
FreqMeasureMulti can definitely be used to measure the period and high time of the input pulse, but unless you modify the library, there is no hook into the rising/falling edge ISRs. If you brought your input signal to...
The frequency and high time of any PWM signal is based on a clock frequency. In the case of T4.0, the clock frequency of the PWM module is F_CPU/4, so for your F_CPU=528MHz, the PWM clock frequency is 528/4 = 132 MHz....
It's complex enough that I would try simplifying the program to either identify the source or eliminating some of the stuff. Since nobody is going to have your board or sensors, try taking out all of the SPI and...
I had to read your last sentence a few times, but now I get it, and yes, I think that's a good idea. The OP didn't say there was a specified delay from rising edge of input to rising edge of output, so you could set the...
The method we've been trying is the best I can think of that doesn't involve developing any low-level code. If it needs to be better, I would want to get away from the digital input interrupt and use a flex timer...
Hi Kurt. Just a note that my comment in the line that defines PWM_FREQUENCY is incorrect. 50 kHz signal has a period of only 20 us, not 200 us. According to the OP's spec, the output pulse must have high time less than...
And here's one more update that (I think) sets the priority of the OneShotTimer to 0, which should further reduce the jitter.
#include "TeensyTimerTool.h"
#define PWM_SIGNAL_PIN (3) // must use a pin that has...
Here's an update with additional code in setup() to increase the priority of the digital input interrupt to 0 (highest). This should help reduce variability in the measurement of the input pulse width, and is probably...
That is much better, though. There is only a little jitter in the start of the output pulse relative to the input pulse, and more jitter (variation) in the length of the output pulse. I think this is because the length...
long values are 32 bits. Signed long values have range -2147483648 to +2147483647. If you keep adding negative numbers, your sum will eventually roll over to the positive range, and if you add positive numbers, you can...
Oh, yes, good point. The digital input and timer interrupts shouldn't coincide, but I forgot about systick. I know how to raise the priority of the digital input interrupt, but I'll have to look into TeensyTimerTool and...
Thanks for those reminders, Paul. Here's an update with FASTRUN for the interrupt routines and the Serial.printf() statements commented out. I left the interrupts at their default priorities for now, since they should...
There is going to be some jitter, and it's going to look much worse at 50 kHz than it will at 10 Hz. I'm guessing, but did you change the relationship output_width = input_width/2 ? You will run into trouble as...
Here's another update with an important change. In the previous version, "high_time_us" was an integer, and in this version it's a float. The measurement of the high time of the input pulse is in ARM clock cycles and...
Here's an update to the previous program that uses Paul's suggested method, but instead of using 2 pins, one for rising and one for falling edges, this one interrupts on CHANGE (both rising and falling edges). The input...
When you say "the width of the source pulse would be measured in advance", do you mean the Teensy 3.2 does not need to measure it, and it will be a constant for a given build? If so, you could use this simple approach:...
Without looking into it too much, I think you would be using the serial interface, which seems to be a 3-wire SPI-like interface, with pin 6 being the chip select, pin 7 the clock, and pin 8 the data. The audio data is...
In the Pin Function table on page 2, it shows that pins 6/7/8 have differing functions based on whether the chip is used in parallel or serial mode. Assuming you plan to use serial mode, you choose the mode via register...
Generally, yes, you can change interrupt functions. Seems like it should probably be done like this
- set function pointer
- enable interrupt
...
- disable interrupt
- set new function pointer
- enable interrupt
Seems like it's more about promotion (conversion?) from unsigned to signed than from 16 to 32 bits, and would still be wrong on AVR.
(_adr_EEPROM-1) is a signed value because the constant "1" is signed. When...
Oh, that's too bad. arduino-printf is very complete, supporting all (?) standard data types and formatting options. It might not seem very appealing now, since you just removed all of those calls to sprintf(), but maybe...
This link is for a small, dependency-free and thread-safe implementation of printf/sprintf/etc. by Marco Paland.
https://github.com/mpaland/printf
I use this library, which is fork of Marco's printf() and...
Sounds and looks like the bootloader is unable to write to flash block 91 on that particular T4.0. If it always fails on the same flash block, that would be further confirmation of a bad flash. Do you have another T4.0...
I second Mike's suggestions, especially the question on use of Serial printing from multiple threads without locking. That has been the source of problems in quite a few forum questions related to TeensyThreads and...
No, they are two separate pins. In the code below, which is the same as posted by RRdae, but shows a few more lines above Setup(), you can see that MeasHigh and MeasPeriod are variables of type FreqMeasureMulti. In...
30000 floats x 4 bytes/float / 0.5 sec = 240000 bytes/sec = 2.4Mbps
Teensy 4.x can go a lot faster than that. Based on a long thread I've seen on the forum, the issue is probably that your PC is not keeping up on the...
I think you can assume that you can reliably count edges of your 10 MHz external clock. If your TXCO is 10 MHz, and you set your match value in the range 1000 to 10000, you will get interrupts that are nominally 100 us...
I can understand the desire to have timers with callbacks, but it sounds like you may not have all of the necessary logic to stop/start/reset those timers when events occur, such as pushing a button. The timers are nice...
The default clock frequency for T4.x GPT and PIT timers in TeensyTimerTool is 24 MHz, so max period in 32 bits is (2^32)/24e6 = 178.95697 seconds. There are both 32- and 64-bit software-based timers (TCK). At 64 bits,...
You can set the CPU Frequency from the Tools menu of Arduino IDE. Nominal frequency for T3.6 is 180 MHz. For the T4.1, the closest setting is 150 MHz, so you could try that. Do your PID loops run at a fixed frequency...
Yes, the decimal part is discarded when converting the float result to an integer, but 0.5 is added. The modulo value will be <= 64434 as long as 150M/Freq < 65534.5