关于wujian100 SDK中GPIO的调试问题

学习笔记

    • 问题一:引脚电平不稳定
    • 问题二:进入GPIO中断后出不来

第一次在CSDN写博客,用来记录一些学习笔记,小白一只,如有不足之处望大家多多理解和指导!

分享一下关于关于wujian100 SDK中GPIO的调试问题,SDK的源代码链接这里就不放了,相信出现bug的朋友肯定都会人手一份源代码了。

实现声明,我个人觉得源代码有问题,经过我的修改后,调试是成功。(咋也不敢说是源代码的错,也是是自己理解有误,毕竟自己是小白)

在这里先放GPIO源代码的主函数部分代码吧,便于参考:

#include 
#include "soc.h"
#include "drv_gpio.h"
#include "pin_name.h"
#include "pin.h"

volatile static bool int_flag = 1;

static void gpio_interrupt_handler(int32_t idx)
{
    int_flag = 0;
}

void example_pin_gpio_init(void)
{
    drv_pinmux_config(EXAMPLE_GPIO_PIN, EXAMPLE_GPIO_PIN_FUNC);
}

void gpio_falling_edge_interrupt(pin_name_e gpio_pin)
{
    gpio_pin_handle_t pin = NULL;

    example_pin_gpio_init();

    printf("please change the gpio pin %s from high to low\r\n", EXAMPLE_BOARD_GPIO_PIN_NAME);
    pin = csi_gpio_pin_initialize(gpio_pin, gpio_interrupt_handler);

    csi_gpio_pin_config_mode(pin, GPIO_MODE_PULLNONE);
    csi_gpio_pin_config_direction(pin, GPIO_DIRECTION_INPUT);
    csi_gpio_pin_set_irq(pin, GPIO_IRQ_MODE_FALLING_EDGE, 1);

    while (int_flag);

    int_flag = 1;
    csi_gpio_pin_uninitialize(pin);
    printf("gpio falling_edge test passed!!!\n");
    printf("test gpio successfully\n");
}

/*****************************************************************************
test_gpio: main function of the gpio test

INPUT: NULL

RETURN: NULL

*****************************************************************************/
int example_gpio(pin_name_e gpio_pin)
{
    gpio_falling_edge_interrupt(gpio_pin);
    return 0;
}

int main(void)
{
    return example_gpio(EXAMPLE_GPIO_PIN);
}

还有就是工程文件图:
关于wujian100 SDK中GPIO的调试问题_第1张图片

问题一:引脚电平不稳定

这个问题其实很简单,开发板XC7A200T的工作频率有20MHz,线路之间有很强的电路干扰。
当引脚悬空时,如果芯片工作在恶劣的环境下(如有电磁干扰)或者刚上电期间电源供电不稳定,引脚的电平值就会产生波动,这就是不确定信号。
神奇地,我用读引脚电平函数获取到的电平值是个周期的波动值周期在5s左右,以前玩32的时候还真没遇到过。
所以需要上下拉电阻,但是wujian100平台的FPGA源代码可能并没有内部上下拉的设计,所以代码中的这句
csi_gpio_pin_config_mode(pin, GPIO_MODE_PULLNONE);并无任何作用,最终还是需要自己外接上下拉电阻,电平才会真正稳定。

问题二:进入GPIO中断后出不来

首先要明白出不来的原因:中断标志位不清除, 结果是完成中断处理程序后, 它就继续再进中断, 根本不会回到主程序。
那么中断标志位在哪,怎么清楚?要了解到两个寄存器

  • 中断状态寄存器
    当产生对应中断时,这里的寄存器对应标志位会置1
    关于wujian100 SDK中GPIO的调试问题_第2张图片
    注意:其绝对地址为60018040
  • 中断清除寄存器
    给它写1,中断状态寄存器的标志位会清0
    关于wujian100 SDK中GPIO的调试问题_第3张图片
    注意:其绝对地址为6001804C
    绝对地址可以通过看数据手册查看!
    那么问题来了
    在isr.c->ATTRIBUTE_ISR void GPIO0_IRQHandler(void)->wj_oip_gpio_irqhandler(0);->gpio_irq_clear(gpio_pin_priv, (1 << i));中的这个GPIO中断清楚函数本该具有清楚函数这个功能,但是实际上见过我的调试发现,(代码步骤没错)中断清除寄存器虽为只写寄存器但实际上,根本写不进数据,所以产生中断后并不能通过这个函数有效地清楚中断位。

我一度接近奔溃,本以为无路可走。。。
后来意外地发现中断状态寄存器不仅可读而且可以写,这一切和数据手册说的完全不一样,所以我个人认为数据手册不对应FPGA的源程序。
除此之外经过调试还发现一个特点,要想直接改中断状态寄存器的数据,得暂时把中断关掉,改了中断状态寄存器数据后再打开。
总上所述可以得到解决方案:

  1. 在wj_oip_gpio.h中先把寄存器INTSTATUS改为__IOM
__IOM  uint32_t INTSTATUS;      /* Offset: 0x010 (R)    Interrupt status of Port */	//IM
  1. 在isr.c->ATTRIBUTE_ISR void GPIO0_IRQHandler(void)->wj_oip_gpio_irqhandler(0);中把gpio_irq_clear(gpio_pin_priv, (1 << i))替换成以下代码
gpio_pin_handle_t pin = (gpio_pin_handle_t *)&gpio_pin_handle[pin_idx];
gpio_irq_disable(pin);
gpio_control_reg->INTSTATUS = 0;//注意:这是把所有的中断位都清除
gpio_irq_enable(pin);			

这样应该是不会产生跳不出中断的问题了,不知道代码有没有总结漏,但思路没毛病。

但至今仍有一个奇怪的疑问就是,为什么源测试代码就可以跳出中断一次。感觉主要还是引脚的不稳定和寄存器的共同毛病造成的,导致眼见不一定为实。今天先记录到这里,至少程序是按预期正常工作了,关于这个问题有空再深入理解,以上只是为了给各位朋友在遇到类似问题时提供一个想法,谢谢

你可能感兴趣的:(关于wujian100 SDK中GPIO的调试问题)