你好,我现在貌似可以跳转了,但是跳转 后,用户的 app 程序不能够运行,但是如果使用 jlink 直接下载用户 app 程序到板子里面是可以正常运行的, iap 程序如下: #define USER_FLASH_FIRST_PAGE_ADDRESS 0x08080000 void Jump_To_APP(void) { __set_PRIMASK(1);// 关闭全局中断。注意,在跳转前,必须先关闭全局中断,进入用户程序后,在中断向量表地址设置完成后再开中断。 // 通过判断栈顶地址值是否正确来判断是否已经下载用户应用程序。因为用户程序的启动文件开始会初始化栈空间,如果栈顶地址正确,说明用户程序已经下载 // __ASM("CPSID I"); printf("Jump to the new program.\r\n"); JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);// 前4字节为中断向量表 Jump_To_Application = (pFunction) JumpAddress;// 指向用户程序复位函数所在的地址 //设置APP程序堆栈指针 __set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS); // 设置用户程序的栈指针,程序貌似在这个地方执行后就没有返回,???? Jump_To_Application(); // 执行用户程序 } 用户app 设置如下: 用户 app 程序是带 FreeRTOS 的,不过我的 FreeRTOS 系统是在我所以的 外设初始化完成后才启动的 下面这个是 map 文件,程序入口地址貌似也是对的吧 ?? 我使用的是 iar |
目前使用 http 更新程序已经搞定啦 ,多谢多谢啊,
但是使用 tftp 不行,不知道是不是我的 tftp 使用的版本不对呀 ?
我目前使用 tftpd32.452,tftpd64.400 这两个版本的都试过了不行,具体如下:
/**
* @brief Processes traffic received on UDP port 69
* @param args: pointer on tftp_connection arguments
* @param upcb: pointer on udp_pcb structure
* @param pbuf: pointer on packet buffer
* @param addr: pointer on the receive IP address
* @param port: receive port number
* @retval None
*/
static void IAP_tftp_recv_callback(void *arg, struct udp_pcb *upcb, struct pbuf *pkt_buf,
const ip_addr_t *addr, u16_t port)
{
tftp_opcode op;
struct udp_pcb *upcb_tftp_data;
err_t err;
uint32_t i;
char filename[40],message[40], *ptr;
/* create new UDP PCB structure */
upcb_tftp_data = udp_new();
if (!upcb_tftp_data)
{
/* Error creating PCB. Out of Memory */
printf("Can not create pcb 1\r\n");
__LTDC_drv->LTDC_DispStringAt(12, 180,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)"Can not create pcb 1");
return;
}
/* bind to port 0 to receive next available free port */
/* NOTE: This is how TFTP works. There is a UDP PCB for the standard port
* 69 which al transactions begin communication on, however, _all_ subsequent
* transactions for a given "stream" occur on another port */
err = udp_bind(upcb_tftp_data, IP_ADDR_ANY, 0);
if (err != ERR_OK)
{
/* Unable to bind to port */
printf("Can not create pcb 2\r\n");
__LTDC_drv->LTDC_DispStringAt(12, 200,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)"Can not create pcb 2");
return;
}
op = IAP_tftp_decode_op(pkt_buf->payload);
if (op != TFTP_WRQ)
{
/* remove PCB */
printf("Bad TFTP opcode \r\n"); // 错误就在这里, ?????????????????
__LTDC_drv->LTDC_DispStringAt(12, 200,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)"Bad TFTP opcode");
udp_remove(upcb_tftp_data);
}
else
{
//#ifdef USE_LCD
ptr = pkt_buf->payload;
ptr = ptr +2;
// extract file name info
i= 0;
while (*(ptr+i)!=0x0)
{
i++;
}
strncpy(filename, ptr, i+1);
printf("IAP using TFTP \r\n");
__LTDC_drv->LTDC_DispStringAt(12, 220,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)"IAP using TFTP");
sprintf(message, "File: %s",filename);
// LCD_UsrLog("%s\n", message);
printf("State: Erasing...\r\n");
__LTDC_drv->LTDC_DispStringAt(12, 240,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)message);
__LTDC_drv->LTDC_DispStringAt(12, 260,
LCD_COLOR_RED,
LCD_COLOR_TRANSPARENT,
&FontAscii8x16,
(const uint8_t *)"State: Erasing...");
//#endif
// Start the TFTP write mode
IAP_tftp_process_write(upcb_tftp_data, addr, port);
}
pbuf_free(pkt_buf);
}
评分
查看全部评分
现在可以实现 app 无系统的程序跳转了,带系统的程序跳转貌似还是不行,
在 iap 程序跳转前,需要关闭
void Jump_To_APP(void)
{
//检测APP地址是否合法
printf("\r\n_______ *** *** Jump to the new program run please ... *** ***_______\r\n\r\n");
// 判断栈顶地址是否在0x2000 0000 - 0x2000 2000之间,这个判断也可以使用,完全木有任何问题的
if (((*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS ) & 0x2FFE0000 ) == 0x20000000)
{
// 通过判断栈顶地址值是否正确来判断是否已经下载用户应用程序。因为用户程序的启动文件开始会初始化栈空间,如果栈顶地址正确,说明用户程序已经下载
// __ASM("CPSID I");
// Jump to user application
JumpAddress = *(__IO uint32_t*) (USER_FLASH_FIRST_PAGE_ADDRESS + 4);// 前4字节为中断向量表
Jump_To_Application = (pFunction) JumpAddress;// 指向用户程序复位函数所在的地址
// 关闭所有外设中断
HAL_NVIC_DisableIRQ(ETH_IRQn);
HAL_NVIC_DisableIRQ(USART1_IRQn); //关闭串口中断
HAL_NVIC_DisableIRQ(SD_IRQn);
HAL_NVIC_DisableIRQ(SD_DMAx_Rx_IRQn);
HAL_NVIC_DisableIRQ(SD_DMAx_Tx_IRQn);
PWM_Stop();
HAL_FLASH_Lock();
__disable_irq(); //关闭总中断
{
/*
Reset of all peripherals
这些外设关闭非常重要,否则不能够正常实现程序跳转功能,切记切记
*/
__APB1_FORCE_RESET();
__APB1_RELEASE_RESET();
__APB2_FORCE_RESET();
__APB2_RELEASE_RESET();
__AHB1_FORCE_RESET();
__AHB1_RELEASE_RESET();
__AHB2_FORCE_RESET();
__AHB2_RELEASE_RESET();
__AHB3_FORCE_RESET();
__AHB3_RELEASE_RESET();
HAL_RCC_DeInit();
}
__set_PSP(*(volatile uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS);
__set_CONTROL(0);
//设置APP程序堆栈指针
__set_MSP(*(__IO uint32_t*) USER_FLASH_FIRST_PAGE_ADDRESS); // 设置用户程序的栈指针
__set_CONTROL(0);
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; // 关闭滴答定时器中断
SysTick->VAL = 0;
SysTick->LOAD = 0;
Jump_To_Application(); // 执行用户程序
}
else
{
printf("jump uaer app run error ??\r\n");
for(;;)
{}
}
}
现在 app 程序带 系统的,跳转会失败,还需要关闭哪些 功能啊 ????????
你确定你在下载IAP时,没有把APP区也擦了吧?从上面没看出问题。
评分
查看全部评分
评分
查看全部评分
我的是 2MB的 flash , 现在 iap 大小为300KB 以内的,但是 查看 stm32f777BIT6 的flash 分配,只能是 512KB的空间了,
下载 iap 程序时,app的空间是没有被擦除的,iap的地址范围设置的 0x0800 0000 - 0x0807 ffff
我已经在程序跳转前关闭了所以的中段啊
__set_PRIMASK(1); 关闭所以中断, 不知道这个方法在 iar 编译器里面是否适用啊 ???
你好,断电后重新上电,首先会进入到 iap 程序,之后再跳转到 app的,但是跳转 后app 还是不能够运行的
我的 app 单独使用 jlink 下载后可以正常运行的,断电后 程序也会进入到 iap 程序段运行,之后再跳转到 app ,但是再跳转到 app 后,app 的程序还是不能够运行,我 的 app 程序使用了 freertos ,跟这个有没有什么关系呀 ?
评分
查看全部评分
我以前使用 sd 卡更新固件是没有问题的,
感觉这个才是问题关键,楼主的现象应该是在跑APP的时候产生了中断,而此时的中断向量还是IAP的,所以导致执行IAP的中断例程,从而导致APP挂掉,目前这个只是猜测,楼主试下就知道结果了。
评分
查看全部评分
你好,现在最新进展情况,
貌似执行了第 52 行的代码后就出现 什么 The stack pointer for stack 'CSTACK' (currently 0x20022CD8) is outside the stack range (0x200003B0 to 0x200043B0)
这个是怎么回事啊 ???????????
是不是我 的 iap 程序分的太大了啊 ? 我目前分配的是 256KB/512KB 结果也得是一样的不行
程序擦除函数如下:
int8_t FLASH_If_Erase(uint32_t StartSector)
{
uint32_t FlashAddress;
FlashAddress = StartSector;
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
be done by word */
if (FlashAddress <= (uint32_t) USER_FLASH_LAST_PAGE_ADDRESS)
{
FLASH_EraseInitTypeDef FLASH_EraseInitStruct;
uint32_t sectornb = 0;
FLASH_EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
FLASH_EraseInitStruct.Sector = FLASH_SECTOR_5; // 单片机是2MBflash大小
//前面的256KB留给bootloader使用,所以
//此处是扇区5开始
FLASH_EraseInitStruct.NbSectors = FLASH_SECTOR_11 - FLASH_SECTOR_5 + 1;
FLASH_EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
if (HAL_FLASHEx_Erase(&FLASH_EraseInitStruct, §ornb) != HAL_OK)
return (1);
}
else
{
return (1);
}
return (0);
}
扇区分配如下: