1 freertos移植主要参考以下这篇文章
https://www.freesion.com/article/41971435876/
2 GD32F450+LAN8720A,#FreeRTOS_Plus_TCP 网络协议栈移植教程
https://blog.csdn.net/weixin_45775305/article/details/128643872
注意: 移植的时候注意phy地址是否和文中的一样。
3 基于串口ymodem的iap的程序升级主要参考以下这篇文章
【开源】串口YMODEM实现IAP程序升级(附工程源码)
【开源】串口YMODEM实现IAP程序升级(附工程源码)_ymodem工具_freemote的博客-CSDN博客
相较于原作者修改的地方在
(1)
(2)使用gd32f450的flash的读写接口GDFLASH_Write(); flash的具体读写代码参考
立创梁山派GD32F450ZGT6--内部FLASH的读写_gd32f4 fmc_老怪.的博客-CSDN博客
4 基于tcp的iap的升级程序
首先要保证第2步骤中能ping通
tcp iap程序较大,故bootloader rom设置大一些,如图
主要关键代码如下:
实现了一个tcp服务器模型,ip 192.168.1.11,端口8088 ,打开一个网口调试助手,设置tcp client,5s内连接该tcp服务器,5s后,tcp server端若没有客户端链接,直接执行iap_load_app,跳转执行app,然后发送要烧写app的bin文件,发送完成后,发送 字符串 "send ok",tcp server端收到send ok,开始跳转,执行app程序,
#include "main.h"
#include "trng.h"
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "flash.h"
uint8_t ucMACAddress[ 6 ] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };
uint8_t ucIPAddress[ 4 ] = { configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 };
uint8_t ucNetMask[ 4 ] = { configNET_MASK0, configNET_MASK1, configNET_MASK2, configNET_MASK3 };
uint8_t ucGatewayAddress[ 4 ] = { configGATEWAY_ADDR0, configGATEWAY_ADDR1, configGATEWAY_ADDR2, configGATEWAY_ADDR3 };
uint8_t ucDNSServerAddress[ 4 ] = { configDNS_SERVER_ADDR0, configDNS_SERVER_ADDR1, configDNS_SERVER_ADDR2, configDNS_SERVER_ADDR3 };
//#define BOOT_REC_LEN 256*1024 //定义最大接收字节数
#define FLASH_APP1_ADDR 0x08080000
//uint8_t BOOT_RX_BUF[BOOT_REC_LEN] __attribute__ ((at(0X20021000)));//接收缓冲
uint32_t FlashDestination = FLASH_APP1_ADDR; /* Flash user program offset */
typedef void (*pAppFunction) (void);
pAppFunction application;
uint32_t iapbuf[512]; //2K字节缓存
void usart0_init(void);
void Delay (uint32_t count)
{
uint32_t i,t;
for (i=count;i>0;i--)
{
for(t=10000;t>0;t--);
}
}
uint32_t app_address;
void iap_load_app(uint32_t appxaddr)
{
if (((*(__IO uint32_t*)FLASH_APP1_ADDR) & 0x2FFE0000) == 0x20000000) {
app_address = *(__IO uint32_t*) (FLASH_APP1_ADDR + 4);
application = (pAppFunction) app_address;
__set_MSP(*(__IO uint32_t*) FLASH_APP1_ADDR);
application();
}
}
void jumpToApp(void)
{
// USART_Cmd(USART6, DISABLE);//--__disable_irq()只是禁止CPU去响应中断,没有真正的去屏蔽中断的触发,
// TIM_Cmd(TIM3, DISABLE);
if(((*(uint32_t*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
{
__disable_irq();
__set_FAULTMASK(1);//关闭所有中断
iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
}
}
//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin(uint32_t appxaddr,uint8_t *appbuf,uint32_t appsize)
{
uint32_t t;
uint16_t i=0;
uint32_t temp;
uint32_t fwaddr=appxaddr;//当前写入的地址
uint8_t *dfu=appbuf;
for(t=0;t<appsize;t+=4)
{
temp=(uint32_t)dfu[3]<<24;
temp|=(uint32_t)dfu[2]<<16;
temp|=(uint32_t)dfu[1]<<8;
temp|=(uint32_t)dfu[0];
dfu+=4;//偏移4个字节
iapbuf[i++]=temp;
if(i==512)
{
i=0;
GDFLASH_Write(fwaddr,iapbuf,512);
fwaddr+=2048;//偏移2048 512*4=2048
}
}
if(i)GDFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.
}
/* The maximum time to wait for a closing socket to close. */
#define tcpechoSHUTDOWN_DELAY ( pdMS_TO_TICKS( 5000 ) )
// 服务器监听端口
#define tcpechoPORT_NUMBER 8088
uint16_t acceptTaskSize;
#if 1
static void vAcceptConnectionTask(void *parameters)
{
int32_t lBytes, lSent, lTotalSent,packet_size ;
Socket_t xConnectedSocket;
//static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 1000*5 );
static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 1000 );
TickType_t xTimeOnShutdown;
uint8_t *pucRxBuffer = NULL;
uint32_t tmp=0;
char cflag[]="send ok";
xConnectedSocket = ( Socket_t ) parameters;
//pucRxBuffer = ( uint8_t * ) pvPortMalloc( ipconfigTCP_MSS );
static const TickType_t xReceiveTimeOut = portMAX_DELAY;
pucRxBuffer = ( uint8_t * ) pvPortMalloc( 110 );
if(pucRxBuffer != NULL)
{
FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
FreeRTOS_setsockopt( xConnectedSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xReceiveTimeOut ) );
for( ;; )
{
/* Zero out the receive array so there is NULL at the end of the string
when it is printed out. */
//memset( pucRxBuffer, 0x00, ipconfigTCP_MSS );
memset( pucRxBuffer, 0x00, 110 );
/* Receive data on the socket. */
//lBytes = FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 );
lBytes = FreeRTOS_recv( xConnectedSocket, pucRxBuffer, 100, 0 );
/* If data was received, echo it back. */
if( lBytes > 0 )
{
//memcpy(&BOOT_RX_BUF[tmp],pucRxBuffer,lBytes);
tmp=tmp+lBytes;
//printf("receive lBytes is %d\n\r",lBytes);
//printf("receive tmp is %d\n\r",tmp);
//lSent = 0;
//lTotalSent = 0;
if(!memcmp(pucRxBuffer,cflag,7)){
printf("bin file receive is ok\n\r");
break;
}
packet_size = lBytes/4+((lBytes%4)?1:0);
GDFLASH_Write(FlashDestination,(unsigned int*)pucRxBuffer,packet_size);
FlashDestination+=lBytes;
}
else if(lBytes == 0 )
{
/* Socket closed? */
//printf("receive timeout\n\r");
printf("receive byte is %d\n\r",tmp);
break;
}
}
//iap_write_appbin(FLASH_APP1_ADDR,BOOT_RX_BUF,BOOT_REC_LEN);//更新FLASH代码
jumpToApp();
}
/* Initiate a shutdown in case it has not already been initiated. */
FreeRTOS_shutdown( xConnectedSocket, FREERTOS_SHUT_RDWR );
/* Wait for the shutdown to take effect, indicated by FreeRTOS_recv()
returning an error. */
xTimeOnShutdown = xTaskGetTickCount();
do
{
if( FreeRTOS_recv( xConnectedSocket, pucRxBuffer, ipconfigTCP_MSS, 0 ) < 0 )
{
break;
}
} while( ( xTaskGetTickCount() - xTimeOnShutdown ) < tcpechoSHUTDOWN_DELAY );
/* Finished with the socket, buffer, the task. */
vPortFree( pucRxBuffer );
FreeRTOS_closesocket( xConnectedSocket );
vTaskDelete( NULL );
}
static void vListeningConnectionTask(void *parameters)
{
//printf("into vListeningConnectionTask\n\r");
struct freertos_sockaddr xClient, xBindAddress;
Socket_t xListeningSocket, xConnectedSocket;
socklen_t xSize = sizeof( xClient );
//static const TickType_t xReceiveTimeOut = portMAX_DELAY;
static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 1000*5 );
const BaseType_t xBacklog = 20;
xListeningSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
configASSERT( xListeningSocket != FREERTOS_INVALID_SOCKET );
FreeRTOS_setsockopt( xListeningSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
xBindAddress.sin_port = tcpechoPORT_NUMBER;
xBindAddress.sin_port = FreeRTOS_htons( xBindAddress.sin_port );
FreeRTOS_bind( xListeningSocket, &xBindAddress, sizeof( xBindAddress ) );
FreeRTOS_listen( xListeningSocket, xBacklog );
//while(1)
{
xConnectedSocket = FreeRTOS_accept( xListeningSocket, &xClient, &xSize );
configASSERT( xConnectedSocket != FREERTOS_INVALID_SOCKET );
if(xConnectedSocket==NULL){
printf("FreeRTOS_accept 5s timeout\n\r");
jumpToApp();
}
printf("have client connect,start receive bin files\n\r");
//xTaskCreate( vAcceptConnectionTask, "ClientInstance", acceptTaskSize, ( void * ) xConnectedSocket, tskIDLE_PRIORITY, NULL );
vAcceptConnectionTask(( void * ) xConnectedSocket);
}
//while(1);
}
void vStartTCPServerTask(uint16_t taskSize, UBaseType_t priority)
{
//printf("create TCPServerTask\n\r");
xTaskCreate(vListeningConnectionTask, "TCPServerTask", taskSize, NULL, priority, NULL);
acceptTaskSize = taskSize;
}
#endif
void start_task(void * pvParameters)
{
printf("hello\r\n");
while (1)
{
vTaskDelay(1000);
}
}
void enet_inti_task(void * pvParameters)
{
//printf("into enet_inti_task\n\r");
trng_init(); //初始化随机数发生器,在FreeRTOS_IPInit之前
FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress ); /* 初始化网络栈*/
vTaskDelete(NULL);
}
int main(void)
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
//uart0_init(115200);
usart0_init();
//printf("\n\rUSART printf example1112\n\r");
xTaskCreate(enet_inti_task , "enet_inti_task" , 128, NULL , 12 , NULL);
xTaskCreate(start_task , "start_task" , 128, NULL , 10 , NULL);
vStartTCPServerTask(128,8);
vTaskStartScheduler();
while(1)
{
printf("freertos error\r\n");
}
}
void usart0_init(void)
{
rcu_periph_clock_enable( RCU_GPIOA);
/* enable USART clock */
rcu_periph_clock_enable(RCU_USART0);
/* connect port to USARTx_Tx */
gpio_af_set(GPIOA,GPIO_AF_7, GPIO_PIN_9);
/* connect port to USARTx_Rx */
gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);
/* configure USART Tx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_9);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_9);
/* configure USART Rx as alternate function push-pull */
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_10);
/* USART configure */
usart_deinit(USART0);
usart_baudrate_set(USART0,115200U);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_enable(USART0);
}
int fgetc(FILE *f)
{
/* ???????? */
while (!usart_flag_get(USART0, USART_FLAG_RBNE));
return (int)usart_data_receive(USART0);
}