OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7599|回复: 11

【求助】FreeRTOS在uxListRemove出现HardFault

[复制链接]

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
发表于 2022-5-21 16:30:42 | 显示全部楼层 |阅读模式
50金钱
本帖最后由 让睫毛载来爱 于 2022-5-21 23:59 编辑

学习stm32与FreeRTOS的时候,想通过uart+DMA做一个发送数据的功能

实现方法是
  1. 申请一个队列,在调用发送时,将数据指针放在队列中
  2. 起一个读取任务一直读这个队列,读到数据后,调用DMA发送,然后等待DMA发送完成的信号量
  3. 在DMA发送完成的中断中,释放信号量,使读取任务继续循环

按照思路已经实现了代码:
void dmauart_init(void);
void dma_print(const char *fmt, ...)
    __attribute__((__format__(__printf__, 1, 2)));
void dmauart_send(void *pdata, uint32_t len);
void dmauart_send_no_copy(void *pdata, uint32_t len);
size_t dmauart_rcv(void *pdata, uint32_t len, TickType_t xBlockTime);
写了测试任务:
  使用dmauart_send的时候可以正常发送,
  使用dma_print就会进入HardFault中断
testtask.png

进入HardFault中断调用栈
callstack.png

对比了下dmauart_senddma_print
dma_print获取了当前线程名字,并根据print参数输出两个格式化参数
最终调用dmauart_send输出给队列,发送任务读取到队列数据进行发送
print.png


现在不知道哪里出了问题,导致进入了HardFault_Handler中断
还有就是出现HardFault_Handler中断怎么调试处理呢?
板子使用的 NUCLEO-F767ZI
代码已上传,使用clion+openocd

f767uartdma.zip

2.16 MB, 下载次数: 2

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

800

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3775
金钱
3775
注册时间
2017-3-7
在线时间
1645 小时
发表于 2022-5-23 12:18:51 | 显示全部楼层
目前程序没看出来哪有问题,不过动态内存申请完,最好判断下是否申请成功,NULL!=PTR,试试把任务的stacksize设大点试试
回复

使用道具 举报

70

主题

6698

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
12692
金钱
12692
注册时间
2012-11-26
在线时间
3711 小时
发表于 2022-5-23 12:58:30 | 显示全部楼层
任务的开销给小了可能,开大点
学无止境
回复

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
 楼主| 发表于 2022-5-24 02:57:35 | 显示全部楼层
a5820736 发表于 2022-5-23 12:18
目前程序没看出来哪有问题,不过动态内存申请完,最好判断下是否申请成功,NULL!=PTR,试试把任务的stacks ...

内核内存分配200k,任务栈从128改为512还是不行
回复

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
 楼主| 发表于 2022-5-24 02:58:01 | 显示全部楼层
jermy_z 发表于 2022-5-23 12:58
任务的开销给小了可能,开大点

内核内存分配200k,任务栈从128改为512还是不行
回复

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
 楼主| 发表于 2022-5-24 03:03:25 | 显示全部楼层


删除了不相关方法完整代码

==========================================================

#include "dmauart.h"
#include "main.h"
#include "semphr.h"
#include "stm32f7xx_hal.h"
#include "stm32f7xx_nucleo_144.h"
#include "stream_buffer.h"
#include "string.h"
#include <queue.h>
#include <stdarg.h>
#include <stdio.h>
#include <stm32f7xx_hal_uart.h>

typedef struct {
    uint32_t len;
    uint8_t free_after_use;
    void *pdata;
} binary_t;

void MX_USART3_UART_Init();

static QueueHandle_t dmaTxBusy = NULL;

static QueueHandle_t sendFunBusy = NULL;
static QueueHandle_t rcvFunBusy = NULL;

static QueueHandle_t dmaTxQueue = NULL;

TaskHandle_t dmaTxTaskHandle;

_Noreturn void dmaTxTask(void *argument);

StreamBufferHandle_t dmaRxStream;

void dmauart_init(void) {
    // send and dma Mutex
    dmaTxBusy = xSemaphoreCreateCounting(1, 1);

    sendFunBusy = xSemaphoreCreateBinary();
    xSemaphoreGive(sendFunBusy);

    rcvFunBusy = xSemaphoreCreateBinary();
    xSemaphoreGive(rcvFunBusy);

    dmaTxQueue = xQueueCreate(16, sizeof(binary_t));
    dmaRxStream = xStreamBufferCreate(128, 0);

    MX_USART3_UART_Init();

    xTaskCreate((TaskFunction_t) dmaTxTask, "dmaTxTask", 128 * 4, NULL, 40,
                &dmaTxTaskHandle);
}

// hdma_usart3_rx
void DMA1_Stream1_IRQHandler(void) {
    if (READ_BIT(DMA1->LISR, DMA_LISR_TCIF1)) {
        DMA1->LIFCR = DMA_LIFCR_CTCIF1;
        // rx dma complete
        portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;

        uint32_t size = RECEIVE_BUFF_SIZE - DMA_RX_Stream->NDTR;
        if (size == 0) {
            return;
        }
        if (READ_BIT(DMA_RX_Stream->CR, DMA_SxCR_CT)) {
            xStreamBufferSendFromISR(dmaRxStream, (const void *) DMA_RX_Stream->M1AR,
                                     size, &xHigherPriorityTaskWoken);
        } else {
            xStreamBufferSendFromISR(dmaRxStream, (const void *) DMA_RX_Stream->M0AR,
                                     size, &xHigherPriorityTaskWoken);
        }
    }
}

void DMA1_Stream3_IRQHandler(void) {
    if (READ_BIT(DMA1->LISR, DMA_LISR_TCIF3)) {
        DMA1->LIFCR = DMA_LIFCR_CTCIF3;
        // tx dma complete
        portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        xSemaphoreGiveFromISR(dmaTxBusy, &xHigherPriorityTaskWoken);
        portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
    }
    if (READ_BIT(DMA1->LISR, DMA_LISR_FEIF3)) {
        // tx dma harf complete
        DMA1->LIFCR = DMA_LIFCR_CFEIF3;
    }
}

void USART3_IRQHandler(void) {
    if ((USART3->ISR & USART_ISR_ORE) == USART_ISR_ORE) {
        USART3->ICR = USART_ICR_ORECF;
    }

    if (READ_BIT(USART3->ISR, USART_ISR_RTOF)) {
        USART3->ICR = USART_ICR_RTOCF;
        BSP_LED_Toggle(LED_GREEN);
        portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
        CLEAR_BIT(DMA_RX_Stream->CR, DMA_SxCR_EN);
        uint32_t size = RECEIVE_BUFF_SIZE - DMA_RX_Stream->NDTR;

        if (size == 0)
            goto end;

        if (READ_BIT(DMA_RX_Stream->CR, DMA_SxCR_CT)) {
            xStreamBufferSendFromISR(dmaRxStream, (const void *) DMA_RX_Stream->M1AR,
                                     size, &xHigherPriorityTaskWoken);
        } else {
            xStreamBufferSendFromISR(dmaRxStream, (const void *) DMA_RX_Stream->M0AR,
                                     size, &xHigherPriorityTaskWoken);
        }
        SET_BIT(DMA_RX_Stream->CR, DMA_SxCR_EN);
        end:
        portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
        return;
    }

    if (READ_BIT(USART3->ISR, USART_ISR_TC)) {
        USART3->ICR = USART_ICR_TCCF;
    }
}

_Noreturn void dmaTxTask(void *argument) {
    binary_t msg = {0, 0, NULL};
    // disable dma
    CLEAR_BIT(DMA_TX_Stream->CR, DMA_SxCR_EN);

    MODIFY_REG(DMA_TX_Stream->CR, DMA_SxCR_CHSEL_Msk, 4 << DMA_SxCR_CHSEL_Pos);
    SET_BIT(DMA_TX_Stream->CR, DMA_SxCR_MINC);
    // set 01 to memory to p
    SET_BIT(DMA_TX_Stream->CR, DMA_SxCR_DIR_0);
    CLEAR_BIT(DMA_TX_Stream->CR, DMA_SxCR_DIR_1);
    // set uart tx
    DMA_TX_Stream->PAR = (uint32_t) &(USART3->TDR);
    // en TC IE
    SET_BIT(DMA_TX_Stream->CR, DMA_SxCR_TCIE);

    for (;;) {
        if (xQueueReceive(dmaTxQueue, &msg, portMAX_DELAY)) {

            CLEAR_BIT(DMA_TX_Stream->CR, DMA_SxCR_EN);
            DMA_TX_Stream->NDTR = msg.len;
            DMA_TX_Stream->M0AR = (uint32_t) msg.pdata;
            SET_BIT(DMA_TX_Stream->CR, DMA_SxCR_EN);
            SET_BIT(USART3->CR3, USART_CR3_DMAT);

            xSemaphoreTake(dmaTxBusy, portMAX_DELAY);
            if (msg.pdata != NULL && msg.free_after_use)
                vPortFree(msg.pdata);
            msg.pdata = 0;
            msg.free_after_use = 0;
            msg.len = 0;
        } else {
            taskYIELD();
        }
    }
}

void dma_print(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    int len = vsnprintf(NULL, 0, fmt, args);
    va_end(args);

    char *name = pcTaskGetName(NULL);
    int name_len = strlen(name);

    char *buffer = pvPortMalloc(len + name_len + 4);
    if (buffer == NULL) return;
    int index = 0;
    for (; index < name_len; ++index) {
        buffer[index] = name[index];
    }
    buffer[index++] = ':';
    buffer[index++] = ' ';

    int n = vsprintf(buffer + index, fmt, args);
    if (n > 0) {
        dmauart_send(buffer, index + n);
    } else {
        vPortFree(buffer);
    }
}

void dmauart_send(void *pdata, uint32_t len) {
    if (len == 0)
        return;
    if (pdata == NULL)
        return;

    xSemaphoreTake(sendFunBusy, portMAX_DELAY);
    void *buf = pvPortMalloc(len);
    memcpy(buf, pdata, len);
    binary_t msg;
    msg.len = len;
    msg.free_after_use = 1;
    msg.pdata = buf;
    xQueueSend(dmaTxQueue, (void *) &msg, (TickType_t) portMAX_DELAY);
    xSemaphoreGive(sendFunBusy);
}

UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_rx;
DMA_HandleTypeDef hdma_usart3_tx;

static uint8_t receive_buf0[RECEIVE_BUFF_SIZE];
static uint8_t receive_buf1[RECEIVE_BUFF_SIZE];

void MX_USART3_UART_Init(void) {
    huart3.Instance = USART3;
    huart3.Init.BaudRate = 115200;
    huart3.Init.WordLength = UART_WORDLENGTH_8B;
    huart3.Init.StopBits = UART_STOPBITS_1;
    huart3.Init.Parity = UART_PARITY_NONE;
    huart3.Init.Mode = UART_MODE_TX_RX;
    huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart3.Init.OverSampling = UART_OVERSAMPLING_16;
    huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
    huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    if (HAL_UART_Init(&huart3) != HAL_OK) {
        Error_Handler();
    }
}

void HAL_UART_MspInit(UART_HandleTypeDef *uartHandle) {

    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if (uartHandle->Instance == USART3) {
        __HAL_RCC_USART3_CLK_ENABLE();

        __HAL_RCC_GPIOD_CLK_ENABLE();
        /**USART3 GPIO Configuration
        PD8     ------> USART3_TX
        PD9     ------> USART3_RX
        */
        GPIO_InitStruct.Pin = STLK_RX_Pin | STLK_TX_Pin;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
        HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

        /* USART3 DMA Init */
        /* USART3_RX Init */
        hdma_usart3_rx.Instance = DMA1_Stream1;
        hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
        hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
        hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_usart3_rx.Init.Mode = DMA_NORMAL;
        hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
        hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
        if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK) {
            Error_Handler();
        }

        __HAL_LINKDMA(uartHandle, hdmarx, hdma_usart3_rx);

        /* USART3_TX Init */
        hdma_usart3_tx.Instance = DMA1_Stream3;
        hdma_usart3_tx.Init.Channel = DMA_CHANNEL_4;
        hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
        hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
        hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
        hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
        hdma_usart3_tx.Init.Mode = DMA_NORMAL;
        hdma_usart3_tx.Init.Priority = DMA_PRIORITY_LOW;
        hdma_usart3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
        if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK) {
            Error_Handler();
        }

        __HAL_LINKDMA(uartHandle, hdmatx, hdma_usart3_tx);

        /* USART3 interrupt Init */
        HAL_NVIC_SetPriority(USART3_IRQn, 6, 0);
        HAL_NVIC_EnableIRQ(USART3_IRQn);

        MODIFY_REG(USART3->RTOR, USART_RTOR_RTO, 1400);
        SET_BIT(USART3->CR2, USART_CR2_RTOEN);

        // disable dma
        CLEAR_BIT(DMA_RX_Stream->CR, DMA_SxCR_EN);
        MODIFY_REG(DMA_RX_Stream->CR, DMA_SxCR_CHSEL_Msk, 4 << DMA_SxCR_CHSEL_Pos);

        // set 00 to Peripheral-to-memory
        CLEAR_BIT(DMA_RX_Stream->CR, DMA_SxCR_DIR_0);
        CLEAR_BIT(DMA_RX_Stream->CR, DMA_SxCR_DIR_1);
        // set uart rx
        DMA_RX_Stream->PAR = (uint32_t) &(USART3->RDR);
        DMA_RX_Stream->M0AR = (uint32_t) &receive_buf0;
        DMA_RX_Stream->M1AR = (uint32_t) &receive_buf1;
        DMA_RX_Stream->NDTR = RECEIVE_BUFF_SIZE;
        SET_BIT(DMA_RX_Stream->CR, DMA_SxCR_MINC);
        SET_BIT(DMA_RX_Stream->CR, DMA_SxCR_DBM);
        // en TC IE
        SET_BIT(DMA_RX_Stream->CR, DMA_SxCR_TCIE);
        SET_BIT(DMA_RX_Stream->CR, DMA_SxCR_EN);

        CLEAR_BIT(USART3->CR1, USART_CR1_UE);
        SET_BIT(USART3->CR3, USART_CR3_DMAR);
        SET_BIT(USART3->CR1, USART_CR1_RTOIE);
        SET_BIT(USART3->CR1, USART_CR1_UE);
    }
}

回复

使用道具 举报

3

主题

800

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3775
金钱
3775
注册时间
2017-3-7
在线时间
1645 小时
发表于 2022-5-24 09:48:06 | 显示全部楼层
char *buffer = pvPortMalloc(len + name_len + 4);这个申请完了,传到dma_send后,没有释放
回复

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
 楼主| 发表于 2022-5-24 23:10:19 | 显示全部楼层
a5820736 发表于 2022-5-24 09:48
char *buffer = pvPortMalloc(len + name_len + 4);这个申请完了,传到dma_send后,没有释放

这个我知道,但是泄漏一两次不会导致进入HardFatal吧
还没到消息队列的接收端,不知道两个代码那里会导致HardFatal

现在的代码 // dma_print("dma_print %d\n", count++);
StartDefaultTask                      ->   任务启动
dma_print                                 ->   组装数据
dmauart_send                          ->   给队列发送书记
xQueueenericenc                    ->   FreeRTOS 消息队列发送
xTaskRemoveFromEventList   ->
HardFatal_Handler                   ->  进入异常


使用字符串就是可以的  /// dmauart_send("dmauart_send\r\n", 14);
dmauart_send                          ->   给队列发送书记
xQueueenericenc                    ->   FreeRTOS 消息队列发送
xTaskRemoveFromEventList   ->

dmaTxTask#xQueueReceive  -> 队列收到数据,调用dma,等待dma繁忙空闲
DMA1_Stream3_IRQHandler  -> dma 发送完成,释放dma繁忙

回复

使用道具 举报

3

主题

800

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3775
金钱
3775
注册时间
2017-3-7
在线时间
1645 小时
发表于 2022-5-25 13:57:19 | 显示全部楼层
让睫毛载来爱 发表于 2022-5-24 23:10
这个我知道,但是泄漏一两次不会导致进入HardFatal吧
还没到消息队列的接收端,不知道两个代码那里会 ...

嗯,这个只能dubug加断点调试了,但看代码没什么大毛病
回复

使用道具 举报

5

主题

133

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1775
金钱
1775
注册时间
2015-3-13
在线时间
270 小时
发表于 2022-8-1 17:12:01 来自手机 | 显示全部楼层
楼主的问题解决了没? 我也是进入hardfault
回复

使用道具 举报

3

主题

18

帖子

0

精华

初级会员

Rank: 2

积分
61
金钱
61
注册时间
2016-1-18
在线时间
26 小时
 楼主| 发表于 2022-11-17 18:15:49 | 显示全部楼层
shiqurizi 发表于 2022-8-1 17:12
楼主的问题解决了没? 我也是进入hardfault

没有,你解决了没
回复

使用道具 举报

32

主题

187

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1123
金钱
1123
注册时间
2021-3-21
在线时间
172 小时
发表于 2022-11-18 16:39:03 | 显示全部楼层
调试模式下看一下R14的值
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 22:06

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表