学习笔记
- 问题一:引脚电平不稳定
- 问题二:进入GPIO中断后出不来
第一次在CSDN写博客,用来记录一些学习笔记,小白一只,如有不足之处望大家多多理解和指导!
分享一下关于关于wujian100 SDK中GPIO的调试问题,SDK的源代码链接这里就不放了,相信出现bug的朋友肯定都会人手一份源代码了。
实现声明,我个人觉得源代码有问题,经过我的修改后,调试是成功。(咋也不敢说是源代码的错,也是是自己理解有误,毕竟自己是小白)
在这里先放GPIO源代码的主函数部分代码吧,便于参考:
#include <stdio.h>
#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");
}
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);
}
还有就是工程文件图:
问题一:引脚电平不稳定
这个问题其实很简单,开发板XC7A200T的工作频率有20MHz,线路之间有很强的电路干扰。
当引脚悬空时,如果芯片工作在恶劣的环境下(如有电磁干扰)或者刚上电期间电源供电不稳定,引脚的电平值就会产生波动,这就是不确定信号。
神奇地,我用读引脚电平函数获取到的电平值是个周期的波动值周期在5s左右,以前玩32的时候还真没遇到过。
所以需要上下拉电阻,但是wujian100平台的FPGA源代码可能并没有内部上下拉的设计,所以代码中的这句
csi_gpio_pin_config_mode(pin, GPIO_MODE_PULLNONE);并无任何作用,最终还是需要自己外接上下拉电阻,电平才会真正稳定。
问题二:进入GPIO中断后出不来
首先要明白出不来的原因:中断标志位不清除, 结果是完成中断处理程序后, 它就继续再进中断, 根本不会回到主程序。
那么中断标志位在哪,怎么清楚?要了解到两个寄存器
我一度接近奔溃,本以为无路可走。。。
后来意外地发现中断状态寄存器不仅可读而且可以写,这一切和数据手册说的完全不一样,所以我个人认为数据手册不对应FPGA的源程序。
除此之外经过调试还发现一个特点,要想直接改中断状态寄存器的数据,得暂时把中断关掉,改了中断状态寄存器数据后再打开。
总上所述可以得到解决方案:
- 在wj_oip_gpio.h中先把寄存器INTSTATUS改为__IOM
__IOM uint32_t INTSTATUS; /* Offset: 0x010 (R) Interrupt status of Port */ //IM
- 在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);
这样应该是不会产生跳不出中断的问题了,不知道代码有没有总结漏,但思路没毛病。
但至今仍有一个奇怪的疑问就是,为什么源测试代码就可以跳出中断一次。感觉主要还是引脚的不稳定和寄存器的共同毛病造成的,导致眼见不一定为实。今天先记录到这里,至少程序是按预期正常工作了,关于这个问题有空再深入理解,以上只是为了给各位朋友在遇到类似问题时提供一个想法,谢谢
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)