- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am trying to simply configure P2 as an external. rising edge interrupt. I currently have it connected to a simple switch that transitions from high to low. I have verified that my port mapping is correct by a simple debug loop that outputs traces on the HCI_UART to indicate the state of the pin. When I run this loop in create(), the correct input state is read via gpio_getPinInput(), this verifies that I have the right pin, and the change in state can be detected.
I have read the following:
How to Write WICED Smart Applications
--> Followed the example code int he GPIO section - can't get my ISR to run
Re: Wiced Smart Software Runtime -- Lots of Questions
--> As this thread suggested, I tried registering my interrupt callback (ISR) before the bleprofile_Init() call in create(), did not work
--> This has some interesting points about interrupt priority and such but nothing I can see that can explain what's happening.
Re: how to identify GPIO interrupt source pin?
--> Again, interesting, and this post makes it seem doable, but again, this did not help solve my problem
What I tried, was to check the state of that pin, P2 (PORT 0, PIN 2), using gpio_getPinInput() in the 1 second timer tick. In that function, regardless the state of my switch controlling the logic level on that pin, the pin is reported as low. This suggests that perhaps the input is not coming through when I want it to?
I have a trace debug statement in my ISR that would tell me when it is called, and it is NEVER called, regardless how many times I flip the switch. My code is below, I'm sure I'm doing something wrong, just can't seem to figure out what it is since all the docs and threads make this sound so easy but I can't get it to work at all.
// dump the database to debug uart.
legattdb_dumpDb();
// As per some readings online, it is recommended that you register your interrupt handlers before you call bleprofile_Init()
UINT16 interrupt_handler_mask[3] = {0, 0, 0};
interrupt_handler_mask[IRQ_PORT] |= (1 << IRQ_PIN); //IRQ_PORT = 0, IRQ_PIN=2
// Now register the interrupt handler.
gpio_registerForInterrupt(interrupt_handler_mask, application_gpio_interrupt_handler, NULL);
gpio_configurePin(AMS3911_IRQ_PORT, IRQ_PIN,GPIO_INPUT_ENABLE|GPIO_PULL_DOWN|GPIO_EN_INT_RISING_EDGE,GPIO_PIN_OUTPUT_LOW);
// Clear out any spurious interrupt status..
gpio_clearPinInterruptStatus(IRQ_PORT, IRQ_PIN);
bleprofile_Init(bleprofile_p_cfg);
bleprofile_GPIOInit(bleprofile_gpio_p_cfg);
// Initialized ROM code which will monitor the battery
blebat_Init();
...
....
....
void application_gpio_interrupt_handler(void *parameter, UINT8 data)
{
ble_trace0("******** Interrupt Detected*******\n");
UINT8 iregs[3] = {0,0,0};
u32 irqStatus;
BYTE gpio_level = gpio_getPinInput(IRQ_PORT, IRQ_PIN);
do
{
cfa_kickWatchdog();
//DO STUFF TO READ REGISTERS OF A SPI CONNECTED PERIPHERAL
gpio_level = gpio_getPinInput(IRQ_PORT, IRQ_PIN);
} while(gpio_level); /* PIC24 irq is edge triggered, sometimes there is no edge but still an interrupt */
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Everyone,
So, I figured it out: It turned out I had a gpio_init() call in some function that was called to set up the SPI communication. Calling gpio_init() causes all the GPIO settings to reset, so once I scoured the code for this call and removed it, it started to work! I guess this function is not really meant to be called by the developer.
BAD gpio_init()! BAD!
It turned out that I was initializing my SPI communication after my IRQ setup, and since hat SPI initializaition called gpio_init(), that negated all my config. It was in a library function deeper in the project so it was not obvious, but it now works!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi dshalaby, I will get back to you very soon, I am looking into this right now.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello dshalaby,
1. Examine the I2C_temperature sensor App in the SDK.
2. LM73 Sensor Code should explain this.
Thanks
JT
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This is the sample code that we are using for our Mpresssion/Odyssey platform. We have an interruption set for P4 between the BCM20737S and a uC. The interruption is activated on falling edge (see example below: GPIO_EN_INT_FALLING_EDGE). Our P4 is pulled down by a resistor and the uC will force a state HIGH followed by LOW.
The defines are:
#define GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT | 0 |
#define GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN | 4 |
I put in bold the important pieces of code to enable an interruption on a specific pin.
void gpio_config_efm32_interrupt()
{
//Declare the three ports even if we are only using one!
UINT16 interrupt_handler_mask[3] = {0,0,0};
DBG_PRINT_GPIO("gpio_config_efm32_interrupt> start...\n");
//Setup the interruption line for P4, the Port is 0 (4/16) and the Pin is 4 (4%16)
gpio_configurePin(GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT, GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN,
GPIO_INPUT_ENABLE | GPIO_EN_INT_FALLING_EDGE, GPIO_PIN_OUTPUT_LOW);
//Set the mask for the specific PORT of interest (PORT 0 in our case!)
interrupt_handler_mask[GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT] |=
(1<< GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN);
gpio_registerForInterrupt(interrupt_handler_mask, gpio_efm32_interrupt_routine, (void*)NULL);
// Clear out any spurious interrupt status. (not sure it is needed, I saw it in the sample code
//from Broadcom, may not be needed). Also when an interrupt happens there is no need to call this
//function, the Broadcom stack does it for us!
gpio_clearPinInterruptStatus(GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT,
GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN);
DBG_PRINT_GPIO("gpio_config_efm32_interrupt> end...\n");
}
void gpio_efm32_interrupt_routine(void* parameter, UINT8 arg)
{
//do something during the interrupt.
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In our case APPLICATION_INIT() would call bleapp_set_cfg(xx,xx,xx,xx, xx, main_client). As soon as APPLICATION_INIT() returns we execute main_client and this is where we set the interruption posted above.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the interruption routine I would do the minimum for now, just print ble_trace0("******** Interrupt Detected*******\n");
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok thank you very much. Not sure how this code differs from what I am doing, can you please highlight what, if any, code that I am missing that is in your example? From what I can see, we're both doing the same thing in our code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you try to call the initialization of the interrupt in your "main" function?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, thanks again for your help. I can call the ISR manually, and it does run at that point, that said, the GPIO level is always read as low, regardless the actual state of that pin.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have tried adjusting the BLE_PROFILE_GPIO_CFG to apply some interrupt settings (as defined in bleprofile.h, GPIO flag bits), to "pin" 2, as defined in platform.h, which suggests that in the context of hte _GPIO_CFG, "pin" means the number suffixed to the pin label "PXX", rather than the way pin is defined in the H/W user manual, where PORT = <PORT NUM>/16, PIN = <PORT_NUM> % 16.
Firstly, can someone confirm my understanding here that pin is defined differently when setting up your BLE_PROFILE_GPIO_CFG than when setting up gpio with the gpiodriver.h?
Secondly, if my understanding is correct, is there something wrong with my config (settings in BOLD are what I applied😞
const BLE_PROFILE_GPIO_CFG genoav1_0_gpio_cfg =
{
{
GPIO_PIN_WP, // This need to be used to enable/disable NVRAM write protect
GPIO_PIN_BUTTON, GPIO_PIN_LED, GPIO_PIN_BUZZER, 2, // try to enable the IRQ line on P2
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // Other GPIOs are not used
},
/*.gpio_flag =*/
{
GPIO_SETTINGS_WP,
GPIO_SETTINGS_BUTTON, GPIO_SETTINGS_LED, GPIO_SETTINGS_BUZZER, GPIO_INT,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}
};
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
P2 refers to GPIO P2 (physical pin 22). If you need to find the port associated to P2 you will do 2/16 = 0 --> PORT0. You can use the definition that you have to enable the GPIO that's an option. You need to make sure that you pass the address of the structure called genoav1_0_gpio_cfg to bleapp_set_cfg() in APPLICATION_INIT.
The code that you put together yesterday looks good. Can you try to disable the pull down from the GPIO? and try again. If this is not working we can try the same code on the Tag3 board. We can setup an interruption on P0 and fire the interruption via the application button on the board.
I am still no convinced that you do your initialization in the "main" function the one called right after APPLICATION_INIT returns, could you please confirm?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi 79rpm,
Okay so I am doing my initialization of these IRQs in a function called genoav1_0_create() which is called after APPLICATION_INIT(). The initialization is:
UINT16 interrupt_handler_mask[3] = {0, 0, 0};
interrupt_handler_mask[IRQ_PORT] |= (1 << IRQ_PIN);
// Now register the interrupt handler.
gpio_registerForInterrupt(interrupt_handler_mask, application_gpio_interrupt_handler, NULL);
gpio_configurePin(IRQ_PORT,IRQ_PIN,GPIO_INPUT_ENABLE|GPIO_EN_INT_RISING_EDGE,GPIO_PIN_OUTPUT_LOW);
// Clear out any spurious interrupt status..
gpio_clearPinInterruptStatus(IRQ_PORT,IRQ_PIN);
I have tried setting the GPIO_PULL_UP and GPIO_PULL_DOWN that made no difference.
I have tried calling gpio_ConfigurePin() before gpio_registerForInterrupt() and vice versa, no difference.
I have tried playing with the BLE_PROFILE_GPIO_CFG , no difference
I have tried changing my #define statements for PORT and PIN to use parenthesis, (2) rather than 2. No difference
Also, I have loaded the i2c_temerature_sensor example, and that one does fire the ISR correctly when I toggle P4, and when I simply change the LM73_ALERT_INTERRUPT_PIN to (2), and apply my external toggle switch, it does run the ISR. So this confirms that it's not a hardware config issue, but that it's a config thing.
Also, now the loop that once correctly detected the state of that pin no longer works, it just reports the pin is low no matter what, so something is wrong.
Any additional support would be greatly appreciated.
Thanks in advance
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Everyone,
So, I figured it out: It turned out I had a gpio_init() call in some function that was called to set up the SPI communication. Calling gpio_init() causes all the GPIO settings to reset, so once I scoured the code for this call and removed it, it started to work! I guess this function is not really meant to be called by the developer.
BAD gpio_init()! BAD!
It turned out that I was initializing my SPI communication after my IRQ setup, and since hat SPI initializaition called gpio_init(), that negated all my config. It was in a library function deeper in the project so it was not obvious, but it now works!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for sharing the solution with everyone!