how catch interrupt in low level code ? ( STM32F4xx or F1xx)

What are you developing?
Post Reply
jcbuntu
Posts: 27
Joined: Wed Jun 02, 2021 1:47 pm
Location: Andon 06 - France

how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by jcbuntu »

Hello.
I would, now, code without external libraries or others facilities. Documentation STM is very heavy and it's good for ... neurons ! :)
I've tried, with success, to work with timers and theirs different channels on inputs and outputs pins.
But for interrupts, i'm blocked ...

I use Roger's core on Arduino IDE with Linux on STM32F407VET6 board ( usually Black F4VE !).
Actual project is based on SysTick system ( Doc PM0214 §4.5 p 246) witch is a good exemple for intern exception handler.

By reading STK_CTRL register bit COUNTFLAG, i can catch the 0 counter by pooling ... and have a delay.
And now, the best :
** 1 Always by pooling, when i modify the STK_LOAD register ( i.e. FFFFh) as say in §4.5.2 p248, board don't work (but it's OK when base value is 18750d -> 493Eh) : :o

Code: Select all

#define LED2 PA6    //PA6
#define LED3 PA7    //PA7
#define GPIOA_EN 0  //RCC_AHB1ENR bit 0 - activation horloge du portA

#define STK_EN   0  //STK_CTRL  → bit 0 - Activation down-count

//=======================  RAM  ===============================
//------------------  Variables globales  ---------------------
volatile unsigned long FlagSTK = 0x00000000;

//...............  Registres STM32F407 GPIO .....................
volatile unsigned long *AHB1_ENR =      (unsigned long*) 0x40023830;

volatile unsigned long *GPIOA_MODE =    (unsigned long*) 0x40020000;
volatile unsigned long *GPIOA_OSPEED =  (unsigned long*) 0x40020008;
volatile unsigned long *GPIOA_AFL =      (unsigned long*) 0x40020020;
volatile unsigned long *GPIOA_AFH =      (unsigned long*) 0x40020024;
volatile unsigned long *GPIOA_OD =      (unsigned long*) 0x40020014;

//...............  Registres STM32F407 SysTick .....................
volatile unsigned long *STK_CTRL =      (unsigned long*) 0xE000E010;
volatile unsigned long *STK_LOAD =      (unsigned long*) 0xE000E014;
volatile unsigned long *STK_VAL =       (unsigned long*) 0xE000E018;
volatile unsigned long *STK_CALIB =     (unsigned long*) 0xE000E01C;

//=======================  Fonctions  ===============================
//====================  End of preamble  ===============================

void setup() 
  {
  //--------------  Config pin de sortie des 2 LED  ----------
  *AHB1_ENR |= (1<<GPIOA_EN); //Valide l'horloge du port A-(Arduino:facultatif)

#ifdef ANIM
  //LED 2 et 3
  *GPIOA_MODE |= ((1<<(PA7<<1)) | (1<<(PA6<<1)));     //PA7,PA6 ordinaries outputs
  *GPIOA_OSPEED &= ~((1<<15)|(1<<14)|(1<<13)|(1<<12)); // PA7 et PA6 low speed
  *GPIOA_OD |= ((1<<PA7)|(1<<PA6));   // PA7 et PA6 = 1 => LED OFF
#endif

//--------------  Config SysTick  ----------

  *STK_LOAD = 0x0000493E;             //décimal = 18750 -> tempo 1ms
  *STK_VAL =  0x00000000;             //RAZ compteur
  *STK_CTRL |= ((1<<STK_EN)); //Lance le comptage
  }

void loop() 
{
  static unsigned char EtatLED3 = 0;
  static unsigned int NbreCNT = 0;  


  if(*STK_CTRL & STK_FLAG) NbreCNT++; //Capture COUNTFLAG state
  if( NbreCNT >= 112)
  {
    EtatLED3 += 1;     //Inverse l'état de la LED3 (seul LSB utilisé)
    if( (EtatLED3 & 0x01))  *GPIOA_OD &= ~(1<<LED3);  //ON PA7 -> bit 7 = 0
    else *GPIOA_OD |= (1<<LED3);            //OFF PA7 -> bit 7 = 1

    NbreCNT = 0;
  }
}
** 2 Interrupt. i've tried to work with exception ( it's interrupt for core system) with the code follow :

Code: Select all

//==================  Pré-compilateur  ========================
//------------------  Macros  - Constantes  -------------------


#define LED2 PA6    //PA6
#define LED3 PA7    //PA7

#define GPIOA_EN 0  //RCC_AHB1ENR bit 0 - activation horloge du portA
#define STK_EN   0  //STK_CTRL  → bit 0 - Activation décomptage
#define STK_INT  0  //STK_CTRL  → bit 1 - Active l'exception

//=======================  RAM  ===============================
//------------------  Variables globales  ---------------------
volatile unsigned long FlagSTK = 0x00000000;

//...............  Registres STM32F407 GPIO .....................
volatile unsigned long *AHB1_ENR =      (unsigned long*) 0x40023830;

volatile unsigned long *GPIOA_MODE =    (unsigned long*) 0x40020000;
volatile unsigned long *GPIOA_OSPEED =  (unsigned long*) 0x40020008;
volatile unsigned long *GPIOA_AFL =      (unsigned long*) 0x40020020;
volatile unsigned long *GPIOA_AFH =      (unsigned long*) 0x40020024;
volatile unsigned long *GPIOA_OD =      (unsigned long*) 0x40020014;

//...............  Registres STM32F407 SysTick .....................
volatile unsigned long *STK_CTRL =      (unsigned long*) 0xE000E010;
volatile unsigned long *STK_LOAD =      (unsigned long*) 0xE000E014;
volatile unsigned long *STK_VAL =       (unsigned long*) 0xE000E018;
volatile unsigned long *STK_CALIB =     (unsigned long*) 0xE000E01C;

//=======================  Fonctions  ===============================
void SysTick_IRQHandler( void);    //I suppose it's the good name - not sure
//====================  End of preamble  ===============================


void setup() 
  {
  noInterrupts();			// same result if not here

  //--------------  Config pin de sortie des 2 LED  ----------
  *AHB1_ENR |= (1<<GPIOA_EN); //Valide l'horloge du port A-(Arduino:facultatif)

  //LED 2 et 3
  *GPIOA_MODE |= ((1<<(PA7<<1)) | (1<<(PA6<<1)));     //PA7,PA6 en sorties ordinaires
  *GPIOA_OSPEED &= ~((1<<15)|(1<<14)|(1<<13)|(1<<12)); // PA7 et PA6 low speed
  *GPIOA_OD |= ((1<<PA7)|(1<<PA6));   // PA7 et PA6 = 1 => LED éteintes

//--------------  Config SysTick  ----------
  *STK_LOAD = 0x0000493E;             //décimal = 18750 -> tempo 1ms
  *STK_VAL =  0x00000000;             //RAZ compteur
  *STK_CTRL |= ((1<<STK_EN) | (1<<STK_INT)); //Valide down-count et exception

  interrupts();		// same result if not here
  }

void loop() 
{
  static unsigned char EtatLED3 = 0;
  static unsigned int NbreCNT = 0;  

  if( FlagSTK >= 630)
  {
    EtatLED3 += 1;     //Inverse l'état de la LED3 (seul LSB utilisé)
    if( (EtatLED3 & 0x01))  *GPIOA_OD &= ~(1<<LED3);  //Allume PA7 -> bit 7 = 0
    else *GPIOA_OD |= (1<<LED3);            //Eteint PA7 -> bit 7 = 1

    FlagSTK = 0x00000000;
  }
}


//Handler of Systick - Name not sure ... I've not seen any documentation.
void SysTick_IRQHandler( void)
{
  FlagSTK++;
}
The name of exception normalized handler is not sure :oops: . This way don't use traditional issue of NVIC ( only for priority) because it's a negative interruption number (-1) (PM0214 §2.3.3 p39).
So, perhaps somebody could help me to understand ... with only basic C code : :?
How catch the normalized exception of SysTick ?
How install a personal handler address in vector address 0x0000 003C (RM0090 p372) ?

Thank you for reading my heavy post.
mrburnette
Posts: 633
Joined: Thu Dec 19, 2019 1:23 am
Answers: 7

Re: how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by mrburnette »

Have you read the following in your quest?

https://github.com/rogerclarkmelbourne/ ... t-handlers
jcbuntu
Posts: 27
Joined: Wed Jun 02, 2021 1:47 pm
Location: Andon 06 - France

Re: how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by jcbuntu »

No ! i'm stupid ... my web requests was'nt the bests !
Your link seems really interesting and synthetic. I've a good work to understand and test these informations.
I'll post here when tests are in progress.
thank you.
jcbuntu
Posts: 27
Joined: Wed Jun 02, 2021 1:47 pm
Location: Andon 06 - France

Re: how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by jcbuntu »

Hello.
It's OK, now, for all low level functions !
After reading object of your link, i've get informations about the exact name that sould have the SysTick handler.
Always no official document ... but in my directories !
I've found .../arduino-1.8.13hardware/Arduino_STM32-master/STM32F4/cores/maple/libmaple/systick.c file.
At the end of this file, there is the name and code -> void __exc_systick( void) ... and it was my first way.
So, i've put, in my STM32Duino my own handler :

Code: Select all

void __exc_systick( void)
{
  FlagSTK++;
}
... no result but compilation error ->

Code: Select all

nvic.h:219: multiple definition of `__exc_systick'
Systick.ino:82: first defined here
collect2: error: ld returned 1 exit status
In fact, the linker work, first on the shetch .ino, and secondly on libraries. I've commented the handler in Roger's libraries ( systick.c) ... and compilation was OK.
But LED blink one shot ... and it's not blink definition !
I've added reading of COUNFLAG bit in a system register ( it's not explicit in PM0214) and all work fine !

Code: Select all

void __exc_systick( void)
{
  long i = *STK_CTRL & STK_FLAG;	//Read COUNTFLAG - bit purge
  FlagSTK++;				//Active work of handler
}
The names handlers are in
arduino-1.8.13/hardware/Arduino_STM32-master/STM32F4/variants/generic_f407v/ld/vector_symbols.inc and have a different prefix between exception and interruption.

Exceptions are enabled in NVIC after boot, not interruptions. Linker don't like have more than one definition of handler. It was good for me, to find one problem.
Another thank for your help.
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by ag123 »

if all you need is just systick, it is already there
https://github.com/rogerclarkmelbourne/ ... tick.h#L82

Code: Select all

void systick_attach_callback(void (*callback)(void));
jcbuntu
Posts: 27
Joined: Wed Jun 02, 2021 1:47 pm
Location: Andon 06 - France

Re: how catch interrupt in low level code ? ( STM32F4xx or F1xx)

Post by jcbuntu »

Hello, ag123.
I'm in spirit to understand low level commands and links between software and hardware. So, if using libraries perfectly works, i prefer "bare metal" code.
About Systick, it's good now, in low level code.
Thank you for help
Post Reply

Return to “Projects”