How to trigger an task on a GPIO output from a GPIO input event

Hi

I am trying to use the two GPIO pins. One GPIO pin is configured as a input and connected externally to a button.

The second is configured as an output pin. I want to press the button and trigger the second GPIO pin to output a low signal

The button press will trigger a hardware nRESET. see attached schematics

I use the PPI to connect them, not sure if this is the way to do it. Especially the TEP and EEP register values not sure about 

//Button pins interface init
    NRF_P1->PIN_CNF[6] = 0x0003000C;     //Nrf52 button GPIO input pin port P1.06, internal pull up
    NRF_GPIOTE->INTENCLR = 0x00000001;   //Disable interupts on CONFIG[0] pin
    NRF_GPIOTE->CONFIG[0] = 0x00022601;  //Set BUTTON press on port P1.06 as a GPIOTE EVENT to generate an interrupt event when going from HIGH to LOW.
    NRF_GPIOTE->EVENTS_IN[0] = 0;        // Clear any potential events that could have occured during configuration
    NRF_GPIOTE->INTENSET = 0x00000001;   //Enable interupts on CONFIG[0] pin

    //nRF52 APPCPU_SELF_nRESET
    NRF_P1->OUTSET = 0x00000400;        //Set APPCPU_SELF_nRESET GPIO output pin HIGH. 
    NRF_P1->PIN_CNF[10] = 0x0000000F;   //Nrf52 APPCPU_SELF_nRESET GPIO output pin port P1.10, internal pull up
    NRF_GPIOTE->INTENCLR = 0x00000002;  //Disable interupts on CONFIG[1] pin
    NRF_GPIOTE->CONFIG[1] = 0x00122A03; //Set GPIO output port P1.10 as a GPIOTE TASK (HIGH_to_LOW) to trigger on a event.
    NRF_GPIOTE->EVENTS_IN[1] = 0;       // Clear any potential events that could have occured during configuration
    NRF_GPIOTE->INTENSET = 0x00000002;  //Enable interupts on CONFIG[1] pin

    //PPI channel configuration 0 config. Makes nRF52 self reset trigger on button press
    NRF_PPI->CHENCLR = 0x00000001;  
    NRF_PPI->CH[0].EEP = 0x40006100;
    NRF_PPI->CH[0].TEP = 0x40006104;
    NRF_PPI->CHENSET = 0x00000001;

kr

Øystein

Parents
  • Hi Øystein,

    I'm not sure I like the idea of having a GPIO output connected directly to the reset line. Is it not sufficient to perform a soft reset from your code? Anyway, I took the liberty of updating your code to make it more readable, see below. The  TEP or EEP or endpoint address was wrong.

    #define BTN_INPUT   NRF_GPIO_PIN_MAP(1,6)
    #define RESET_SIG   NRF_GPIO_PIN_MAP(1,10)
    
    
    nrf_gpio_cfg_input(BTN_INPUT, NRF_GPIO_PIN_PULLUP);
    NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
                            (BTN_INPUT << GPIOTE_CONFIG_PSEL_Pos) |
                            (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos);
    
    NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
                            (RESET_SIG << GPIOTE_CONFIG_PSEL_Pos) |
                            (GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos) |
                            (GPIOTE_CONFIG_OUTINIT_High << GPIOTE_CONFIG_OUTINIT_Pos);
    
    NRF_PPI->CH[0].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[0];
    NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[1];
    NRF_PPI->CHENSET = 1;

    Best regards,

    Vidar

  • Hi Vidar

    I think you are correct, its uneccesary I think to use a GPIO and route it to the nRESET pin. It semmes like it has hostorically been designed that way for firmware upgrade over USB. USBDFU Trigger Lib need a GPIO that can control the physical "RESET pin

    I also encountered a problem with my design. The PPI channel TASK OUT do not release the PIN and set it HIGH, its kept  LOW so the  MCU freezes. It do not work. I also tried to set up a second PPI channel to trigger a LOW_TO_HIGH on the GPIO pin 1.10 when the nRESET signal goes  LOW. Not sure why, but did not work

    Anyway. as you point out, Is it not sufficient to perform a soft reset from your code. I think maybe I try that, but is there any code exapmles or guides on how I can trigger SOFT RESET triggered by a GPIO INTERRUPT event HIGH_TO_LOW on pin GPIO 1.6

    KR

    Øystein

  • Hi Øystein,

    Oystein said:
    I also encountered a problem with my design. The PPI channel TASK OUT do not release the PIN and set it HIGH, its kept  LOW so the  MCU freezes. It do not work. I also tried to set up a second PPI channel to trigger a LOW_TO_HIGH on the GPIO pin 1.10 when the nRESET signal goes  LOW. Not sure why, but did not work

    Are you testing with the output physically connected to the reset line? 

    Oystein said:
    Anyway. as you point out, Is it not sufficient to perform a soft reset from your code. I think maybe I try that, but is there any code exapmles or guides on how I can trigger SOFT RESET triggered by a GPIO INTERRUPT event HIGH_TO_LOW on pin GPIO 1.6

    You can write '0xB1' (BOOTLOADER_DFU_START) followed by NVIC_SystemReset() in your button ISR to reset into bootloader DFU mode as long as the bootloader is built with NRF_BL_DFU_ENTER_METHOD_GPREGRET

    Best regards,

    Vidar

  • Hi

    I dont have any bootloader but solved it like this. With this code i can choose wether to have a software reset or hardware reset

    //Button pins interface init
     NRF_P1->PIN_CNF[6] = 0x0000000C;     //Nrf52 button GPIO input pin port P1.06, internal pull up, STANDARD driveSENSE disabled
     NRF_GPIOTE->INTENCLR = 0x00000001;   //Disable interupts on CONFIG[0] pin
     NRF_GPIOTE->CONFIG[0] = 0x00122601;  //Set BUTTON press on port P1.06 as a GPIOTE EVENT to generate an interrupt event when going from HIGH to LOW.
     NRF_GPIOTE->EVENTS_IN[0] = 0;        // Clear any potential events that could have occured during configuration
     NRF_GPIOTE->INTENSET = 0x00000001;   //Enable EVENT interupts on UARTTE CONFIG[0] pin
    
     //nRF52 self RESET pin
     NRF_P1->OUTSET = 0x00000400;        //Set P1.10 GPIO output pin HIGH. 
     NRF_P1->PIN_CNF[10] = 0x0000000F;   //GPIO output pin port P1.10, internal pull up, STANDARD drive, SENSE disabled
    
     //Enable GPIOTE interrupt in NVIC
     NVIC_EnableIRQ(GPIOTE_IRQn);        // Enable GPIOTE interrupt in NVIC
    
    //GPIOTE Interrupt handler
    void GPIOTE_IRQHandler(void)
    {
        if (NRF_GPIOTE->EVENTS_IN[0])   // Check if event on channel 0 fired
        {
            NRF_GPIOTE->EVENTS_IN[0] = 0;  // Clear event
    
            //Use only soft or hard reset
            //NVIC_SystemReset();            // 🔥 Force system soft reset
            NRF_P1->OUTCLR = 0x00000400;     // 🔥 Force system hard reset
        }
    }

    I am not 100% sure if myt understanding of SOFT and HARD RESET is coreect, but anyway both NVIC_SYSTEMRESET() or setting the P.1.10 LOW both ways will reset the MCU

    kr

    Øystein

Reply
  • Hi

    I dont have any bootloader but solved it like this. With this code i can choose wether to have a software reset or hardware reset

    //Button pins interface init
     NRF_P1->PIN_CNF[6] = 0x0000000C;     //Nrf52 button GPIO input pin port P1.06, internal pull up, STANDARD driveSENSE disabled
     NRF_GPIOTE->INTENCLR = 0x00000001;   //Disable interupts on CONFIG[0] pin
     NRF_GPIOTE->CONFIG[0] = 0x00122601;  //Set BUTTON press on port P1.06 as a GPIOTE EVENT to generate an interrupt event when going from HIGH to LOW.
     NRF_GPIOTE->EVENTS_IN[0] = 0;        // Clear any potential events that could have occured during configuration
     NRF_GPIOTE->INTENSET = 0x00000001;   //Enable EVENT interupts on UARTTE CONFIG[0] pin
    
     //nRF52 self RESET pin
     NRF_P1->OUTSET = 0x00000400;        //Set P1.10 GPIO output pin HIGH. 
     NRF_P1->PIN_CNF[10] = 0x0000000F;   //GPIO output pin port P1.10, internal pull up, STANDARD drive, SENSE disabled
    
     //Enable GPIOTE interrupt in NVIC
     NVIC_EnableIRQ(GPIOTE_IRQn);        // Enable GPIOTE interrupt in NVIC
    
    //GPIOTE Interrupt handler
    void GPIOTE_IRQHandler(void)
    {
        if (NRF_GPIOTE->EVENTS_IN[0])   // Check if event on channel 0 fired
        {
            NRF_GPIOTE->EVENTS_IN[0] = 0;  // Clear event
    
            //Use only soft or hard reset
            //NVIC_SystemReset();            // 🔥 Force system soft reset
            NRF_P1->OUTCLR = 0x00000400;     // 🔥 Force system hard reset
        }
    }

    I am not 100% sure if myt understanding of SOFT and HARD RESET is coreect, but anyway both NVIC_SYSTEMRESET() or setting the P.1.10 LOW both ways will reset the MCU

    kr

    Øystein

Children
No Data
Related