Back to main page: Leveraging TAG4 to better understand the WICED Smart Programming Environment

 

 

When using a microcontroller with a kernel, interrupts are the most fundamental way to interact with that kernel. In order for the push of a button to turn on an LED we must register that button as an interrupt, and toggle the LED within the interrupt_handler function that you will declare, define, and register as a callback with the kernel.

 

If all you wish to do is push a button that turns on the LED, there is very quick and easy way to register for interrupts on the WICED platform:

 

                Configure the push button in the GPIO configure definition.

 

              const BLE_PROFILE_GPIO_CFG interrupt_example_gpio_cfg = {

                  {GPIO_PIN_WP, GPIO_PIN_BUTTON, 13,

                    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},

 

                  {GPIO_SETTINGS_WP, GPIO_SETTINGS_BUTTON, GPIO_SETTINGS_LED,

                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}

              };

 

                Define, declare, and register the interrupt handler (handler must have a UINT8 parameter).

 

              bleprofile_regIntCb((BLEPROFILE_SINGLE_PARAM_CB)interrupt_handler);

 

                Toggle the LED within interrupt handler.

 

              void interrupt_handler(UINT8 gpio) {

                  bleprofile_LEDBlink  (50, 50, 3);   

                }

 

Interrupts, on the other hand, that are necessary for other, higher volume, higher speed/frequency applications require a different method of instantiation. There are a few more steps as well as more parameters to take into account. If you require interrupts for anything other than a single push button the following method is necessary to use:

         

  1. Define and declare your interrupt handler function.
  2. Configure interrupt mask.
  3. Register your interrupt handler using the mask.
  4. Configure the pin as an interrupt.

 

The interrupt handler must be defined and declared as a function that takes two parameters, one of which being an 8-bit integer, the other a pointer.

 

                            static void interrupt_handler (void* parameter, UINT8 arg);

 

The interrupt mask is an array of three 16 bit integers. The mask is passed as a parameter while registering for an interrupt in the following line of code. The three integers refer to the three ports of GPIOs. For the purpose of instantiating GPIO 4 as an interrupt, the

following mask would suffice:

 

                            UINT16 masks[3] = {(1 << 4), 0 , 0}; //replace 4 with GPIO number

 

But if you wished to access a GPIO outside of port 0, for instance pin 24, the mask would look like this:

 

              UINT16 masks2[3] = { 0, (1 << 8), 0};

              //port 1 starts at 16, 24 is 16+8, mask is set to 8

 

Below the mask we’ll register the interrupt handler function using the above mask as a parameter in order for the interrupt handler to be called on the appropriate GPIO interrupt.

 

              gpio_registerForInterrupt(masks, interrupt_handler, NULL);

 

In the above registration of the interrupt, when pin 4 receives an interrupt, the interrupt handler will be called and execute whatever code it contains.

 

But pin 4 doesn’t receive interrupts until its configured to. So, the final step is to configure it. The following code is worthy of copying and using for most interrupts. The third parameter can be changed to either rising edge or both edges.

 

              gpio_configurePin(0, 4, GPIO_EN_INT_RISING_EDGE, GPIO_PIN_OUTPUT_LOW);

 

The attached sample code implements the interrupt in the create function where you will see the last three steps executed sequentially.

 

              UINT16 masks[3] = {(1 << 4), 0 , 0};

              gpio_registerForInterrupt(masks, interrupt_handler, 0);

              gpio_configurePin(0, 4, GPIO_EN_INT_RISING_EDGE, GPIO_PIN_OUTPUT_LOW);

 

Now to complete our final project, all we must do is toggle the GPIO within the interrupt handler. The easiest way to do this is to call the following function (see API directory for detailed parameters):

 

              bleprofile_LEDBlink(50, 50, 3);

 

If using this API be sure that you properly configure your GPIO configuration array (as seen in prior posting of this project).

 

The attached sample firmware shows all these aspects put together, so, when loaded the LED flashes on every push of the button (sample firmware uses GPIO 0 not 4).

 

The second method is well suited for receiving interrupts from sensors or anything else attached to one of your serial busses. The interrupt pin from the sensor should be hardwired directly to the GPIO you wish to register as an interrupt (if the interrupt on the sensor is open-drain, pull it up with a 10K).

 

Registering for interrupts from sensors is another topic in itself which we will cover in a future blog posting. In summary, interrupts are a fundamental way of interacting with the kernel via push button and sensor interrupts.

 

Jacob W Torres

 

 

Back to main page: Leveraging TAG4 to better understand the WICED Smart Programming Environment