我正在 TrueSTM Atollic IDE 上调试错误的串行连接。
监 window 口,表达式
要求我选择一个变量并将其显示为数组。缺点是我需要在每次重新编译时重新选择,+100 值时它会变得非常慢,而且对我来说看起来不太清楚。
因此,我创建了一个函数,它可以简单地打印出其中一个缓冲区中保存的字节,然后将这些字节显示在 SWV 控制台上。
freertos.c
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"
#include "stdbool.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
uint8_t X [4] = {0xFF,0xFF,0xFF,0xFF};
uint8_t * xt = X;
osThreadDef(CAN_Producer, FrameExtractorNEW, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(CAN_Producer), NULL);
void FrameExtractorNEW(void const * argument){
Print_Bytes(xt,4); // fails
printf("Cheese\n") // fails
}
main.c
#include "main.h"
#include "cmsis_os.h"
#include "can.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_CAN2_Init();
MX_CAN1_Init();
MX_USART3_UART_Init();
MX_FREERTOS_Init();
osKernelStart();
while (1)
{}
}
// accept pointer to first element, and number of consecutive byte values to display
void Print_Bytes(uint8_t * a1, int bytes_to_read){
for (int i = 0; i<bytes_to_read; i++){
printf("0x%02X " , *(a1+i));
}
}
到目前为止,事情很简单、直接,至少看起来是这样。
我的问题是,如果我尝试使用 freertos.c
中的函数 Print_Bytes()
,它会起作用,但前提是它至少已被调用之前在 main.c
中出现过一次。在 main.c
中使用 printf()
打印任何内容至少一次也将使其在其他文件中的其他位置工作。
如果没有“启用”程序,程序执行将转到 HardFault_Handler()
,并出现以下错误。
对于调用它们的函数,我有必要包含 printf()
和 Print_Bytes()
,但它似乎不足以让它正常工作我希望它应该有效。
最佳答案
我敢打赌,第一次运行时的 printf
会初始化一些内部变量。在 main 中它使用主程序堆和堆栈。如果您第一次在任务中使用,它会在任务堆和堆栈上执行,并且所有标准分配都可能在此上下文中不起作用(printf 使用 malloc 函数)。
我个人已经编写了这个函数系列的我自己的 freeRTOS 安全版本。在多线程环境中使用线程不安全函数是非常糟糕的做法。
关于c - 无法在 main 之外使用 printf(),除非 printf() 在 main 中至少使用一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55187546/