嵌入式技术william hill官网
直播中

goodmbby

8年用户 1163经验值
擅长:处理器/DSP
私信 关注
[问答]

使用基于STM32F407的RTTStudio一直进不了外部中断是什么原因造成的呢

使用RTT Studio基于STM32F407芯片开发,之前使用引脚的外部中断功能正常,最近把某些引脚的初始化换到其他文件放,结果一直进不了外部中断。后来调试跟踪才发现,绑定中断时rt_pin_attach_irq()返回值=7,这个是什么原因造成的呢?

回帖(8)

贾熹

2022-8-9 10:09:37
既然可以调试跟踪,那不直接看看谁在返回-7,问题不就清楚了么。
举报

goodmbby

2022-8-9 10:09:50
还在跟踪
1.jpg


举报

王越建

2022-8-9 10:10:08
rt_pin_attach_irq 的源码如下:

rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void  *args)
{
    RT_ASSERT(_hw_pin.ops != RT_NULL);
    if(_hw_pin.ops->pin_attach_irq)
    {
        return _hw_pin.ops->pin_attach_irq(&_hw_pin.parent, pin, mode, hdr, args);
    }
    return -RT_ENOSYS;
}
static rt_err_t stm32_pin_attach_irq(struct rt_device *device, rt_int32_t pin, rt_uint32_t mode, void (*hdr)(void *args), void *args)
{
    const struct pin_index *index;
    rt_base_t level;
    rt_int32_t irqindex = -1;
    index = get_pin(pin);
    if (index == RT_NULL)
    {
        return RT_ENOSYS;
    }
    irqindex = bit2bitno(index->pin);
    if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
    {
        return RT_ENOSYS;
    }
    level = rt_hw_interrupt_disable();
    if (pin_irq_hdr_tab[irqindex].pin == pin &&
            pin_irq_hdr_tab[irqindex].hdr == hdr &&
            pin_irq_hdr_tab[irqindex].mode == mode &&
            pin_irq_hdr_tab[irqindex].args == args)
    {
        rt_hw_interrupt_enable(level);
        return RT_EOK;
    }
    if (pin_irq_hdr_tab[irqindex].pin != -1)
    {
        rt_hw_interrupt_enable(level);
        return RT_EBUSY;
    }
    pin_irq_hdr_tab[irqindex].pin = pin;
    pin_irq_hdr_tab[irqindex].hdr = hdr;
    pin_irq_hdr_tab[irqindex].mode = mode;
    pin_irq_hdr_tab[irqindex].args = args;
    rt_hw_interrupt_enable(level);
    return RT_EOK;
}
上述代码会将中断统一放在 pin_irq_hdr_tab 数组中,你在调试的时候看一下,pin_irq_hdr_tab 这个表是否和默认初始化的值一样,另外看一下你代码在函数 stm32_pin_attach_irq() 中计算得到的 irqindex 的值是多少?然后代码根据 pin_irq_hdr_tab[irqindex].pin 是否是 -1,也就是是否还有未初始化的成员来判断是否可以绑定中断回调函数,否则就直接返回 RT_EBUSY(7)

你一共初始化了几个 IO 中断?是不是有类似 PA3 PB3 这种情况都初始化 IO 中断了?可以把你所有关于 IO 中断初始化和绑定回调函数的代码贴上来。

static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
{
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
};
举报

goodmbby

2022-8-9 10:10:19
专业呀,是的。是这个原因,原来以前注释掉的那个功能块也使用这些IO的外部中断,导致的!
能问您一个额外的问题吗?一般线程栈溢出是啥原因,也没有开辟什么资源,就是外部中断进来后通过串口发送数据。但是发现一旦进入外部中断,不一会就报错了,栈空间越来越大,最后满了。
1.jpg
举报

goodmbby

2022-8-9 10:10:24
不过确实是通过串口发送数据导致的问题。
举报

王越建

2022-8-9 10:10:35
越来越大是不是你动态申请了什么然后没有释放导致的,你代码是怎么写的可以放上来看看
举报

goodmbby

2022-8-9 10:10:47
static void func_thread(void* paratmer)
{
while(1)
{
if(某个事件发生)
{
串口发送数据;
}
}
}

我已经发现如果注释掉串口发送数据的语句,就不会溢出。
然后串口发送主要调用了函数:rt_device_write(servo_rs232_serial, 0, buf, 10);
举报

王越建

2022-8-9 10:11:21
你是用中断发送的还是轮询发送的?我还没用过中断发送,轮询发送的源码如下,这里面是不会出现申请空间的操作的。 rt_serial_write -> _serial_poll_tx -> serial->ops->putc(将要发送的数据写到寄存器中)

static rt_size_t rt_serial_write(struct rt_device *dev,
                                 rt_off_t          pos,
                                 const void       *buffer,
                                 rt_size_t         size)
{
    struct rt_serial_device *serial;
    RT_ASSERT(dev != RT_NULL);
    if (size == 0) return 0;
    serial = (struct rt_serial_device *)dev;
    if (dev->open_flag & RT_DEVICE_FLAG_INT_TX)
    {
        return _serial_int_tx(serial, (const rt_uint8_t *)buffer, size);
    }
#ifdef RT_SERIAL_USING_DMA
    else if (dev->open_flag & RT_DEVICE_FLAG_DMA_TX)
    {
        return _serial_dma_tx(serial, (const rt_uint8_t *)buffer, size);
    }
#endif /* RT_SERIAL_USING_DMA */
    else
    {
        return _serial_poll_tx(serial, (const rt_uint8_t *)buffer, size);
    }
}
rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t *data, int length)
{
    int size;
    RT_ASSERT(serial != RT_NULL);
    size = length;
    while (length)
    {
        /*
         * to be polite with serial console add a line feed
         * to the carriage return character
         */
        if (*data == 'n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM))
        {
            serial->ops->putc(serial, 'r');
        }
        serial->ops->putc(serial, *data);
        ++ data;
        -- length;
    }
    return size - length;
}
你把你写的代码贴上来,伪代码的逻辑看着是没有问题的,不会导致内存泄露。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分