GD32或STM32(GD32F103RB)Ymodem串口升级源码分析

2024-01-03 12:46:08

先看GD32或STM32(GD32F103RB)用Ymodem升级-CSDN博客

首先了解下串口的使用,看以下代码:(代码进行过删减,主要用作理解步骤使用)

初始化串口,这里没有开启任何关于串口的中断(串口的idle空闲标记也仅是查询是否置位);

使能串口的DMA接收,同样也没有开DMA中断;

着重介绍一下UART_RecvData函数的使用,该函数是用了DMA,代码上以查询的方式获取串口数据,主要步骤如下:(每次需要调用该函数时,都会执行以下,请结合下面代码看以下文字)

1 设置DMA的帧数据长度dma_transfer_number_config:如果调用函数传递的len=-1,则USART1_RX_BUF_SIZE为1029,否则设置的长度就是len;(可能会有疑问?每次都有1029数据传递么(3帧头+1024+2CRC),Ymodem不是还有128的帧么);我理解这里帧长度,只是说收完这么长的一帧之后,一定会触发相应的标记或者中断;但是,如果实际上收到的帧长度没有那么长,也同样会有相应的标记或中断被触发。例如DMA的DMA_FLAG_FTF,传输完成标记;

2 while等待串口的USART_FLAG_IDLE空闲标记:该标记置位的条件是,收完一帧数据,或者收完一段数据后停止了一段时间(根据代码现象,我理解是这样,但是我没有仔细去查阅);UART_RecvData函数超时后,根据调试现象(容易接收失败),UART_SendChar(YMODEM_COM, 0x15, timeout);添加这条NAK 0x15的应答,我理解上位机收到后这条会重发该帧。

这里再说下USART_FLAG_IDLE这个标记怎么清除:软件先读USART_STAT,再读USART_DATA可清除该位。(没有找到有清除它的函数);

3 拷贝DMA的buf的内容。

static void HardwareInit(void) {
    UART_UserInit(YMODEM_COM, 115200);
    UART1_UserDMAInit();
}


void UART_UserInit(uint32_t usartPeriph, uint32_t baud) {
	uint32_t com_id = 0U;

	switch(usartPeriph) {
	case USER_COM0:
		com_id = 0U;
		break;

	case USER_COM1:
		com_id = 1U;
		break;

	case USER_COM2:
		com_id = 2U;
		break;

	case USER_COM3:
		com_id = 3U;
		break;
	}

	/* enable GPIO clock */
	rcu_periph_clock_enable(COM_TX_CLK[com_id]);
	rcu_periph_clock_enable(COM_RX_CLK[com_id]);

	/* enable USART clock */
	rcu_periph_clock_enable(COM_CLK[com_id]);

	/* connect port to USARTx_Tx */
	gpio_init(COM_TX_PORT[com_id], GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_TX_PIN[com_id]);

	/* connect port to USARTx_Rx */
	gpio_init(COM_RX_PORT[com_id], GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, COM_RX_PIN[com_id]);

	/* 

文章来源:https://blog.csdn.net/weixin_39257775/article/details/135336963
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。