7 years, 9 months ago.

Precise timing with mbed in microseconds?

Hello I am trying to send bits through the GPIO of my STM32 Nucleo 401RE with an mbed compiler at 5 microseconds per bit. I wrote this simple code to test the timing of the microcontroller:

write bit

#include "mbed.h"

DigitalOut mypin(D8);

float wtf[]={0,1,1,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1,1,0,0,1,0,1,1,0,1,0,1,0,0,1,0,1,1,0,0,1,1,0,0,1,1,0,0,1,0,1,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,1};
int main() {
while (1) {
for (int i=0; i<=63; i++) {
if(wtf[i]==1){
    mypin=1;
    wait_us(5);}
else{
 mypin=0;
 wait_us(5);
 }
}
}
}

However, i found that at 5 microseconds (200KHz) I was getting timing errors of around 1 or 2 microseconds for each bit. This is unacceptable for what my eventual goal is, which requires very precise timing at this speed. Is there a way to achieve this with mbed?

3 Answers

7 years, 8 months ago.

Shaheer, when using wait_us the processor sits idle for 5us in this case, then it executes some code. So, your timing is going to be 5us + however long it takes to loop around and set new digital output.

You could try using the "ticker" API. I don't know how precise that is.

The other round about way but should be very precise would be to use a pwm output looped back around to a digital input. Set the PWM frequency with a multi-meter or oscilloscope then use "InteruptIn".

Someone else here may have a much better answer. I'm certainly no expert.

Corey

7 years, 8 months ago.

Shaheer, consider to use XMOS for this requirement which is a very suitable option.

See here, figure 4:

http://www.xmos.com/download/private/XS1-Ports-Specification(X1373A).pdf

You can get started with the XMOS startkit @ $15 USD from Digikey. The best suggestion is to marry mbed with XMOS as follows:

http://www.digikey.com/products/en?keywords=startkit%20xmos

set up the XMOS IP using XC language to R/W your data from mbed over I2C

then use the XMOS IP to stream out the data with precise output as required

With XMOS, you can dedicate your idea into a single thread but run 8 parallel threads per tile at the same time. If required, you can cascade with additional CPUs with additional tiles. For your immediate request, the startkit should work out fine. I2C IP is available through the many posted projects + use mbed for any GUI / quick USB, etc. and allow the XMOS CPU to stream out with precision.

XMOS is the middle ground of standard micros and FPGA devices. Hope this helps.

7 years, 8 months ago.

Maybe a bit more unconventional idea, but should work fine:

Replace wait_us with your own wait function that just runs a loop: for(int i = 0; i < size; i++) {NOP(); }. Reason for this is that you have more resolution in your wait time (if 1us is sufficient, you can also stick to wait_us());

Now in your program time how long it takes to set your output pin 1000 (or more) times to '0', using normal Timer functions. Do the same again, but now you set your output pin 1000 times to 0, and you also have the previous wait statement in the loop, with a rough estimate with how long that should be. With this information you can then calculate how long your wait statement should be.

As example: setting output 1000 times to zero costs you 300 microseconds. Setting output 1000 times to zero + having a wait_custom(100); in the loop takes you 4000 microseconds. Your goal is that it takes 5000 microseconds (then it is 5 microseconds per bit). Since now your custom wait took 4000-300 = 3300 microseconds, and it should be 1000 microseconds longer. So you need to do wait_custom(100 * 4300 / 3300) = wait_custom(130).