Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use gpio interrupt? #8

Closed
ly0 opened this issue Dec 15, 2014 · 9 comments
Closed

How to use gpio interrupt? #8

ly0 opened this issue Dec 15, 2014 · 9 comments

Comments

@ly0
Copy link

ly0 commented Dec 15, 2014

I haven't seen any API could do this.

@donnib
Copy link

donnib commented Dec 22, 2014

@ly0 have you found any info on this ? I am looking for the same info.

@ly0
Copy link
Author

ly0 commented Dec 22, 2014

@donnib refered to http://g-lab.ca/esp8266ex-gpio-registers/, maybe we need to handle the related registers directly. search 'INT' for more info on that page. But I haven't tried.

@espressif
Copy link
Collaborator

gpio driver has been upload, you can have a test.

@donnib
Copy link

donnib commented Dec 25, 2014

@espressif which driver are you reffering to ? 0.9.4 has GPIO interrupt supported ? If so any documentation about that ?

@ly0
Copy link
Author

ly0 commented Dec 25, 2014

@Karang
Copy link

Karang commented Dec 30, 2014

In the exemple you talked about a gpio_intr_ack function (https://github.com/espressif/esp_iot_rtos_sdk/blob/master/examples/driver_lib/driver/gpio.c#L101). But I can't find it anywhere. Even if I add the signature : void gpio_intr_ack(uint32 mask); the linker can't find it.

EDIT: I managed to compile by providing the address to the linker (PROVIDE ( gpio_intr_ack = 0x40004dcc );) But now I'm getting this exception when I trigger my interrupt :

Fatal exception (20): (EXCCAUSE_INSTR_PROHIBITED)
epc1=0x00000004
epc2=0x00000000
epc3=0x4024306f
epcvaddr=0x00000004
depc=0x00000000

Here is my code :

LOCAL void (*callbacks[16])(void);
LOCAL void interruptHandler(int gpio_mask) {
    for (int i=0 ; i<16 ; i++) {
        if ((0x1<<i) & gpio_mask) {
            if (callbacks[i] != NULL) {
                (*callbacks[i])();
            }
        }
    }
    gpio_intr_ack(gpio_mask);
}

And this is how i register the handler :

for (int i=0 ; i<16 ; i++) {
    callbacks[i] = NULL;
}
_xt_isr_attach(ETS_GPIO_INUM, (_xt_isr)interruptHandler);
_xt_isr_unmask(1<<ETS_GPIO_INUM);

EDIT2: It seems that the interrupt is given no arguments (gpio_mask is always 16, whatever the pin are). I tried to use gpio_intr_pending(); but it always return 0 and throw a 29 (EXCCAUSE_STORE_PROHIBITED) exception. It also seems that the interrupt is triggered a lot before crashing, shouldn't it be triggered once ?

EDIT3: I tried to use _xt_clear_ints(uint32 mask); and _xt_read_ints(); but I have the same issue, with _xt_read_ints(); returning a lot of 20 and some 84.

@Karang
Copy link

Karang commented Jan 2, 2015

Any idea ? This issue seems to be linked with the pwm one.

Edit: an answer has been found by hreintke on esp8266.com : http://www.esp8266.com/viewtopic.php?f=8&t=241&p=7246#p7246

@HomeACcessoryKid
Copy link

Now, 2 years later, is there an answer to this?
For now I cannot see any clear instructions in the SDK itself and the driver code seems incomplete.
For example, gpio.c contains the function gpio_config() but there is no prototype in gpio.h
The example given on espressif site depends on this function...

Is there a conclusive example how to do this??

@HomeACcessoryKid
Copy link

HomeACcessoryKid commented Jan 8, 2017

I propose to add this to the official distribution: it is backward compatible and it means people can have a 'one-stop-shop-experience' by just reading the gpio.h file.

//example based on ESP8266_RTOS_SDK version 1.5.0
#include "esp_common.h"
#include "gpio.h"

#define GPIO_INPUT(gpio_bits)       ((gpio_input_get()&gpio_bits)?1:0)
#define GPIO_INTERRUPT_ENABLE   _xt_isr_unmask(1 << ETS_GPIO_INUM)
void gpio_config(GPIO_ConfigTypeDef *pGPIOConfig);

/******************************************************************************
 * FunctionName : gpio_intr_handler - generic handling of GPIO interrupts
*******************************************************************************/
void (*gpio_intr_callbacks[16])(void);
void gpio_intr_handler() {
    int i;
    uint32 gpio_mask = _xt_read_ints();
    uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
    os_printf("interrupt@%dus: mask=0x%02x, status=0x%02x\n",system_get_time(),gpio_mask,gpio_status);
    for (i=0 ; i<16 ; i++)
        if ( (0x1<<i) & gpio_status & gpio_intr_callbacks[i]!= NULL )
            (*gpio_intr_callbacks[i])();   
    GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status );     //clear interrupt status
}

//****** THE ITEMS ABOVE SHOULD BE ADDED TO THE GPIO driver files ************//

/******************************************************************************
 * FunctionName : Pin0 specific interrupt handler
*******************************************************************************/
LOCAL void callback0() {
    static uint32  oldtime;
//  os_printf("oldtime: %d\n",oldtime);
    if ( (oldtime+200)<(oldtime=(system_get_time()/1000) ) ) {  //200ms debounce guard
        GPIO_OUTPUT(GPIO_Pin_2,GPIO_INPUT(GPIO_Pin_2)^1);       //toggle
        os_printf("Pin2-toggle\n");
    }
//  os_printf("newtime: %d\n",oldtime);
}

/******************************************************************************
 * FunctionName : user_init
*******************************************************************************/
void user_init(void)
{   
    GPIO_ConfigTypeDef gpio0_in_cfg;                            //Define GPIO Init Structures
    GPIO_ConfigTypeDef gpio2_in_cfg;

    gpio0_in_cfg.GPIO_IntrType = GPIO_PIN_INTR_NEGEDGE;         //Falling edge trigger
    gpio0_in_cfg.GPIO_Mode     = GPIO_Mode_Input;               //Input mode
    gpio0_in_cfg.GPIO_Pin      = GPIO_Pin_0;                    //Enable GPIO
    gpio_config(&gpio0_in_cfg);                                 //Initialization function
    gpio_intr_handler_register(gpio_intr_handler,NULL);         //Register the interrupt function
    GPIO_INTERRUPT_ENABLE;

    gpio_intr_callbacks[0]=callback0;                           //define the Pin0 callback

    gpio2_in_cfg.GPIO_IntrType = GPIO_PIN_INTR_DISABLE;         //no interrupt
    gpio2_in_cfg.GPIO_Mode     = GPIO_Mode_Output;              //Output mode
    gpio2_in_cfg.GPIO_Pullup   = GPIO_PullUp_EN;                //improves transitions
    gpio2_in_cfg.GPIO_Pin      = GPIO_Pin_2;                    //Enable GPIO
    gpio_config(&gpio2_in_cfg);                                 //Initialization function
}

/***********************************************************************************
 * FunctionName : user_rf_cal_sector_set forced upon us by espressif since RTOS1.4.2
***********************************************************************************/
uint32 user_rf_cal_sector_set(void) {
    extern char flashchip;
    SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4);
    //sec_num = chip_size / flash->sector_size; but sector size is 4096 = 2^12
    uint32_t sec_num = flash->chip_size >> 12;
    return sec_num - 5;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants