If statement does not work inside infinite loop stm32 - c

I am working with a STM32F030R8T6 and the HAL libraries. I use the STM32CubeMX for all the initialization code.
When I use a "if" statement inside the infinite loop it does not work.
Eg.
while (1) {
if ((Seconds - oldSec) >= 10) {
printf("Entramos 10sec\r\n");
oldSec = Seconds;
}
}
but if a use a HAL_Delay() function it works eg.
while (1) {
HAL_Delay(1);
if ((Seconds - oldSec) >= 10) {
printf("Entramos 10sec\r\n");
oldSec = Seconds;
}
}
I do not know, what is the problem?
I use the arm-gcc compiler with makefile.

CubeMX provides optimization level 3 by default and this causes problems if variables are not volatile but changed outside context (like in interrupts).
Solution is to have Seconds and oldSeconds as volatile and make sure Seconds is increased in SysTick_IRQHandler or in HAL_SYSTICK_Callback functions.
Solution is also to set optimizations to level 0. But as you can see what can happen if you don't follow volatile rule, it is better to stay at level 3.

Related

Variable value not updated by interrupt on STM32F4 Discovery

In the code below, I can see that the timer is working normally as the LED is always blinking. But the value of the count variable never changes inside the second while.
I don't know what could possibly go wrong?
// count variable used only in main and TIM2_IRQHandler.
uint8_t count=0;
int main(void)
{
count=0;
SystemInit();
GPIOInit();
NVIC_Configuration();
TIM_Configuration();
init_USART3(115200);
// All initialization is ok.
USART_puts(USART3, "\r\nConnection ok.\r\n");// Working normally
while (1)
{
if(asterixok==1)// No problem. This code if ok ->>process continue next step.
{
GPIO_SetBits(GPIOD , GPIO_Pin_12); // Led on (ok)
count=0;// count going to zero, timer working, must be change in there
while(1)
{
//Led blinking continue
//Timer query working normal led (13) blink.
//There is a problem
if(count>5) // Timer working, count never change in timer interrupt query (WHY)
{
GPIO_SetBits(GPIOD , GPIO_Pin_14); // LED OFFFFFFFFFFFFFFFF
USART_puts(USART3, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n");
goto nextstate;
}
}
nextstate:
GPIO_SetBits(GPIOD , GPIO_Pin_15); // Led never going on because code step in while loop.
}
}
}
void USART3_IRQHandler(void)
{
if( USART_GetITStatus(USART3, USART_IT_RXNE) )
{
unsigned char t = USART3->DR;
if(t=='*')
{
asterixok=1;
}
}
}
void TIM2_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )
{
TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);
count++;
if(count>100)
count=0;
if( display )
{
GPIO_ResetBits(GPIOD , GPIO_Pin_13);
}
else
{
GPIO_SetBits(GPIOD , GPIO_Pin_13);
}
display = ~display;
}
}
I have tried with another Discovery board but the problem continues.
Please help. I'm going crazy!
You should declare count as volatile, as such :
volatile uint8_t count;
While compiling main the compiler was able to prove that count was not modified in the loop body, and so it probably cached its value in a register and maybe even optimized out the if statement. You could verify that by looking at a disassembly. The compiler does not know about interrupts as per the standard and so is permitted to perform such optimizations. Qualifying count as volatile will forbid the compiler from making these optimizations, forcing it to reload the variable from memory each time it is used.
In this simple case volatile will be enough but please be aware that it doesn't guarantee atomicity of operations, and it doesn't prevent the compiler and CPU from reordering instructions around accesses to the variable. It only forces the compiler to generate memory access instructions each time the variable is used. For atomicity you need locks, and to prevent reordering you need memory barriers.

Making a delay in C with 20MHz crystal(beginner level)

I've recently started with C and Im trying to figure out how to make a 10ms delay for
PIC16F884. From the formulas in the datasheet I've managed to create the following:
fosc = 20MHz and Toscx4 = 200ns
If I put a preset to 100 => t=100x200ns=20us and to get a 10 ms delay
10ms/20us = 500
Will the following code in C give me what Im looking for (10ms delay)? Assume I have all the initiating code and variables.
void interrupt ISR(void){
if(TMR0IF){
TMR0IF=0;
counter++;
}
if(counter==100){
delay++;
counter=0;
}
}
int main(void){
TMR0=155;
if(delay>4){
//any code
delay=0;
}
}
Might be a bad example but hopefully you understand
No, since the code in main() never actually waits, it won't implement a delay.
Assuming the interrupt and timer logic is properly set up, you're still going to need to loop:
delay = 0;
TMR0 = 155; /* Start timer. */
while(delay < 4)
; /* Do nothing */
/* More code here, delay has expired */
Also, remember to make delay a volatile variable since you're accessing it from multiple parallel threads of execution.
If you're a really beginner and want a tool that can help you calculate timer settings I advise you to look at this link :
http://www.mikroe.com/timer-calculator/
It generate the ccode for settiing properly a lot of different microcontroller

Delay using timer on raspberry pi

I need to create a accurate delay (around 100us) inside a thread function. I tried using the nanosleep function but it was no accurate enough. I read some post about how to read the hardware 1MHz timer, so on my function in order to create a 100us delay y tried something like this:
prev = *timer;
do {
t = *timer;
} while ((t - prev) < 100);
However, the program seems to stay inside the loop. But if I insert a small nano sleep inside the loop it works (but loosing precision):
sleeper.tv_sec = 0;
sleeper.tv_nsec = (long)(1);
prev = *timer;
do {
nanosleep (&sleeper, &dummy);
t = *timer;
} while ((t - prev) < 500);
I tried the first version in a stand along program and it works, but in my main program, where this is inside a thread it does not.
Does anyone know what the first version (without a small nanosleep) does not work?
I'm sorry to say but Raspberry Pi's OS is not a "real-time OS". In another words, you won't get consistent 100us precision in a user space program due to inherent OS scheduling limitations. If you need that kind of precision, you should use an embedded controller like an Arduino.

Using hardware timer in C

Okay, so I've got some C code to perform a mathematical operation which could, pretty much, take any length of time (depending on the operands supplied to it, of course). I was wondering if there is a way to register some kind of method which will be called every n seconds which can analyse the state of the operation, i.e. what iteration it is currently at, possibly using a hardware timer interrupt or something?
The reason I ask this is because I know the common way to implement this is to be keeping track of the current iteration in a variable; say, an integer called progress and have an IF statement like this in the code:
if ((progress % 10000) == 0)
printf("Currently at iteration %d\n", progress);
but I believe that a mod operation takes a relatively long time to execute, so the idea of having it inside a loop which will be ran many, many times scares me, from an optimisation point of view.
So I get the feeling that having an external way of signalling a progress print is nice and efficient. Are there any great ways to perform this, or is the simple 'mod check' the best (in terms of optimising)?
I'd go with the mod check, but maybe with subtractions instead :-)
icount = 0;
progress = 10000;
/* ... */
if (--progress == 0) {
progress = 10000;
printf("Currently at iteration %d0000\n", ++icount);
}
/* ... */
While mod operations are usually slow, the compiler should be able to optimize and predict this really well and only mis-predict once ever 10'000 ifs, burning one mod operation and ~20 cycles (for the mis-prediction) on it, which is fine. So you are trying to optimize one mod operation every 10'000 iterations. Of course this assumes you are running it on a modern and typical CPU, and not some embedded system with unknown specs. This should even be faster than having a counter variable.
Suggestion: Test it with and without the timing code, and figure out a complex solution if there is really a problem.
Premature optimisation is the root of all evil. -Knuth
mod is about the same speed as division, on most CPU's these days that means about 5-10 cycles... in other words hardly anything, slower than multiply/add/subtract, but not enough to really worry about.
However you are right to want to avoid sting in a loop spinning if you're doing work in another thread or something like that, if you're on a unixish system there's timer_create() or on linux the much easier to use timerfd_create()
But for single threaded, just putting that if in is enough.
Use alarm setitimer to raise SIGALRM signals at regular intervals.
struct itimerval interval;
void handler( int x ) {
write( STDOUT_FILENO, ".", 1 ); /* Defined in POSIX, not in C */
}
int main() {
signal( SIGALRM, &handler );
interval.it_value.tv_sec = 5; /* display after 5 seconds */
interval.it_interval.tv_sec = 5; /* then display every 5 seconds */
setitimer( ITIMER_REAL, &interval, NULL );
/* do computations */
interval.it_interval.tv_sec = 0; /* don't display progress any more */
setitimer( ITIMER_REAL, &interval, NULL );
printf( "\n" ); /* done with the dots! */
}
Note, only a smattering of functions are OK to call inside handler. They are listed partway down this page. If you want to communicate anything for a fancier printout, do it through a sig_atomic_t variable.
you could have a global variable for the iterations, which you could monitor from an external thread.
While () {
Print(iteration);
Sleep(1000);
}
You may need to watch out for data races though.

Using the C preprocessor to effectively rename variables

I'm writing a few very tight loops and the outermost loop will run for over a month. It's my understanding that the less local variables a function has, the better the compiler can optimize it. In one of the loops, I need a few flags, only one of which is used at a time. If you were the proverbial homicidal maniac that knows where I live, would you rather have the flag named flag and used as such throughout or would you prefer something like
unsigned int flag;
while (condition) {
#define found_flag flag
found_flag = 0;
for (i = 0; i<n; i++) {
if (found_condition) {
found_flag = 1;
break;
}
}
if (!found_flag) {
/* not found action */
}
/* other code leading up to the next loop with flag */
#define next_flag flag
next_flag = 0;
/* ... /*
}
This provides the benefit of allowing descriptive names for each flag without adding a new variable but seems a little unorthodox. I'm a new C programmer so I'm not sure what to do here.
Don't bother doing this, just use a new variable for each flag. The compiler will be able to determine where each one is first and last used and optimise the actual amount of space used accordingly. If none of the usage of the flag variables overlap, then the compiler may end up using the same space for all flag variables anyway.
Code for readability first and foremost.
I completely agree with dreamlax: the compiler will be smart enough for you to ignore this issue entirely, but I'd like to mention that you neglected a third option, which is rather more readable:
while (something) {
/* setup per-loop preconditions */
{
int flag1;
while (anotherthing) {
/* ... */
}
/* deal with flag found or not-found here */
}
/* possibly some other preconditions */
{
int flag2;
while (stillanotherthing) {
/* ... */
}
}
}
which would tell a dumb compiler explicitly when you are done with each flag. Note that you will need to take care about where you declare variables that need to live beyond the flag-scope blocks.
Your trick would only be useful on very old, very simple, or buggy compilers that aren't capable of correct register (re)allocation and scheduling (sometimes, that's what one is stuck with for various or ancient embedded processors). gcc, and most modern compilers, when optimizations are turned on, would reallocate any register or local memory resources used for local variables until they are almost hard to find when debugging at the machine code level. So you might as well make your code readable and not spend brain power on this type of premature optimization.

Resources