蓝牙BLE---DA14683的GPIO中断按键源码

版权声明:转载请注明出处。技术交流加微信:life5270 https://blog.csdn.net/JaLLs/article/details/84579192

ad_gpio_intr.h 

/**
 * \addtogroup BSP
 * \{
 * \addtogroup ADAPTERS
 * \{
 * \addtogroup GPIO_INTR
 * \{
 */

/**
 *****************************************************************************************
 *
 * @file ad_gpio_intr.h
 *
 * @brief WKUP adapter API
 *
 * Copyright (C) 2015. Dialog Semiconductor Ltd, unpublished work. This computer
 * program includes Confidential, Proprietary Information and is a Trade Secret of
 * Dialog Semiconductor Ltd. All use, disclosure, and/or reproduction is prohibited
 * unless authorized in writing. All Rights Reserved.
 *
 * <[email protected]> and contributors.
 *
 *****************************************************************************************
 */

#ifndef AD_GPIO_INTR_H_
#define AD_GPIO_INTR_H_

#include <hw_gpio.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * \brief Device gpio pointer, handle to use with ad_gpio_intr_register(), ad_gpio_intr_unregister() etc.
 *
 */
#ifndef AD_GPIO_INTR_INSTANCE
/**
 * \brief Entry for gpio interrupt
 *
 * \param [in] _name name that will be later used to refer to instance
 * \param [in] _port port id of triggering pin
 * \param [in] _pin pin id of triggering pin
 * \param [in] _press_callback function to be called when interrupt occurs
 * \param [in] _release_callback function to be called when interrupt occurs
 *
 */
#define AD_GPIO_INTR_INSTANCE(_name, _port, _pin, _press_callback, _release_callback) \
        INITIALISED_PRIVILEGED_DATA ad_gpio_intr_config dev_##_name = { \
                .port = _port, \
                .pin = _pin, \
                .pressed = false, \
                .press_cb = _press_callback, \
                .release_cb = _release_callback, \
                .next_element = NULL, \
        }; \
        INITIALISED_PRIVILEGED_DATA ad_gpio_intr_config *_name = &dev_##_name;
#endif

/**
 * \brief Definition of callback function
 */
typedef void (*ad_gpio_intr_cb)(void);

/**
 * \brief Definition of the structure of gpio interrupt instance
 */
typedef struct ad_gpio_intr_config {
        HW_GPIO_PORT port;
        HW_GPIO_PIN pin;
        bool pressed;
        ad_gpio_intr_cb press_cb;
        ad_gpio_intr_cb release_cb;
        struct ad_gpio_intr_config *next_element;
} ad_gpio_intr_config;

/**
 * \brief Initialize adapter environment
  */
void ad_gpio_intr_init(void);

/**
 * \brief Register instance and if necessary setup wkup driver
 *
 * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro)
 */
void ad_gpio_intr_register(ad_gpio_intr_config *cfg);

/**
 * \brief Unregister instance
 *
 * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro)
 */
void ad_gpio_intr_unregister(ad_gpio_intr_config *cfg);

/**
 * \brief Check if instance has been registered
 *
 * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro)
 *
 * \return true if instance has been registered, false otherwise
 */
bool ad_gpio_intr_check_registered(ad_gpio_intr_config *cfg);

/**
 * \brief Check if interrupt has been handled by checking the level of the specific irq line
 *
 * \param [in] cfg handle of the instance (the _name field of AD_GPIO_INTR_INSTANCE macro)
 *
 * \return true if instance has been handled, false otherwise
 */
bool ad_gpio_irq_handled(ad_gpio_intr_config *cfg);

#ifdef __cplusplus
extern }
#endif

#endif /* AD_GPIO_INTR_H_ */

/**
 * \}
 * \}
 * \}
 */

ad_gpio_intr.c

/**
 * \addtogroup BSP
 * \{
 * \addtogroup ADAPTERS
 * \{
 * \addtogroup GPIO_INTR
 * \{
 */

/**
 *****************************************************************************************
 *
 * @file ad_gpio_intr.c
 *
 * @brief WKUP adapter implementation
 *
 * Copyright (C) 2015. Dialog Semiconductor Ltd, unpublished work. This computer
 * program includes Confidential, Proprietary Information and is a Trade Secret of
 * Dialog Semiconductor Ltd. All use, disclosure, and/or reproduction is prohibited
 * unless authorized in writing. All Rights Reserved.
 *
 * <[email protected]> and contributors.
 *
 *****************************************************************************************
 */
#if dg_configUSE_HW_KEYBOARD_SCANNER
#include <stdint.h>
#include "sdk_defs.h"
#include "interrupts.h"
#include <sys_power_mgr.h>
#include <ad_gpio_intr.h>
#include <assert.h>
#include <stdarg.h>
#include <platform_devices.h>
#include <hw_wkup.h>
#include "hw_keyboard_scanner.h"
#include "hw_cpm.h"

/*
 * \brief Definitions
 */
#define BUFFER_SIZE     16      //size must be a base-2 number
#define WKUP_INT_PRIO   1

/*
 * \brief Forward function declarations
 */
static int ad_kbscn_msg_cb(void);
static int ad_kbscn_fifo_over_cb(void);
static void ad_wkup_cb(void);
static void ad_gpio_intr_wake_up_ind(bool value);

static bool ad_gpio_intr_prepare_for_sleep(void);
static void ad_gpio_intr_sleep_cancel(void);
static void ad_gpio_intr_xtal16m_ready_ind(void);
/*
 * \brief Global variables
 */
struct ad_gpio_intr_env_t {
        OS_MUTEX ad_gpio_intr_mutex;
        ad_gpio_intr_config *head_config;
};

const adapter_call_backs_t ad_gpio_intr_pm_call_backs = {
        .ad_prepare_for_sleep = ad_gpio_intr_prepare_for_sleep,
        .ad_sleep_canceled = ad_gpio_intr_sleep_cancel,
        .ad_wake_up_ind = ad_gpio_intr_wake_up_ind,
        .ad_xtal16m_ready_ind = ad_gpio_intr_xtal16m_ready_ind,
        .ad_sleep_preparation_time = 0,
};

INITIALISED_PRIVILEGED_DATA static wkup_config ad_gpio_intr_wkup_cfg = {
        .debounce = 0,
#if (dg_configBLACK_ORCA_IC_REV ==  BLACK_ORCA_IC_REV_A)
        .threshold = 1,
#endif
};

INITIALISED_PRIVILEGED_DATA static uint8_t columns[] = {
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
        UNUSED_INDEX,
};

INITIALISED_PRIVILEGED_DATA static uint8_t rows[] = {
        UNUSED_INDEX,
};

PRIVILEGED_DATA static  struct kbscn_msg_tag msg_buf[BUFFER_SIZE];

INITIALISED_PRIVILEGED_DATA struct kbscn_init_tag ad_gpio_intr_kbscn_init_env = {
        .columns                = columns,
        .rows                   = rows,
        .num_columns            = sizeof(columns),
        .num_rows               = sizeof(rows),
        .row_scan_active_time   = 1,                    // 1 + 1w + 1z = 3 cycles x (div/16 usec) = 3 usec => scan cycle = 1 * 3 = 3 usec
        .debounce_press_time    = 5,                    // 5 * scan cycle = 15 usec
        .debounce_release_time  = 5,                    // 5 * scan cycle = 15 usec
        .inactive_time          = 0,
        .clock_div              = KBSCN_PCLK_DIV16,     // 16MHz / div = 1MHz
        .inactivity_cb          = NULL,
        .fifo_under_cb          = NULL,
        .fifo_over_cb           = ad_kbscn_fifo_over_cb,
        .msg_cb                 = ad_kbscn_msg_cb,
        .msg_buf                = msg_buf,
        .msg_buf_sz             = BUFFER_SIZE,
        .msg_evt                = true,
        .inactive_evt           = false,
        .fifo_evt               = true,
};

PRIVILEGED_DATA static uint32_t msg_wr_idx = 0, msg_rd_idx = 0;

PRIVILEGED_DATA static struct ad_gpio_intr_env_t ad_gpio_intr_env;

/*
 * \brief Functions
 */
void ad_gpio_intr_init(void)
{
        if (ad_gpio_intr_env.ad_gpio_intr_mutex == NULL)
        {
                OS_MUTEX_CREATE(ad_gpio_intr_env.ad_gpio_intr_mutex);
                OS_ASSERT(ad_gpio_intr_env.ad_gpio_intr_mutex);

                pm_register_adapter(&ad_gpio_intr_pm_call_backs);

                hw_wkup_init(NULL);
                hw_wkup_set_debounce_time(ad_gpio_intr_wkup_cfg.debounce);
#if 0//(dg_configBLACK_ORCA_IC_REV ==  BLACK_ORCA_IC_REV_A)
                hw_wkup_set_counter_threshold(ad_gpio_intr_wkup_cfg.threshold);
                hw_wkup_reset_counter();
#endif
        }
}


void ad_gpio_intr_register(ad_gpio_intr_config *cfg)
{
        int i;
        ad_gpio_intr_config *cfg_ptr;
        if (!cfg) {
                return;
        }

        OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER);

        cfg_ptr = ad_gpio_intr_env.head_config;
        if (!ad_gpio_intr_env.head_config){
                ad_gpio_intr_env.head_config = cfg;
                hw_wkup_register_interrupt(ad_wkup_cb, WKUP_INT_PRIO);
        } else {
                while (cfg_ptr) {
                        ///Check if already added
                        if (cfg_ptr == cfg)
                                break;
                        ///Add it if not in the list
                        if (cfg_ptr->next_element == NULL){
                                cfg_ptr->next_element = cfg;
                                break;
                        }
                        cfg_ptr = cfg_ptr->next_element;
                }
        }

        for (i = 0; i < sizeof(columns); i++) {
                HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4));
                HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i])));
                if((cfg->port == port) && (cfg->pin == pin))
                        break;
        }
        if (i == sizeof(columns)) {
                for (i = 0; i < sizeof(columns); i++) {
                        if (columns[i] == UNUSED_INDEX) {
                                columns[i] = CONV_PORT_PIN_TO_INDEX(
                                        ((0x0F & cfg->port) << 4) | (0x0F & cfg->pin));
                                break;
                        }
                }
        }
        OS_ASSERT(i < sizeof(columns)); //No available slot in columns array

        OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex);

        hw_wkup_freeze();
        if (hw_kbscn_get_status())
                hw_kbscn_disable();
        hw_kbscn_init(&ad_gpio_intr_kbscn_init_env, &msg_wr_idx, &msg_rd_idx);
        hw_wkup_configure_pin(cfg->port, cfg->pin, true, HW_WKUP_PIN_STATE_LOW);
        hw_kbscn_enable();
        hw_wkup_unfreeze();
        hw_kbscn_activate_msg_evt();
}

void ad_gpio_intr_unregister(ad_gpio_intr_config *cfg)
{
        int i;
        bool remove = true;
        ad_gpio_intr_config *cfg_ptr;
        if (!cfg) {
                return;
        }

        for (i = 0; i < sizeof(columns); i++) {
                HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4));
                HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[i])));
                if ((cfg->port == port) && (cfg->pin == pin))
                        break;
        }

        if (i == sizeof(columns))
                return;

        OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER);

        cfg_ptr = ad_gpio_intr_env.head_config;

        if(ad_gpio_intr_env.head_config == cfg){
                ad_gpio_intr_env.head_config = NULL;
                hw_wkup_unregister_interrupt();
        } else {
                while (cfg_ptr) {
                        if (cfg_ptr->next_element == cfg) {
                                cfg_ptr->next_element = cfg->next_element;
                        } else if((cfg_ptr->port == cfg->port) && (cfg_ptr->pin == cfg->pin)) {
                                remove = false;
                                break;
                        }
                        cfg_ptr = cfg_ptr->next_element;
                }
        }

        if (remove)
                columns[i] = UNUSED_INDEX;

        OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex);

        hw_wkup_configure_pin(cfg->port, cfg->pin, false, 0);
}

bool ad_gpio_intr_check_registered(ad_gpio_intr_config *cfg)
{
        bool ret = false;
        ad_gpio_intr_config *cfg_ptr;

        if (!cfg) {
                return ret;
        }

        OS_MUTEX_GET(ad_gpio_intr_env.ad_gpio_intr_mutex, OS_MUTEX_FOREVER);

        cfg_ptr = ad_gpio_intr_env.head_config;

        while (cfg_ptr) {
                if (cfg_ptr == cfg) {
                        ret = true;
                        break;
                }
                cfg_ptr = cfg_ptr->next_element;
        }

        OS_MUTEX_PUT(ad_gpio_intr_env.ad_gpio_intr_mutex);

        return ret;
}

bool ad_gpio_irq_handled(ad_gpio_intr_config *cfg)
{
        volatile ad_gpio_intr_config *cfg_gbl = cfg;
        bool status, ret = true;

        cfg_gbl->pressed = false;
        hw_cpm_delay_usec(200);
        status = hw_gpio_get_pin_status(cfg->port, cfg->pin);
        if(!cfg_gbl->pressed){
                cfg_gbl->pressed = !status;
                ret = status;
        }

        return ret;
}

static void ad_wkup_cb(void)
{
        hw_wkup_reset_interrupt();
        hw_wkup_freeze();
}

static void ad_kbscn_msg_consume(void)
{
        struct kbscn_msg_tag *p_msg;
        ad_gpio_intr_config *cfg_ptr;

        while (msg_rd_idx != msg_wr_idx) {
                p_msg = &msg_buf[msg_rd_idx];

                if (!(p_msg->flags & LAST_MSG)) {
                        HW_GPIO_PORT port = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[p_msg->column]) >> 4));
                        HW_GPIO_PIN pin = (0xF & (CONV_INDEX_TO_PORT_PIN(columns[p_msg->column])));
                        OS_ASSERT(p_msg->row == 0);
                        if (p_msg->flags & PRESSED) {
                                cfg_ptr = ad_gpio_intr_env.head_config;
                                while (cfg_ptr) {
                                        if ((cfg_ptr->port == port) && (cfg_ptr->pin == pin) && !cfg_ptr->pressed) {
                                                cfg_ptr->pressed = true;
                                                if (cfg_ptr->press_cb) {
                                                        cfg_ptr->press_cb();
                                                }
                                        }
                                        cfg_ptr = cfg_ptr->next_element;
                                }
                        }
                        if (!p_msg->flags) {
                                cfg_ptr = ad_gpio_intr_env.head_config;
                                while (cfg_ptr) {
                                        if ((cfg_ptr->port == port) && (cfg_ptr->pin == pin) && cfg_ptr->pressed) {
                                                cfg_ptr->pressed = false;
                                                if (cfg_ptr->release_cb) {
                                                        cfg_ptr->release_cb();
                                                }
                                        }
                                        cfg_ptr = cfg_ptr->next_element;
                                }
                        }
                }

                msg_rd_idx++;
                msg_rd_idx &= (BUFFER_SIZE - 1); // fast modulo operation
        }
}

static int ad_kbscn_msg_cb(void)
{
        ad_kbscn_msg_consume();
        /* Re-enable fifo irq in case of buffer overflow */
        hw_kbscn_activate_msg_evt();
        return 0;
}

static int ad_kbscn_fifo_over_cb(void)
{
        hw_kbscn_disable();
        hw_kbscn_reset_fifo();

        /* Consume any events in buffer */
        ad_kbscn_msg_consume();

        /* Reset buffer */
        msg_wr_idx = 0;
        msg_rd_idx = 0;

        hw_kbscn_enable();
        hw_kbscn_activate_msg_evt();

        return 0;
}

static void ad_gpio_intr_wake_up_ind(bool value)
{
        hw_kbscn_init(&ad_gpio_intr_kbscn_init_env, &msg_wr_idx, &msg_rd_idx);
        hw_kbscn_enable();
        hw_kbscn_activate_msg_evt();
}

static void ad_gpio_intr_sleep_cancel(void)
{
        hw_wkup_freeze();
}

static void ad_gpio_intr_xtal16m_ready_ind(void) {
        /* nothing to do */
}

static bool ad_gpio_intr_prepare_for_sleep(void)
{
        ad_gpio_intr_config *cfg_ptr;

        for (int i = 0; i < sizeof(columns); i++) {
                HW_GPIO_PORT port;
                HW_GPIO_PIN pin;
                if (columns[i] == UNUSED_INDEX)
                        continue;
                port = 0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]) >> 4);
                pin = 0xF & (CONV_INDEX_TO_PORT_PIN(columns[i]));
                if (!hw_gpio_get_pin_status(port, pin)){
                        return false;
                }
        }
        cfg_ptr = ad_gpio_intr_env.head_config;
        while (cfg_ptr) {
                if (cfg_ptr->pressed) {
                        return false;
                }
                cfg_ptr = cfg_ptr->next_element;
        }

        hw_wkup_unfreeze();
        return true;
}
#endif
/**
 * \}
 * \}
 * \}
 */

gpio_key.h

/**
 ****************************************************************************************
 *
 * @file demo_hw.h
 *
 * @brief Code related to mesh reference design hardware
 *
 * Copyright (C) 2016-2018 Dialog Semiconductor.
 * This computer program includes Confidential, Proprietary Information  
 * of Dialog Semiconductor. All Rights Reserved.
 *
 ****************************************************************************************
 */

#ifndef DEMO_HW_H_
#define DEMO_HW_H_

#include <stdint.h>
#include "osal.h"

/**
 * Initialize peripherals needed for demo
 * These are initialized only once
 */
void hw_init(void);

/**
 * Configure peripherals needed for demo
 * These need to be reinitialized after sleep exit
 */
void hw_configure(void);

/**
 * Trigger hardware reset
 */
void hw_trigger_reboot(void);

#endif /* DEMO_HW_H_ */

 gpio_key.c

/**
 ****************************************************************************************
 *
 * @file demo_hw.c
 *
 * @brief Code related to mesh reference design hardware
 *
 * Copyright (C) 2016-2018 Dialog Semiconductor.
 * This computer program includes Confidential, Proprietary Information  
 * of Dialog Semiconductor. All Rights Reserved.
 *
 ****************************************************************************************
 */

#include <stdio.h>
#include <string.h>
#include "hw_led.h"
#include "hw_breath.h"
#include "hw_gpio.h"
#include "hw_wkup.h"
#include "hw_watchdog.h"
#include "hw_timer2.h"
#include "sys_power_mgr.h"
#include "hw_cpm.h"
#include "ad_gpio_intr.h"
#include "ad_spi.h"
#include "sys_rtc.h"
#include "platform_devices.h"
#include "gpio_key.h"
//#include "appl_support.h"

#       define CFG_GPIO_MB_BUTTON_SW1_PORT       (HW_GPIO_PORT_3)
#       define CFG_GPIO_MB_BUTTON_SW1_PIN        (HW_GPIO_PIN_1)

#       define CFG_GPIO_MB_BUTTON_SW2_PORT       (HW_GPIO_PORT_3)
#       define CFG_GPIO_MB_BUTTON_SW2_PIN        (HW_GPIO_PIN_2)


//uint64_t mytime = 0;
static void k1_button_pressed(void);
static void k1_button_released(void);
//Create GPIO interrupt instance for K1 button
static AD_GPIO_INTR_INSTANCE(K1_BUTTON, CFG_GPIO_MB_BUTTON_SW1_PORT, CFG_GPIO_MB_BUTTON_SW1_PIN,
                             k1_button_pressed, k1_button_released);

static void k2_button_pressed(void);
static void k2_button_released(void);
//Create GPIO interrupt instance for K1 button
static AD_GPIO_INTR_INSTANCE(K2_BUTTON, CFG_GPIO_MB_BUTTON_SW2_PORT, CFG_GPIO_MB_BUTTON_SW2_PIN,
                             k2_button_pressed, k2_button_released);


static void k2_button_pressed(void)
{
        printf("k2_button_pressed\r\n");
}

static void k2_button_released(void)
{
        printf("k2_button_released\r\n");
}

static void k1_button_pressed(void)
{
    printf("k1_button_pressed \r\n");
    //mytime = rtc_get_fromISR();
}

static void k1_button_released(void) {
  //  if ((rtc_get_fromISR() - mytime) > 100000)
    {
        printf("k1_button_released \r\n");
    }
}

void hw_configure(void)
{
        /* Configure Pushbutton K1 */
        hw_gpio_configure_pin(CFG_GPIO_MB_BUTTON_SW1_PORT, CFG_GPIO_MB_BUTTON_SW1_PIN,
               HW_GPIO_MODE_INPUT_PULLUP, HW_GPIO_FUNC_GPIO, true);

        hw_gpio_configure_pin(CFG_GPIO_MB_BUTTON_SW2_PORT, CFG_GPIO_MB_BUTTON_SW2_PIN,
               HW_GPIO_MODE_INPUT_PULLUP, HW_GPIO_FUNC_GPIO, true);
        //mytime = rtc_get_fromISR();
}

void hw_set_mb_led1_level(uint8_t level)
{

}

void hw_init(void)
{
        hw_configure();
        ad_gpio_intr_init();
        ad_gpio_intr_register(K1_BUTTON);
        ad_gpio_intr_register(K2_BUTTON);
}


void hw_trigger_reboot(void)
{
        hw_cpm_reboot_system();
}

猜你喜欢

转载自blog.csdn.net/JaLLs/article/details/84579192