2301_76839845 2024-05-22 15:48 采纳率: 0%
浏览 27
已结题

STM32+LWIP+ADC+DMA

请问一下这个该怎么办
stm32H723运行lwip正常,只要加上ADC使用dma就连不上网络了,通过抓包软件也看不到有SYN码,LWIP报错Assertion "pbuf_free: p->ref > 0" failed at line 753 in ../Middlewares/Third_Party/LwIP/src/core/pbuf.c

  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-22 15:48
    关注

    引自免费微信小程序:皆我百晓生

    在您的情况下,STM32H723使用LWIP网络库时,加入ADC DMA后导致网络连接失败,并且出现了内存管理错误。这可能是由于ADC DMA操作与LWIP中的任务调度、内存池管理之间存在冲突。为了解决这个问题,您可以尝试以下几个步骤:

    1. 检查ADC DMA配置: 确保ADC的DMA配置正确无误,包括触发源、通道选择、传输大小等。
    // 在这里配置ADC DMA
    ADC_HandleTypeDef hadc;
    DMA_HandleTypeDef hdma_adc;
    
    hadc.Instance = ADC1; // 根据实际使用的ADC选择实例
    hdma_adc.Instance = DMA1_Channel2; // 根据实际使用的DMA选择通道
    
    // 配置ADC
    // ...
    
    // 配置DMA
    hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc.Init.PeriphDataAlignment = DMA_DATAALIGN_WORD;
    hdma_adc.Init.MemDataAlignment = DMA_DATAALIGN_WORD;
    hdma_adc.Init.Mode = DMA_CIRCULAR;
    hdma_adc.Init.Priority = DMA_PRIORITY_LOW;
    HAL_DMA_Init(&hdma_adc);
    
    // 连接ADC到DMA
    __HAL_LINKDMA(hadc, HDMA_Handle, hdma_adc);
    
    1. 调整中断优先级: 确保ADC DMA中断的优先级低于LWIP相关的任务(例如TCP/IP中断)。这可以通过修改NVIC中断优先级寄存器设置实现。
    // 获取当前ADC DMA中断优先级
    uint32_t priority = NVIC_GetPriority(ADC_IRQn);
    // 设置一个较低的优先级,比如抢占优先级为4,响应优先级为0
    priority = __NVIC_SET_PRIORITY(ADC_IRQn, 4, 0);
    NVIC_SetPriority(ADC_IRQn, priority);
    
    // 同样地,可能还需要调整其他相关中断
    
    1. 使用互斥锁保护LWIP内存池: 当ADC DMA读取ADC数据时,它可能会访问LWIP的内存池。为了避免并发访问引发的问题,可以使用互斥锁来保护内存池。

    首先,在头文件中包含semphr.h,然后创建一个互斥锁变量。

    #include "semphr.h"
    SemaphoreHandle_t adc_dma_semaphore = NULL;
    

    在ADC DMA完成回调函数中获取和释放互斥锁。

    void HAL_ADCExConversionCompleteCallback(ADC_HandleTypeDef* hadc) {
        SemaphoreGiveFromISR(adc_dma_semaphore, NULL);
    }
    
    void adc_dma_start() {
        SemaphoreCreateBinary(adc_dma_semaphore);
        // ... 其他ADC DMA初始化代码
        HAL_NVIC_EnableIRQ(ADC_IRQn); // 开启ADC中断
    }
    

    在ADC DMA中断处理程序中,使用SemaphoreTakeFromISR()获取锁,然后在处理完ADC数据后调用SemaphoreGiveFromISR()释放锁。

    void ADC_IRQHandler(void) {
        if (HAL_ADC_GetITStatus(hadc, ADC_IT_EOC) != RESET) {
            HAL_ADC_IRQHandler(hadc);
            SemaphoreTakeFromISR(adc_dma_semaphore, NULL);
            // 处理ADC数据
            SemaphoreGiveFromISR(adc_dma_semaphore, NULL);
            HAL_NVIC_ClearPendingIRQ(ADC_IRQn);
        }
    }
    
    1. 检查LWIP堆栈配置: 确保LWIP的内存池足够大,可以容纳所有预期的数据包。如果内存池太小,可能会导致上述的内存管理错误。
    #define MEMP_POOL_SIZE   800 // 增加内存池大小,根据需求调整
    #define MEMP_NUM_TCP_PCB  10 // 根据需求调整
    #define MEMP_NUM_UDP_PCB  10 // 根据需求调整
    #define MEMP_NUM_RAW_PCB  10 // 根据需求调整
    #define MEMP_NUM_FRAG     10 // 根据需求调整
    #define MEMP_NUM_SYSMOB   20 // 根据需求调整
    
    struct memp上下文{
      struct list { struct list *next; } list;
    };
    extern struct memp上下文 MempFree[memp上下文总共];
    

    执行以上步骤后,应该能解决LWIP与ADC DMA之间的冲突。然而,如果问题依然存在,请考虑使用调试工具进一步分析,例如使用RTOS调试工具查看任务切换情况,或者使用硬件断点检查ADC DMA和LWIP任务之间的交互。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月23日
  • 创建了问题 5月22日

悬赏问题

  • ¥15 三分类机器学习模型可视化分析
  • ¥15 本地测试网站127.0.0.1 已拒绝连接,如何解决?(标签-ubuntu)
  • ¥50 Qt在release捕获异常并跟踪堆栈(有Demo,跑一下环境再回答)
  • ¥30 python,LLM 文本提炼
  • ¥15 关于将inet引入的相关问题
  • ¥15 关于一个倒计时的操作和显示设计
  • ¥15 提问STK的问题,哪位航天领域的同学会啊
  • ¥15 苹果系统的mac m1芯片的笔记本使用ce修改器使用不了
  • ¥15 单相逆变的电压电流双闭环中进行低通滤波PID算法改进
  • ¥15 关于#java#的问题,请各位专家解答!