刚刚学习嵌入式,找了个STM32F429上的FreeRTOS的例子,可以通过USART1串口发送数据,在qemu模拟器上运行,COM3和COM4是一对虚拟串口,
qemu命令:qemu-system-gnuarmeclipse --verbose --board STM32F429I-Discovery --mcu STM32F429ZI -serial COM3 --image hello_rtos.elf --semihosting-config enable
putty连接COM4,可以看到写串口输出的AAAA……,一旦输入任何字符,写串口终止。
第一个问题:请问如何实现读和写串口。
第二个问题:采用半主机模式,但printf信息没有输出到串口。这个是怎么回事呢。
谢谢!
main.c如下:
[C] 纯文本查看 复制代码 #include "stm32f4xx.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "stdio.h"
// 定义消息队列大小
#define QUEUE_LENGTH 10
// 消息数据结构
typedef struct
{
uint8_t data; // 字节数据
} MsgData;
// 声明一个消息队列句柄
QueueHandle_t xQueue;
// USART发送任务
void USART_SendTask(void *pvParameters)
{
MsgData msg;
msg.data = 'A';
while(1)
{
// 发送字节 'A'
while(!(USART1->SR & USART_SR_TXE)); // 等待发送缓冲区为空
USART1->DR = msg.data;
xQueueReceive(xQueue, &msg, 0); // 尝试接收消息,等待时间为0
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时1秒
}
}
// USART接收任务
void USART_ReceiveTask(void *pvParameters)
{
MsgData msg;
while(1)
{
if (USART1->SR & USART_SR_RXNE) // 检查接收缓冲区是否非空
{
uint8_t data = USART1->DR; // 读取接收到的字节
//if (data == 'B')
{
// 执行接收到的指令
// 例如,打印一条消息
//printf("Received 'B'\n");
// 发送消息给发送任务
msg.data = 'B';
xQueueSend(xQueue, &msg, 0);
}
}
vTaskDelay(pdMS_TO_TICKS(100)); // 延时100毫秒
}
}
int main(void)
{
// 初始化硬件
// 创建一个消息队列
xQueue = xQueueCreate(QUEUE_LENGTH, sizeof(MsgData));
// 使能USART1和GPIOA的时钟
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
// 配置 GPIOA 的引脚 PA9 为复用推挽输出模式(TX)
// 配置 GPIOA 的引脚 PA10 为浮空输入模式(RX)
GPIOA->MODER |= GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_0;
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9;
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9; // 设置引脚速度为高速
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPDR9;
GPIOA->PUPDR |= GPIO_PUPDR_PUPDR10_0;
// 配置 USART1
USART1->CR1 &= ~USART_CR1_UE; // 禁用 USART1
USART1->CR1 &= ~USART_CR1_M; // 8 位数据位(字长)
USART1->CR2 &= ~USART_CR2_STOP; // 1 位停止位
USART1->CR1 &= ~USART_CR1_PCE; // 无校验
USART1->CR1 &= ~USART_CR1_OVER8; // Oversampling 16
USART1->BRR = 0x1D4C; // 波特率 9600 @ 16MHz
USART1->CR1 |= USART_CR1_TE; // 使能发送
USART1->CR1 |= USART_CR1_RE; // 使能接收
USART1->CR1 |= USART_CR1_UE; // 使能 USART1
// 配置 USART1 的接收中断
NVIC_SetPriority(USART1_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
NVIC_EnableIRQ(USART1_IRQn);
USART1->CR1 |= USART_CR1_RXNEIE;
// 创建发送任务
xTaskCreate(USART_SendTask, "USART_SendTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
// 创建接收任务
xTaskCreate(USART_ReceiveTask, "USART_ReceiveTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);
// 启动任务调度器
vTaskStartScheduler();
while (1)
{
// 此处添加程序逻辑
}
}
void vApplicationStackOverflowHook(TaskHandle_t xTask,
char *pcTaskName)
{
// 空实现,可以在此处添加堆栈溢出时的处理逻辑
}
void vApplicationMallocFailedHook(void)
{
// 空实现,可以在此处添加内存分配失败时的处理逻辑
}
void vApplicationTickHook(void)
{
// 空实现,可以在此处添加每个时钟节拍(tick)时的处理逻辑
}
void vApplicationIdleHook(void)
{
// 空实现,可以在此处添加空闲任务处理逻辑
}
Makefile内容如下:
[C] 纯文本查看 复制代码 # GNU ARM Embedded Toolchain
CC=arm-none-eabi-gcc
LD=arm-none-eabi-ld
AR=arm-none-eabi-ar
AS=arm-none-eabi-as
CP=arm-none-eabi-objcopy
OD=arm-none-eabi-objdump
# Build Parameters: MCU Flags, Definitions, Includes,
# Compile Flags, Linker Script, Linker Flags
MCFLAGS=-mcpu=cortex-m4 -mthumb -mlittle-endian \
-mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb-interwork
DEFS=-DUSE_STDPERIPH_DRIVER -DSTM32F4XX
INCLUDES=-I. \
-I../../Libraries/CMSIS/Device/ST/STM32F4xx/Include \
-I../../Utilities/STM32F429I-Discovery \
-I../../Libraries/CMSIS/Include \
-I../../Libraries/STM32F4xx_StdPeriph_Driver/inc \
-I../../FreeRTOS/Source/portable/GCC/ARM_CM3 \
-I../../FreeRTOS/Source/include \
-I../../TraceRecorder/include
CFLAGS=-c $(MCFLAGS) $(DEFS) $(INCLUDES)
LDSCRIPT = ./stm32_flash.ld
LDFLAGS=-T $(LDSCRIPT) --specs=nosys.specs $(MCFLAGS)
# Inputs: C Sources, Assembler Sources
SOURCES=main.c stm32f4xx_it.c system_stm32f4xx.c \
../../Utilities/STM32F429I-Discovery/stm32f429i_discovery.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_syscfg.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/misc.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_gpio.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_rcc.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_exti.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_i2c.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_dma.c \
../../Libraries/STM32F4xx_StdPeriph_Driver/src/stm32f4xx_usart.c \
../../FreeRTOS/Source/portable/GCC/ARM_CM3/port.c \
../../FreeRTOS/Source/portable/MemMang/heap_2.c \
../../FreeRTOS/Source/croutine.c \
../../FreeRTOS/Source/event_groups.c \
../../FreeRTOS/Source/list.c \
../../FreeRTOS/Source/queue.c \
../../FreeRTOS/Source/tasks.c \
../../FreeRTOS/Source/timers.c \
../../TraceRecorder/trcKernelPort.c \
../../TraceRecorder/trcSnapshotRecorder.c \
../../TraceRecorder/trcStreamingRecorder.c
ASMSOURCES=../../Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc_ride7/startup_stm32f429_439xx.s
# Outputs: Object Files, ELF Executable &
# Converted ELF Executable to Intel HEX format
OBJECTS=$(SOURCES:%.c=%.o)
OBJECTS+=$(ASMSOURCES:%.s=%.o)
EXECUTABLE=hello_rtos.elf
TARGET=hello_rtos.hex
# Build Rules
.PHONY: release
release: $(TARGET)
.PHONY: all
all: $(TARGET)
.PHONY: debug
debug: CFLAGS+=-g # Add debug flag
debug: LDFLAGS+=-g
debug: $(TARGET)
$(TARGET): $(EXECUTABLE)
$(CP) -O ihex $< $@
@echo "Objcopy from ELF to IHEX complete!\n"
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
@echo "Linking complete!\n"
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
@echo "Compiled "$<"!\n"
%.o: %.s
$(CC) $(CFLAGS) $< -o $@
@echo "Assambled "$<"!\n"
.PHONY: clean
clean:
rm -f $(OBJECTS) $(EXECUTABLE) $(TARGET)
|