Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

PSoC™ 4

urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

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 ? Capture.JPG

0 Likes
1 Solution
RyanZhao
Moderator
Moderator First comment on KBA 500 replies posted 250 solutions authored
Moderator

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

View solution in original post

16 Replies
odissey1
Level 9
First comment on KBA 1000 replies posted 750 replies posted
Level 9

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

0 Likes
urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

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 ?

0 Likes
Anonymous
Not applicable

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.

0 Likes
urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

Problem solved by changing interrupt priority.

urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

but not final. Now I connected BLE and again it's stopped

I have 5 interrupts

Capture.JPG

1. for BLE

2. wakeup from sleep

3. received byte from RX

4. timer of seconds

5. sensor

What a rules for priorities ?

0 Likes
RyanZhao
Moderator
Moderator First comment on KBA 500 replies posted 250 solutions authored
Moderator

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

Bob_Marlowe
Level 10
50 questions asked 10 questions asked 1000 solutions authored
Level 10

@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

RyanZhao
Moderator
Moderator First comment on KBA 500 replies posted 250 solutions authored
Moderator

@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

0 Likes
Anonymous
Not applicable

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.

chaplin.u_1533771

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.

0 Likes
urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

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.

0 Likes
Anonymous
Not applicable

@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);

0 Likes
urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

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

0 Likes
Anonymous
Not applicable

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?

0 Likes
RyanZhao
Moderator
Moderator First comment on KBA 500 replies posted 250 solutions authored
Moderator

e.pratt_1639216

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..

0 Likes
Anonymous
Not applicable

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

0 Likes
urchc_1533771
Level 5
5 likes given First like received First like given
Level 5

I placed 0 for seconds timer and 1 to all others. Also removed interruptStatus = CyEnterCriticalSection(); in LowPowerImplementation

and it work as need.

0 Likes