- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi !
I have PWM that make me 1 sec interrupt and wake up pushbutton. see pic
I see that after I use push button interrupt PWM stopped to make 1 sec interrupts.
Why it's happened ? How prevent it ?
Solved! Go to Solution.
- Labels:
-
PSoC 4 Architecture
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Uri,
0 is the highest priority; and 3, the lowest priority.
High priority interrupt can interrupt in low priority interrupt handler.
See AN90799 PSoC4 Interrupt.
http://www.cypress.com/file/127121/download
Generally, recommend to use same priority for all interrupts. Because during a low priority interrupt handler execution, if another high priority interrupt nested, it might use same peripherals with the low priority interrupt, and generate some 'dirty data' for the low priority interrupt handler. This is unexpected.
Thanks,
Ryan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
chaplin.u,
you must clear interrupt source in ISR routine:
OneSecTimer_ClearInterrupt(OneSecTimer_TCPWM_INTR_MASK_TC);
TCPWM datasheet Page 5: "In order to receive subsequent interrupts, the interrupt should be cleared by using the TCPWM_ClearInterrupt() API in the interrupt handler of the ISR component."
PSoC 4 Timer Counter Pulse Width Modulator (TCPWM)
/odissey1
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Of course I do it.
Each interrupt handler have clear :
// Interrupt for Wakeup
CY_ISR(WakeUp_Isr)
{
if(WakeSwitch_Read() == 0u) /* Switch pressed */
{
WakeSwitch_ClearInterrupt(); /* Clears the PICU interrupt */
...
}
// --------------------------------------
// Increment secs
// --------------------------------------
CY_ISR(Sec_Int)
{
OneSecTimer_ClearInterrupt(OneSecTimer_INTR_MASK_TC);
if(TimerEnable)
{
secs++;
}
}
As I told before seconds timer work fine but after WakeUp_Isr is happened Sec_Int not work.
May be need renew it ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Change your WakeUp_Isr to this:
CY_ISR(WakeUp_Isr)
{
WakeSwitch_ClearInterrupt(); /* Clears the PICU interrupt */
if(WakeSwitch_Read() == 0u) /* Switch pressed */
{
...
}
}
Also, you may need to make sure the PWM works in the power mode you are using.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Problem solved by changing interrupt priority.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
but not final. Now I connected BLE and again it's stopped
I have 5 interrupts
1. for BLE
2. wakeup from sleep
3. received byte from RX
4. timer of seconds
5. sensor
What a rules for priorities ?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Uri,
0 is the highest priority; and 3, the lowest priority.
High priority interrupt can interrupt in low priority interrupt handler.
See AN90799 PSoC4 Interrupt.
http://www.cypress.com/file/127121/download
Generally, recommend to use same priority for all interrupts. Because during a low priority interrupt handler execution, if another high priority interrupt nested, it might use same peripherals with the low priority interrupt, and generate some 'dirty data' for the low priority interrupt handler. This is unexpected.
Thanks,
Ryan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Ryan
I would describe that a bit different:
The highest priority should be given to the most time critical task as BLE.
The lowest priority can be given to all the tasks that are running on (comparably) slow peripherals as I2C or UART.
In the case that an interrupt handler accesses a component that can be used by another task you should encapsulate the access in a "Critical section" by using CyEnterCriticalSection() and CyExitCriticalSection.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Bob
Yes, you are right. I think that is why it requires priority for interrupts. My comprehension about it is a little narrow.
And glad to hear that Uri's project work as needed now.
Thanks,
Ryan
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
rzzh
Generally interrupts won't fire inside each other unless you "get lucky" with coincident events, or the critical case of a very fast-paced interrupts (frequent generation, extended handling time, consistently fired timing).
You will need to adjust the priorities for individual projects, but generally setting the BLE component to higher priority and all others to lower priority works well.
If you set a CyEnterCriticalSection() without having the end of the section, it will leave the interrupt-enable bits messed up, thus always make sure to have a matching pair of Enter and Exit critical section function calls.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you read my post I told I removed disabling interrupts :
/* Disable global interrupts */
// interruptStatus = CyEnterCriticalSection();
I don't know why before system going to sleep need disable interrupts. How I can wake up ?
After I removed it wake up is work.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@chaplin
I understand. I read the post
I was referring to general use; If you put one of them, but forget the matching call to enter/exit critical section, it will cause issues with behavior (such as you saw).
I am using CyEnterCriticalSection() and CyExitCriticalSection() around sleep and deep sleep calls in my own project, as I didn't want ISRs firing within the logic code that called the power modes. It seems to work with those calls around it, so my guess would be that you didn't have a closing CyExitCriticalSection() call after waking up from low power mode. It would need to look something like this:
uint8 intrStatus = CyEnterCriticalSection();
CySysPmDeepSleep();
CyExitCriticalSection(intrstatus);
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's not my code but example :
*******************************************************************************
* Function Name: LowPowerImplementation()
********************************************************************************
* Summary:
* Implements low power in the project.
*
* Parameters:
* None
*
* Return:
* None
*
* Theory:
* The function tries to enter deep sleep as much as possible - whenever the
* BLE is idle and the UART transmission/reception is not happening. At all other
* times, the function tries to enter CPU sleep.
*
*******************************************************************************/
void LowPowerImplementation(void)
{
CYBLE_LP_MODE_T bleMode;
/* For advertising and connected states, implement deep sleep
* functionality to achieve low power in the system. For more details
* on the low power implementation, refer to the Low Power Application
* Note.
*/
if(LPM_Flag == TRUE)
{
if((CyBle_GetState() != CYBLE_STATE_ADVERTISING) ||(CyBle_GetState() != CYBLE_STATE_CONNECTED))
{
/* Request BLE subsystem to enter into Deep-Sleep mode between connection and advertising intervals */
bleMode = CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP);
/* Disable global interrupts */
// interruptStatus = CyEnterCriticalSection();
/* When BLE subsystem has been put into Deep-Sleep mode */
if(bleMode == CYBLE_BLESS_DEEPSLEEP)
{
Advertising_LED_Write(LED_OFF);
Warning_LED_Write(LED_OFF);
Connected_LED_Write(LED_OFF);
/* And it is still there or ECO is on */
if((CyBle_GetBleSsState() == CYBLE_BLESS_STATE_ECO_ON) ||
(CyBle_GetBleSsState() == CYBLE_BLESS_STATE_DEEPSLEEP))
{
CyBle_Stop();
/* Put the CPU into the Deep-Sleep mode when all debug information has been sent */
if((UartDeb_SpiUartGetTxBufferSize() + UartDeb_GET_TX_FIFO_SR_VALID) == 0u)
{
CySysPmDeepSleep();
}
else /* Put the CPU into Sleep mode and let SCB to continue sending debug data */
{
CySysPmSleep();
}
}
}
else /* When BLE subsystem has been put into Sleep mode or is active */
{
/* And hardware doesn't finish Tx/Rx opeation - put the CPU into Sleep mode */
if(CyBle_GetBleSsState() != CYBLE_BLESS_STATE_EVENT_CLOSE)
{
CySysPmSleep();
}
}
/* Enable global interrupt */
//CyExitCriticalSection(interruptStatus);
}
}
}
As you can see it's absolutely standard code that not wake up if I enable CyExitCriticalSection
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes, it looks pretty standard. Unless you need the CriticalSection during low-power, there is no real reason to do so. Interesting that it works for my own code then...
Is the CyBle_Stop(); line supposed to be there? Turning off the radio fully when entering deep sleep will cause the BLESS to stop running iirc. Perhaps that is the cause of the not waking up problem?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Got it! And I prefer to share a "lucky" case I met before: CapSense and LED control GPIOs use a same port. If CapSense interrupt and GPIO interrupt are not in same priority level, operation of the shared IO port may be interrupted on half way due to high priority isr....This can lead to CapSense stuck or unexpected LED blink..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
rzzh
Ah, yes. That would be a case to avoid
I generally try to abstract the hardware interactions into interfaces that are changed/operated in main code to prevent collisions like you are mentioning, and thus I wouldn't think of that case right away. It is a good idea to keep in mind what the interrupts are doing and their priority so that they behave nicely
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I placed 0 for seconds timer and 1 to all others. Also removed interruptStatus = CyEnterCriticalSection(); in LowPowerImplementation
and it work as need.