0
#include "stm32f4xx.h"
#define  SR_CC1IF  (1U<<1)
#define  SR_CC2IF  (1U<<2)
#define  SR_CC3IF  (1U<<3)
#define  SR_CC4IF  (1U<<4)
int reg_a;
int reg_b;
int reg_c;
int reg_d;
int x;
int main(void)
{
  tim1_all_channels_input_capture();
  while(1)
  { 
     while( (TIM1->SR & SR_CC1IF)==1 && (TIM1->SR & SR_CC2IF)==1 && 
            (TIM1->SR & SR_CC3IF)==1 && (TIM1->SR & SR_CC4IF)==1 )
     {
       x=x+1;
       reg_a =TIM1->CCR1;
       reg_b =TIM1->CCR2;
       reg_c =TIM1->CCR3;
       reg_d =TIM1->CCR4;
     }
  }
}

Above is my code. I am doing input capture on TIM1 ch1,2,3,4 (all channels). Second while loop checks if an input capture occurred or not by checking the Status register(SR) bits 1,2,3,4 respectively for ch1,ch2,ch3, and ch4. If 1 that means capture occurred.

When all of these channels have been captured then I enter the while loop and start storing the CCRx value in variables. Whenever I read a value from CCR1 register the SR registers bit 1 has to reset to 0. For CCRx, SR register bit x should reset according to the reference manual by ST. I am using a STM32F401RE.

enter image description here


enter image description here


The problem is when I am reading CCR1(ch1), CCIF1(SR bit 1) is set to '0' but also rest of the SR bits are set to '0' (bit 2,3,4). Even though I have not read from their respective registers.

Is there any way to avoid this?

edit::

#include "stm32f4xx.h"
#include  <stdint.h>
#include <stdio.h>
#include "math.h"
#include<stdlib.h>

#define SR_CC1IF (1U<<1) #define SR_CC2IF (1U<<2) #define SR_CC3IF (1U<<3) #define SR_CC4IF (1U<<4) #define SR_CC_ALL (SR_CC1IF | SR_CC2IF | SR_CC3IF | SR_CC4IF)

int reg_a=0; int reg_b=0; int reg_c=0; int reg_d=0;

void tim2_all_channels_input_capture(void);

int x= 0; void main(void) { tim2_all_channels_input_capture(); while(1) {

    volatile uint32_t sr = TIM1-&gt;SR;

    if((sr &amp; SR_CC_ALL) == SR_CC_ALL)
    {
    x=x+1;
    reg_a =TIM1-&gt;CCR1;
    reg_b =TIM1-&gt;CCR2;
    reg_c =TIM1-&gt;CCR3;
    reg_d =TIM1-&gt;CCR4;
    }

}

}

1 Answers1

3

There's just too many bugs and problems... Some remarks/general code review:

  • (TIM1->SR & SR_CC2IF)==1 etc -> (TIM1->SR & (1U<<2))==1 is plain wrong since CC2IF results in 0x4 not 0x1. Same bug with all of those masks. Instead you should check (TIM1->SR & SR_CC2IF)!=0.

  • Most MCUs do not have bit-level instructions but operate at least on byte level. That means that each of your TIM1->SR & SR_CC1IF checks result in a register read - you keep reading the register over and over. That's wrong and inefficient.

  • reg_a =TIM1->CCR1; reads the register and as the friendly manual points out, doing so will clear the SR register.

  • While single stepping and having a raw memory map and/or hardware peripheral view of the register open in the debugger, the debugger is usually not smart enough to pay special respect to "clear by reading" registers. So it's a known problem with debuggers that single stepping through such code might cause the debugger to clear registers.

  • Are you sure that you should loop and read while the flags are set? That doesn't make much sense. Seems that the while should be swapped for an if.

  • Never use signed int when dealing with raw binary data. There are very few situations where you should ever use it at all. Stick to the stdint.h types instead.

  • The correct format of main() for "freestanding" microcontroller systems and the gcc compiler is void main (void), since freestanding systems never return from main. Make sure to compile with -ffreestanding.

  • Global variables should be avoided.

A first start towards a working program might look like this:

#include "stm32f4xx.h"
#include <stdint.h>
#define  SR_CC1IF  (1U<<1)
#define  SR_CC2IF  (1U<<2)
#define  SR_CC3IF  (1U<<3)
#define  SR_CC4IF  (1U<<4)
#define  SR_CC_ALL (SR_CC1IF | SR_CC2IF | SR_CC3IF | SR_CC4IF)

void main (void) { uint32_t x=0; uint32_t reg_a=0; uint32_t reg_b=0; uint32_t reg_c=0; uint32_t reg_d=0;

tim1_all_channels_input_capture();
while(1)
{
    volatile uint32_t sr = TIM1-&gt;SR; // only read the actual register once

    if((sr &amp; SR_CC_ALL) == SR_CC_ALL)
    {
      x=x+1;
      reg_a = TIM1-&gt;CCR1;
      reg_b = TIM1-&gt;CCR2;
      reg_c = TIM1-&gt;CCR3;
      reg_d = TIM1-&gt;CCR4;
    }
}

}

Lundin
  • 20,162
  • 1
  • 26
  • 76
  • The OP seems to want to check if all the CCxIF flags are set, while your suggestion only checks for any one of them. – brhans Oct 31 '23 at 15:12
  • @brhans Ah, fair enough. Will fix, thanks. – Lundin Oct 31 '23 at 15:17
  • @Lundin Using global variable because if I make it local it doesn't work with the debugger. if((sr & SR_CC_ALL) == SR_CC_ALL) I think this wont work because SR register has more bits further up(bit 6,7,8...16) which are set by the system. I am using 'while' because i continuously want to monitor SR ,as soon as it is true it should be executed. I have made some changes to code in the answer ..can you have a look. –  Oct 31 '23 at 15:45
  • 1
    @rachitjuthani Bad debugger or maybe you are debugging with optimizations enabled. You could declare them static to move them off the stack, while keeping them in local scope. – Lundin Oct 31 '23 at 15:48
  • 1
    @rachitjuthani "I think this wont work because SR register has more bits further up" It will work just fine, that's what bit masking is for in the first place: to mask out the relevant parts. – Lundin Oct 31 '23 at 15:48
  • @rachitjuthani "I am using 'while' because i continuously want to monitor SR" In the code as-is, you are already looping in the while(1). In a more complex program you would perhaps use interrupt instead, especially if an immediate reaction is required. – Lundin Oct 31 '23 at 15:51
  • @Lundin does it mean that if I read any CCRx register the whole SR register will reset?There are other bits in SR that are not resetting. Only bits 1,2,3,4 are resetting. –  Oct 31 '23 at 15:57
  • @Lundin there are also variables that I am defining as float, should i define them as uint32_t ? –  Oct 31 '23 at 16:48
  • @rachitjuthani The registers will supposedly get cleared on bit level as told in the manual. That's handled by the MCU. As for float it should normally be avoided entirely in embedded systems. I think your particular flavour of MCU has FPU on-chip though, so it can be used without getting horrible slow code. As for when to use it, see this: https://electronics.stackexchange.com/a/494924/6102 – Lundin Nov 01 '23 at 07:26