STM32/STM8技术论坛
直播中

未满1年用户
擅长:嵌入式技术 控制/MCU
私信 关注
[问答]

STM32串口接受中断使用C++STL中的queue导致所有中断失效

工程参数

  • 使用Keil的AC5编译器,搭配C++11,在Keil环境中开发STM32F103C8T6
  • 移植了FreeRTOS但是还在模块开发和测试阶段,因此还 没启动调度器 ,但是使用了heap4.c中的pvPortMalloc重载new和定义了内存分配器OSAllocator(下附源码),目的是使用STL库时用FreeRTOS托管内存
  • 单片机启动文件中Heap_Size设置为0,FreeRTOS的heap设置为8k
  • 有两个中断,1s触发的定时器中断和串口接收中断

遇到问题

串口发送是没有问题的,如果不是使用STL的queue,所有功能一切正常,每次接收中断都能正常触发。但是在串口中断中使用queue接受数据,只要触发一次接受中断并入队,那么这个串口中断和定时器中断都失效了,再也不会进去。

最奇怪的是之前这一套方案是可行的,但是写完定时器的代码后就不行了, 尽管不开定时器也不行


代码

串口相关

类成员变量定义:

class Uart_Dev
{
public:
...
private:
...
    uint16_t __rx_max_size;//定义最大容量
    std::queue<uint8_t, std::deque<uint8_t, OSAllocator<uint8_t>>> __rx_queue;
}

中断函数定义:

void Uart_Dev::isr_handler(uint8_t data)
{
    if (__rx_queue.size() < __rx_max_size)
    {
       __rx_queue.push(data);
    }
}
static Uart_Dev *usart1;//指向USART1外设的设备指针,创建有关USART1的对象时,会将this赋值给它
extern "C"
{
    void USART1_IRQHandler(void)
    {
        if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
        {
            uint8_t data = USART_ReceiveData(USART1);
            usart1->isr_handler(data);
        }
    }
}

自定义分配器

template <class _TypeT>
class OSAllocator
{
public:
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef _TypeT value_type;
    typedef value_type* pointer;
    typedef const value_type* const_pointer;
    typedef value_type& reference;
    typedef const value_type& const_reference;

    OSAllocator() noexcept {}

    OSAllocator(const OSAllocator&) noexcept {}

    template <class _TypeU>
    struct rebind {
        typedef OSAllocator<_TypeU> other;
    };

    template <class _TypeU>
    OSAllocator(const OSAllocator<_TypeU>&) noexcept {}

    template <class _TypeU>
    OSAllocator& operator=(const OSAllocator<_TypeU>&) noexcept {
        return *this;
    }

    pointer address(reference __x) const {
        return &__x;
    }

    const_pointer address(const_reference __x) const {
        return &__x;
    }

    pointer allocate(size_type __n, const void* = 0) {
        if (__n == 0) return nullptr;
        pointer __p = static_cast<pointer>(pvPortMalloc(__n * sizeof(value_type)));
        // if (!__p) throw std::bad_alloc();
        return __p;
    }

    void deallocate(pointer __p, size_type) {
        vPortFree(__p);
    }

    size_type max_size() const noexcept {
        return size_type(-1) / sizeof(value_type);
    }

    template <class _Up, class... _Args>
	void construct(_Up* __p, _Args... __args) {
		::new((void *)__p) _Up(__args...);
	}

    template <class _Up>
    void destroy(_Up* __p) noexcept {
        __p->~_Up();
    }
};

祝各位看到帖子和解决问题的大佬们身体健康,万事如意

回帖(1)

杨万富

2025-1-24 16:33:16
根据您的描述,您在使用STM32串口接收中断时,使用了C++ STL中的queue,导致所有中断失效。您使用的是Keil的AC5编译器,搭配C++11,在Keil环境中开发STM32F103C8T6,并移植了FreeRTOS。您已经定义了内存分配器OSAllocator,并使用heap4.c中的pvPortMalloc重载new。

首先,我们需要检查您的代码,以确保没有错误或冲突。以下是一些建议和可能的解决方案:

1. 确保您的FreeRTOS配置正确。检查FreeRTOSConfig.h文件中的配置参数,确保与您的硬件和需求相匹配。

2. 检查您的中断优先级设置。确保串口接收中断和定时器中断的优先级设置正确,以避免优先级冲突。

3. 检查您的串口中断服务例程(ISR)。确保在ISR中正确地处理数据,并将其放入queue中。同时,确保在ISR中没有使用过多的时间,因为这可能会导致其他中断被阻塞。

4. 检查您的queue实现。确保queue的大小足够大,以避免溢出。同时,确保在queue中正确地处理数据,以避免死锁。

5. 检查您的定时器中断服务例程。确保定时器中断服务例程正确地处理定时器中断,并避免与其他中断冲突。

6. 如果可能,尝试使用其他数据结构代替queue,例如使用环形缓冲区。这可能会减少中断失效的问题。

7. 检查您的代码,确保没有其他可能导致中断失效的问题。例如,确保没有使用过多的堆栈空间,或者在中断服务例程中调用了可能导致阻塞的函数。

8. 如果问题仍然存在,您可以尝试使用不同的内存分配器,或者不使用STL的queue,而是使用自定义的数据结构来存储接收到的数据。

通过检查和修改您的代码,您应该能够找到导致中断失效的原因,并解决这个问题。希望这些建议对您有所帮助。
举报

更多回帖

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