Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

FIQ help needed

Posted by Ricky on June 21, 2007
Processor: STM750 (ARM7)
Compiler: IAR

I'm programming firmware for a stepper motor. Currently, the time between steps is controlled by a timer that sends a pulse to the stepper motor every time it expires. An IRQ interrupt allows the timer to be reloaded and other things to be done every step.

The problem is that when FreeRTOS switches tasks, it disables interrupts for as long as 28 microseconds. This causes the motor interrupt to be delayed sometimes until interrupts are reenabled. This interrupt MUST NOT be delayed for any length of time!

I thought that the answer to this problem would be to set up the timer to trigger a fast interrupt (FIQ), since they have a higher priority than IRQs. So I tried setting up Timer 2 to generate an FIQ. But when I run the program, the FIQ is always active because the FIQ Pending bit won't clear (interrupt signal always on?). An oscilloscope shows no activity on the GPIO line defined as the output from the timer.

Can anyone tell me how to simply set up a timer to generate an FIQ? I can't find any documentation anywhere on this subject, and ST's documentation doesn't tell an ARM newbie like me what to do.

Thanks!

RE: FIQ help needed

Posted by Richard on June 22, 2007
For ST microcontroller specific settings I would suggest posting a question on the ST forum (somewhere on mcu.st.com).

As a FreeRTOS.org note, I have successfully used the FIQ to run high priority interrupts in the manner you describe. Note however that you may need to change the definitions of vPortEnterCritical() and vPortExitCritical(). In the ST750/IAR port these use the intrinsics __diable_interrupt() and __enable_interrupt(), and I'm not sure if these disable/enable both IRQ and FIQ, or just IRQ. In your case you want only the IRQ to be disabled. Note also that FIQ interrupts cannot use FreeRTOS.org API functions with such a setup.

Regards.

RE: FIQ help needed

Posted by Ricky on June 22, 2007
I can help you with this one. __disable_interrupt() disables both FIQ and IRQ interrupts. Here's the disassembled code for the IAR functions called by the intrinsic (comments are my own). Note that there are two entry points in the disable function, one for Thumb mode and one for ARM mode, but for some reason there's no Thumb mode entry for the enable function.

Disable interrupts:

??DiI_t: ; This function is in Thumb mode
bx pc ; Jump to the ARM function
nop ; Alignment instruction
??DiI_a: ; This function is in ARM mode
mrs r12, cpsr ; Get the status flags
orr r12, r12, #0xC0 ; Disable both IRQ and FIQ
msr cpsr_c, r12 ; Store the updated status flags
mrs r12, cpsr ; Get the updated status flags again
ands r12, r12, #0xC0 ; Were the flags set okay?
beq ??DiI_a ; No, go back and try again
bx lr ; Return to caller

Enable interrupts:

??EiI_a: ; This function is in ARM mode
mrs r12, cpsr ; Get the status flags
bic r12, r12, #0xC0 ; Enable both IRQ and FIQ
msr cpsr_c, r12 ; Store the updated status flags
mrs r12, cpsr ; Get the updated status flags again
ands r12, r12, #0xC0 ; Were the flags cleared okay?
bne ??EiI_a ; No, go back and try again
bx lr ; Return to caller

In order to keep from disabling FIQ, the two 0xC0's needs to be changed to 0x80.

I added custom assembler functions with the same names that affect only the IRQ. Using the same names causes my function to be used instead of IAR's, so I don't have to change any FreeRTOS code.

RE: FIQ help needed

Posted by Frank Andersen on July 10, 2007
Hi Ricky,

Where did you put the Enable and Disable functions, in my attempt the intrinsic functions are still called.

Best regards, Frank Andersen

RE: FIQ help needed

Posted by Ricky on July 11, 2007
I put them at the end of the assembler file containing the interrupt vectors. Make sure the names are exactly ??DiI_t and ??EnI_t for the Thumb mode entry points, and ??DiI_a and ??EnI_a for the ARM mode. Also, make sure you declare those labels public so that the linker will use them instead of the library versions.

RE: FIQ help needed

Posted by Frank Andersen on July 12, 2007
Hi Ricky,

I get two errors:

Error[403]: Illegal register, 'PC' is not allowed here C:\FreeRTOSV431\FreeRTOS\Demo\ARM7_LPC2378_STK_IAR\SrcIAR\cstartup.s79 154

??DiI_t: ; This function is in Thumb mode
bx pc ; Jump to the ARM function this is the error
nop ; Alignment instruction

Then I tried to replace the bx pc with nop, then the following error came.

Error[e27]: Entry "??DiI_a" in module ?RESET ( C:\FreeRTOSV431\FreeRTOS\Demo\ARM7_LPC2378_STK_IAR\Flash_Debug\Obj\cstartup.r79 ) redefined in module ?DiI_t ( C:\Program Files\

Where did you find the assembler code for the functions?

Best regards, Frank Andersen

RE: FIQ help needed

Posted by Ricky on July 12, 2007
I used the IAR j-link debugger to step through the code. The original code set the interrupt disable bits and then looped back to check if they were still set. I got rid of the loop in my version.

Perhaps you can try an end run around the compiler by using "bx r15"? If that doesn't work, try
________ldr_____r0, =??DiI_t
________bx______r0

As for error e27, it appears that you may be including the library file endisint.s79 in your project. If you do that you'll get the "redefined" error. You can only replace functions that appear in libraries, so you'll need to remove the file from your project list and just use the C runtime library (either Normal or Full, go to Options -> C/C++ Compiler -> Library Configuration to set it).

Here's the exact code I have for the IAR EWARM assembler version 4.41:

________rseg____CODE:CODE(2)
________code16

??DiI_t:
________bx______pc______________________// Switch to arm mode
________nop_____________________________// Alignment instruction

________code32

??DiI_a:
________mrs_____r0, cpsr________________// Get the status flags
________orr_____r0, r0, #0x80___________// Disable IRQ interrupts
________msr_____cpsr_c, r0______________// Store the updated status flags
________bx______lr______________________// Return

________code16

??EnI_t:
________bx______pc______________________// Switch to arm mode
________nop_____________________________// Alignment instruction

________code32

??EnI_a:
________mrs_____r0, cpsr________________// Get the status flags
________bic_____r0, r0, #0x80___________// Enable IRQ interrupts
________msr_____cpsr_c, r0______________// Store the updated status flags
________bx______lr______________________// Return

RE: FIQ help needed

Posted by Frank Andersen on July 13, 2007
Hi Ricky,

Thank you very much, I was not aware of the RSEG and CODExx things.

Do you know how to the functions __enable_interrupt and __disable_interrupt is defined, I would like to make two functions for enabling and disabling the FIQ interrupt. I have made a duplicate of the ??DiI_t, ??DiI_a, ??EnI_t and ??EnI_a and change the #0x80 to #0x40.

I would like to have two functions __enable_fiq and __disable_fiq

But depending on if the ARM is running thumb or arm, I need to call:

??DiF_t
??DiF_a

Does I need to check T bit in CPSR and then branch to the t or a function?

Regarding the loop that checks if the I or F bit is set, I have seen and app not from NXP that states that it is neccesary to check if the bit is set. But IAR does not do that.

Best regards, Frank Andersen

RE: FIQ help needed

Posted by Ricky on July 13, 2007
If you're calling the functions from C, you could write the routines in ARM mode only and let the compiler worry about generating the proper code for the call. Just make sure you use the __arm keyword in the C function prototypes so that the compiler can generate the correct code.

__arm void __disable_fiq (void);
__arm void __enable_fiq (void);

You don't have to worry about using the ??DiF_t naming convention since there's no library version of that function.

If you're calling them from assembler, write the routines in Thumb and ARM mode just like I did and then use the bl instruction to branch to the proper label depending on the mode you're in. You don't need to check the T bit because you'll already know which mode you're in by whether the code is written in Thumb or ARM instructions.

There may be some processors that need you to check if the bit is set. But I'm using the STR750 and STR912 processors which don't need the check so I left it out. IAR included it just in case one of the processors that required the check was being used.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner