eCos GPIO读写及其中断处理

#include "oem_portmisc.h"
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/drv_api.h>

#define GINT_FEDGE_0 0x10000660
#define GINT_STAT_0 0x10000690

typedef union gpio1mode_data {
    u32 d32;
    struct {
        u32 gpio_mode:2;
        u32 rsvd2_5:4;
        u32 i2s_mode:2;
        u32 rsvd8_19:12;
        u32 i2c_mode:2;
        u32 rsvd22_23:2;
        u32 uart1_mode:2;
        u32 rsvd26_31:6;
    } b;
} gpio1mode_data_t;

typedef union gpio2mode_data {
    u32 d32;
    struct {
        u32 rsvd0_19:20;
        u32 p1_led_kn_mode:2;
        u32 p2_led_kn_mode:2;
        u32 p3_led_kn_mode:2;
        u32 p4_led_kn_mode:2;
        u32 rsvd28_31:4;
    } b;
} gpio2mode_data_t;

#if defined(CONFIG_GPIO_INTR_MODE)
typedef struct gpio_intr_info {
    CYG_WORD       int_num;
    cyg_interrupt  gpio_interrupt;
    cyg_handle_t   gpio_interrupt_handle;
} gpio_intr_info_t;

static gpio_intr_info_t gii_1 = {
    .int_num = CYGNUM_HAL_INTERRUPT_PIO,
};

static u32 va(u32 addr);

static void toggle_relay_gpio(uint8_t gpio)
{
    if (gpio_get_value(gpio) > 0) {
        gpio_set_value(gpio, 0);
        // TODO: save it to nv
    } else {
        gpio_set_value(gpio, 1);
        // TODO: save it to nv
    }
}

static cyg_uint32 gpio_isr(cyg_vector_t vector, cyg_addrword_t data)
{
    gpio_intr_info_t * gii = (gpio_intr_info_t *)data;

    cyg_drv_interrupt_mask(gii->int_num);
    cyg_drv_interrupt_acknowledge(gii->int_num);

    // Cause DSR to be run
    return CYG_ISR_CALL_DSR;
}

static void gpio_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
    gpio_intr_info_t * gii = (gpio_intr_info_t *)data;
    u32 val = HAL_REG32(va(GINT_STAT_0));

    if ((val >> SUMPWR_KEY_GPIO) & 0x1) {
        toggle_relay_gpio(RELAY1_GPIO);
    }
    if ((val >> KEY2_GPIO) & 0x1) {
        toggle_relay_gpio(RELAY2_GPIO);
    }
    if ((val >> KEY3_GPIO) & 0x1) {
        toggle_relay_gpio(RELAY3_GPIO);
    }
    if ((val >> KEY4_GPIO) & 0x1) {
        toggle_relay_gpio(RELAY4_GPIO);
    }

    cyg_drv_interrupt_unmask(gii->int_num);
    diag_printf("%p\n", gii);
}
#endif

static inline u32 va(u32 addr)
{
    u32 phy_addr = addr;

    // kseg1: 0xA000 0000 - 0xBFFF FFFF(512M)
    phy_addr &= 0x0FFFFFFC;
    //phy_addr &= 0x0FFFFFFF;
    phy_addr |= 0xb0000000;

    return phy_addr;
}

static int8_t gpio_direction_input(uint8_t gpio)
{
    mem_data_t reg_val;
    u32 ctrl_addr;

    if (gpio > 95) {
        return -1;
    }

    if (gpio <= 31) {
        // GPIO_CTRL_0
        ctrl_addr = va(0x10000600);
    } else if (gpio >= 32 && gpio <= 63) {
        // GPIO_CTRL_1
        ctrl_addr = va(0x10000604);
        gpio = gpio - 32;
    } else {
        // 64 ... 95
        // GPIO_CTRL_2
        ctrl_addr = va(0x10000608);
        gpio = gpio - 64;;
    }

    reg_val.d32 = HAL_REG32(ctrl_addr);
    reg_val.d32 &= ~(1 << gpio);
    HAL_REG32(ctrl_addr) = reg_val.d32;
    return 0;
}

int8_t gpio_get_value(uint8_t gpio)
{
    mem_data_t reg_val;
    u32 ctrl_addr;
    u32 data_addr;

    if (gpio > 95) {
        return -1;
    }

    if (gpio <= 31) {
        // GPIO_CTRL_0
        //ctrl_addr = va(0x10000600);
        // GPIO_DATA_0
        data_addr = va(0x10000620);
    } else if (gpio >= 32 && gpio <= 63) {
        // GPIO_CTRL_1
        //ctrl_addr = va(0x10000604);
        // GPIO_DATA_1
        data_addr = va(0x10000624);
        gpio = gpio - 32;
    } else {
        // 64 ... 95
        // GPIO_CTRL_2
        //ctrl_addr = va(0x10000608);
        // GPIO_DATA_2
        data_addr = va(0x10000628);
        gpio = gpio - 64;;
    }

   // reg_val.d32 = HAL_REG32(ctrl_addr);
   // reg_val.d32 &= ~(1 << gpio);
   // HAL_REG32(ctrl_addr) = reg_val.d32;

    reg_val.d32 = HAL_REG32(data_addr);
    return ((reg_val.d32 >> gpio) & 0x1);
}

void gpio_set_value(uint8_t gpio, uint8_t value)
{
    mem_data_t reg_val;
    u32 ctrl_addr;
    u32 data_addr;

    if (gpio > 95) {
        return;
    }

    if (gpio <= 31) {
        // GPIO_CTRL_0
        ctrl_addr = va(0x10000600);
        if (value > 0) {
            // GPIO_DSET_0
            data_addr = va(0x10000630);
        } else {
            // GPIO_DCLR_0
            data_addr = va(0x10000640);
        }
    } else if (gpio >= 32 && gpio <= 63) {
        // GPIO_CTRL_1
        ctrl_addr = va(0x10000604);
        if (value > 0) {
            // GPIO_DSET_1
            data_addr = va(0x10000634);
        } else {
            // GPIO_DCLR_1
            data_addr = va(0x10000644);
        }
        gpio = gpio - 32;
    } else {
        // 64 ... 95
        // GPIO_CTRL_2
        ctrl_addr = va(0x10000608);
        if (value > 0) {
            // GPIO_DSET_2
            data_addr = va(0x10000638);
        } else {
            // GPIO_DCLR_2
            data_addr = va(0x10000648);
        }
        gpio = gpio - 64;
    }

    reg_val.d32 = HAL_REG32(ctrl_addr);
    reg_val.d32 |= 1 << gpio;
    HAL_REG32(ctrl_addr) = reg_val.d32;

    reg_val.d32 = HAL_REG32(data_addr);
    reg_val.d32 |= 1 << gpio;
    HAL_REG32(data_addr) = reg_val.d32;
}

void gpio_init(void)
{
#if defined(CONFIG_GPIO_INTR_MODE)
    gpio_intr_info_t *gii;
#endif
    gpio1mode_data_t gpio1mode;
    gpio2mode_data_t gpio2mode;
    u32 addr, val;

    // pin mux
    // Reference to "MT7628 PROGRAMMING GUIDE", p15 of System Control
    // GPIO1_MODE 0x10000060
    // GPIO2_MODE 0x10000064
    // GPIO00,02,03,04,05,11, key4,key3,key2,sumpwr_led1,sumpwr_key,zero
    addr = va(0x10000060);

    gpio1mode.d32 = HAL_REG32(addr);
    // GPIO11
    gpio1mode.b.gpio_mode = 0;
    // GPIO00,02,03
    gpio1mode.b.i2s_mode = 1;
    // GPIO04,05
    gpio1mode.b.i2c_mode = 1;
    //gpio1mode.b.uart1_mode = 0;
    HAL_REG32(addr) = gpio1mode.d32;
    /* falling edge */
    gpio_direction_input(SUMPWR_KEY_GPIO);
    gpio_direction_input(KEY2_GPIO);
    gpio_direction_input(KEY3_GPIO);
    gpio_direction_input(KEY4_GPIO);

    // GPIO30,31,32,33, r4,r3,r2,r1
    addr = va(0x10000064);

    gpio2mode.d32 = HAL_REG32(addr);
    // GPIO33
    gpio2mode.b.p1_led_kn_mode = 1;
    // GPIO32
    gpio2mode.b.p2_led_kn_mode = 1;
    // GPIO31
    gpio2mode.b.p3_led_kn_mode = 1;
    // GPIO30
    gpio2mode.b.p4_led_kn_mode = 1;
    HAL_REG32(addr) = gpio2mode.d32;
    /* relay on: LOW, relay off: HIGH */
    gpio_set_value(RELAY1_GPIO, 1);
    gpio_set_value(RELAY2_GPIO, 1);
    gpio_set_value(RELAY3_GPIO, 1);
    gpio_set_value(RELAY4_GPIO, 1);

#if defined(CONFIG_GPIO_INTR_MODE)
    val = HAL_REG32(va(GINT_FEDGE_0));
    val |= (1 << SUMPWR_KEY_GPIO) | (1 << KEY2_GPIO) | (1 << KEY3_GPIO) | (1 << KEY4_GPIO);
    HAL_REG32(va(GINT_FEDGE_0)) = val;

    gii = &gii_1;
    cyg_drv_interrupt_create(gii->int_num,
            5,                        // can change IRQ0 priority
            (cyg_addrword_t)gii,    // Data item passed to interrupt handler
            gpio_isr,
            gpio_dsr,
            &gii->gpio_interrupt_handle,
            &gii->gpio_interrupt);
    cyg_drv_interrupt_attach(gii->gpio_interrupt_handle);
    cyg_drv_interrupt_unmask(gii->int_num);
#endif
}
module_init(gpio_init);

发布了124 篇原创文章 · 获赞 51 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/zoosenpin/article/details/76019349