I have a problem with both the sleepmodes and NVIC_reset(), aka software reset.
The problem is present on two totally distinct boards, both with a LPC1769 uC.
If I enter the sleepmode within main() or another function, except an interrupt routine, the sleep mode is working perfecly. The uC wakes also with an external interrupt on EINT0. The reset function does its job also well in the main function.
But when a sleepmode or reset request is invoked inside an interrupt routine trouble starts. The sleep mode lookes to be entered but the uC does not wake up anymore.
E.g. enter a sleep mode with EINT1 and wake with EINT0:
void EINT0_IRQHandler(void)
{
EXTI_ClearEXTIFlag(0);
}
void EINT1_IRQHandler(void)
{
EXTI_ClearEXTIFlag(1);
CLKPWR_Sleep();
}
Anybody a clue why this does not work properly?
Have you checked your interrupt priorities?
34.3.5.2.1 Wakeup from WFI or sleep-on-exit
Normally, the processor wakes up only when it detects an exception with sufficient priority
to cause exception entry.
Related
I have an EFR32FG14 evaluation board with the example shown in the end.
where it get triggered by an odd number of pins getting pressed.
I want to change this example (in code) so i get the interrupt be triggered by a single pin ,not odd or even.
I have looked inside the example and i see there two lines
NVIC_EnableIRQ(GPIO_ODD_IRQn);
GPIO_ODD_IRQn = 18, /*!< 16+18 EFR32 GPIO_ODD Interrupt */
Inside the GPIO_ODD_IRQHandle event handler called we have
GPIO_IntClear(0xAAAA);
i want to enable interrupt only for PF7(not even or odd) and write an event handler for it.
Is it possile?Thanks.
datasheet:
https://www.silabs.com/documents/public/data-sheets/efr32fg14-datasheet.pdf
user guide:
https://www.silabs.com/documents/public/user-guides/ug318-brd4257b-user-guide.pdf
code example link:
https://github.com/SiliconLabs/peripheral_examples/blob/master/series1/gpio/switch_led_interrupt/src/main_s1.c
I have learned the interrupt system,and ran close example to what i want shown in the post.
The interrupt numbers are fixed when the silicon chip is manufactured. You can't change them.
To have some action taken on PF7 only you could try to use the odd numbered pin interrupt, and then in the handler check which pin was signalled. If it wasn't PF7, then do nothing.
I am currently learning CMSIS-RTOS v2 and I have an issue that is bugging me and I can't find the answer I need.
I am using the STM32L476-Disco board and the joystick center button as an interrupt. I have a very simple Interrupt callback for my center joystick interrupt :
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
//osEventFlagsSet(evt_id,0x0001);
HAL_GPIO_TogglePin(LD5_GPIO_Port,LD5_Pin);
osThreadFlagsSet(ThId_Led_Blink,0x0001);
}
When I call osThreadFlagsSet, the microcontroller freezes and nothing else happen. This is why I've put the HAL_GPIO_TogglePin : to see if the mcu was still responding or not.
I know that my interrupt resets correctly because when I only put my pin toggle, I can toggle the Led correctly.
ThId_Led_Blink is a ThreadId
osThreadId ThId_Led_Blink;
I've checked that the ID is set correctly in my debugger and it is (it's not null).
As you can see, I've tried with osEvenFlagsSet and I have the same result.
When I check the CMSIS_RTOS v2 documentation, it does specify that osThreadFlagsSet can be called from an ISR, but I am not sure if I need to do something else in that case for the Flags to be set correctly and resolve the issue when the ISR is hanging.
Thanks for your help
So after frustrating hours of searching, I finally fixed my issue.
As described in this website : https://www.freertos.org/RTOS-Cortex-M3-M4.html, for STM32 microprocessor, you need to set the NVIC Group Priority to 4. If you look on freeRTOS, they are talking about putting this line in your code :
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
However, the STM32 has it's own library for the NVIC and the correct function to set the priority group is :
HAL_NVIC_SetPriorityGrouping(4);
Why go with the same name when you can change everything?
So make sure to call this function before your kernel initialization if you are using nested interrupts with FreeRTOS/CMSIS RTOS.
Also, make sure that your nested interrupt priority is in the range of configured interrupt priority for your FreeRTOS, otherwise, the osThreadFlagsSet function will fail automatically.
In my app I have three internet operations that run at once. They don't depend on each other so I run each of them in a background thread. They each need to be complete though before my app can move on to the completion handler.
The method that starts each of the three receives as a parameter, block code that functions as a completion handler. This method also has a local variable called internetOperationsRemaining that I set equal to 3 before I start each of the three internet operations.
When each of the internet operations is complete I decrement internetOperationsRemaining on the main thread. This results in internetOperationsRemaining == 0 when they are all complete.
To listen for this condition I run a tight loop on another background thread that simply loops on itself waiting for internetOperationsRemaining to equal 0. Once that happens I call the completion handler that was passed in as a parameter as previously described.
//Spawn a background thread and loop in it until
//allInternetOperationComplete == true.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while(internetOperationsRemaining > 0)
{
//Just spins in here on a background thread waiting
//on the internet to finish.
}
//Now that internetOperationsRemaining == 0, kill the NSURL session
//and call the completion handler on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
[session finishTasksAndInvalidate];
completionHandler();
});
});
The strange behavior that I am seeing is that the app runs perfectly if I have debug set in the scheme, and it doesn't if I have release selected. It simply never breaks out of the while loop.
If I insert some trivial code in the while loop to slow things down just a little it works fine in both debug and release.
while(internetOperationsRemaining > 0)
{
//Just spins in here on a background thread waiting
//on the internet to finish.
int i=0;
++i;
}
I am at a loss to explain this behavior. The tight loop is on a background thread so the app remains responsive to user input as would be expected. I realize that the release scheme introduces optimizations, but I am surprised it actually changed the apps behavior.
Without running code to check, I would think that what is going on is some sort of compiler optimisation which only occurs in Release code.
I think the real problem though is more about design. Using counters and having a thread spinning is not great. I would suggest looking into using NSOperations. You can setup hierarchies of operations so that your completion operation is dependant on the other three. Go read up on using operations, concurrent queues and dependencies and you will get the idea.
I am using a system.timer in a Windows Service to run a process that usually exceeds the timer's interval. I am trying to keep the timer from firing the same code more than once, a known issue with system.timers.
What I want: The timer runs my code, but the timer "pauses" to wait until the code is completed before resuming ticks.
I have two problems:
The way system.timers work is that the timer will create a race condition on you by launching new redundant threads of the same code and pile them up on you if the has not completed by the time the timer's interval has elapsed.
I would start/stop the timer to keep this from happening, but with a System.Timers.Timer, once you stop the timer for the processing to complete, it never comes back - I have never been able to restart a timer once it has been stopped, it has been destroyed and likely collected. Enabling/disabling is the same exact thing as start/stop with same results.
How on earth do you keep a system.timer from launching new redundant threads of the same code if the process has not completed by the time the timer's interval has lapsed? Obviously, starting/stopping (enabling/disabling) the timer is NOT a solution, as it doesn't work.
Help!
Start your timer when it needs to start, kick off another thread to do the work after which the timer can be stopped. The timer won't care if the thread completed or ran away with the prize money. Use Task Parallel Library (TPL) for the most effective usage.
The Start and Stop methods on the Timer do actually work in a Windows service.
I have multiple production services which use code that do that, except my code is written in C#.
However, make sure you are using the System.Timers.Timer and not the Windows.Forms.Timer
Here's a quick example of C# / pseudocode of what my services look like.
// this is the OnStart() event which fires when windows svc is started
private void OnStart()
{
// start your timer here.
MainTimer.Start();
}
private void ElapsedEventHandler()
{
try
{
// Stop the timer, first thing so the problem of another timer
// entering this code does not occur
MainTimer.Stop();
//Do work here...
}
catch (Exception ex)
{
// if you need to handle any exceptions - write to log etc.
}
finally
{
MainTimer.Start();
// finally clause always runs and will insure
// your timer is always restarted.
}
}
i am working on a project in msp430f2274 microcontroller. In my project i am trying to read an reed switch which is being connected to a GPIO pin at P2.3. Normally the pin will remain HIGH as it is being connected to pull up from the hardware. when once the switch is pressed/activated a LOW will come and it will trigger the Hardware. till here it is working fine. but now i want to read the other interrupt also, when it goes back to high. I have tried the interrupt type from low - high to high -low in ISR but still no efffect. please help.
i have added ISR from the code
static char x=0;
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
P1IES^=BIT2;
P1OUT^=(BIT0); // enrer the rest code for detection of door open or close.
P1IFG &= ~BIT2;
//P1IES&=~BIT2;
__bis_SR_register_on_exit(GIE+LPM0_bits); // Enter LPM3 on ISR exit
}
Just an idea, sry if this doesn't help.
You could use a timer that starts with the button click and triggers an interrupt when the button is released.