Dark0711 0 30 июня, 2014 Опубликовано 30 июня, 2014 · Жалоба Всем привет! Нужна помошь, никак не могу разобраться. Решил Я написать свой bootloader, и разместил его в конце флеша. Основная программа вызываеть его когда хочет обновиться. Сделал, все залил. Бутлодер грузиться, находит файл прошивки и должен запихать ее с нолевого адреса флеша. Но при записи(256 512 байит или более)портиться первый две или три пачки, пишиться какаято чушь, а далее все как положено записываеться.Сектора флеша форматирую перед записью. Может кто сталкивался с проблемой??? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 30 июня, 2014 Опубликовано 30 июня, 2014 · Жалоба 1. Лучше наоборот сделать%) Бутлоадер в начало положить, а прошивку боевую ближе к концу. Стартуете с бутлоадера, он проверяет прошивку боевую (целостность и прочее), если все ок переходит к ней,если нет ждет новую. Ну не важно... 2. Была такая фигня (на 1768, но они близнецы братья как понимаю) , нужно запрещать прерывания, если брали стандартные примеры, то там есть запреты, но вместо них пустые заглушки, а иногда ваще нет запретов. А запреты ОЧЕНЬ строго нужны. Даже таймер может сбивать процесс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба 1. Лучше наоборот сделать%) Бутлоадер в начало положить, а прошивку боевую ближе к концу. Стартуете с бутлоадера, он проверяет прошивку боевую (целостность и прочее), если все ок переходит к ней,если нет ждет новую. Идея была в том, что бутлодел заливает прошивку и просто ресетит микроконтроллер и он весело стартует с новой прошивкой 2. Была такая фигня (на 1768, но они близнецы братья как понимаю) , нужно запрещать прерывания, если брали стандартные примеры, то там есть запреты, но вместо них пустые заглушки, а иногда ваще нет запретов. А запреты ОЧЕНЬ строго нужны. Даже таймер может сбивать процесс. Прерывания отрубаю, таблицы векторов перемешаю. В errata вычитал что нужно в Pboost тройку вставить и в Matrix arb еденицу в бит rom lat, не помогло ! Как Я понял из errata что еще частоту можно понизить и типо все пучком будет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Почему не работает, не знаю, но прокомментирую саму реализацию. Размещать бутлоадер в конце вполне разумно, у меня так же сделано. Но идея вызывать загрузчик из приложения не очень хорошая. Тут многие сталкивались с проблемами при таком подходе и в итоге переходили к другой схеме: сначала всегда стартует загрузчик и проверяет, нужно ли обновлять приложение или стартовать имеющееся. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Почему не работает, не знаю, но прокомментирую саму реализацию. Размещать бутлоадер в конце вполне разумно, у меня так же сделано. Но идея вызывать загрузчик из приложения не очень хорошая. Тут многие сталкивались с проблемами при таком подходе и в итоге переходили к другой схеме: сначала всегда стартует загрузчик и проверяет, нужно ли обновлять приложение или стартовать имеющееся. Вот скорей всего так и буду делать, размешать в начале и проверять есть чего или нет. А причина почему вызываю загрузчик из приложения, что бы уменьшить код загрузчика. В основном приложении гружу прошивку в SDRAM через USB, прыгаю на загрузчик, на всё готовое, инициализированное =). И просто копирую с SDRAM в буфер в RAMe, кусочками по 256 байт и пишу во флеш. Просто обидно, хочется разобрать в причинах нестабильной работе IAP, а то он так в середине флеша напишет мне лабуду, а Я потом буду гадать, чего это основная программа падает. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Ну потому обычно и грузят загрузчик первым, он проверяет контрольную сумму прошивки, и если что не переходит на нее. В вашей же схеме залей вы кривую программу (в момент переписывания из рам во флэш), после ресета проц превратиться в кирпич. Естественно после записи программы во флэш ее стоит проверить, что записалось именно то что хотели, но стремление 100% записи понятно. А таймауты все выдерживаются, на стирание страниц и так далее? вот у меня такой IAP, это LPCешный, с некоторыми правками, в частности переделаны макросы запрета прерывания /***************************************************************************** * $Id$ * * Project: NXP LPC1700 Secondary Bootloader Example * * Description: Provides access to In-Application Programming (IAP) routines * contained within the bootROM sector of LPC1100 devices. * * Copyright© 2010, NXP Semiconductor * All rights reserved. * ***************************************************************************** * Software that is described herein is for illustrative purposes only * which provides customers with programming information regarding the * products. This software is supplied "AS IS" without any warranties. * NXP Semiconductors assumes no responsibility or liability for the * use of the software, conveys no license or title under any patent, * copyright, or mask work right to the product. NXP Semiconductors * reserves the right to make changes in the software without * notification. NXP Semiconductors also make no representation or * warranty that such application will be suitable for the specified * use without further testing or modification. *****************************************************************************/ #include "IAP.h" #include <LPC17xx.h> #include <string.h> /* IAP Command Definitions */ #define IAP_CMD_PREPARE_SECTORS 50 #define IAP_CMD_COPY_RAM_TO_FLASH 51 #define IAP_CMD_ERASE_SECTORS 52 #define IAP_CMD_BLANK_CHECK_SECTORS 53 #define IAP_CMD_READ_PART_ID 54 #define IAP_CMD_READ_BOOT_ROM_VERSION 55 #define IAP_CMD_COMPARE 56 #define IAP_CMD_REINVOKE_ISP 57 #define IAP_CMD_READ_SERIAL_NUMBER 58 /* IAP boot ROM location and access function */ #define IAP_ROM_LOCATION 0x1FFF1FF1UL #define IAP_EXECUTE_CMD(a, B) ((void (*)())(IAP_ROM_LOCATION))(a, B) //макрос запрета прерывания с сохранением статуса #define INTERRUPT_DISABLE_STORE(flag1, flag2) (flag1) = __disable_irq(); (flag2) = __disable_fiq() //макрос восстановления статуса прерывания #define INTERRUPT_RESTORE(flag1, flag2) if(!(flag1)) __enable_irq(); if(!(flag2)) __enable_fiq() /***************************************************************************** ** Function name: u32IAP_PrepareSectors ** ** Description: Prepares sector(s) for erasing or write operations. This ** command must be executed before executing the "Copy RAM to ** Flash" or "Erase Sector(s)" commands. ** ** Parameters: u32StartSector - Number of first sector to prepare. ** u32EndSector - Number of last sector to prepare. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_PrepareSectors(uint32_t u32StartSector, uint32_t u32EndSector) { uint32_t u32Status; uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_PREPARE_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; IAP_EXECUTE_CMD(au32Command, au32Result); u32Status = au32Result[0]; } INTERRUPT_RESTORE(IRQ, FIQ); return u32Status; } /***************************************************************************** ** Function name: u32IAP_CopyRAMToFlash ** ** Description: Program the flash memory with data stored in RAM. ** ** Parameters: u32DstAddr - Destination Flash address, should be a 256 ** byte boundary. ** u32SrcAddr - Source RAM address, should be a word boundary ** u32Len - Number of 8-bit bytes to write, must be 256 ** 512, 1024, or 4096. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_CopyRAMToFlash(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_COPY_RAM_TO_FLASH; au32Command[1] = u32DstAddr; au32Command[2] = u32SrcAddr; au32Command[3] = u32Len; au32Command[4] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ IAP_EXECUTE_CMD(au32Command, au32Result); INTERRUPT_RESTORE(IRQ, FIQ); return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_EraseSectors ** ** Description: Erase a sector or multiple sectors of on-chip Flash memory. ** ** Parameters: u32StartSector - Number of first sector to erase. ** u32EndSector - Number of last sector to erase. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_EraseSectors(uint32_t u32StartSector, uint32_t u32EndSector) { uint32_t u32Status; uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_ERASE_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; au32Command[3] = SystemCoreClock / 1000UL; /* Core clock frequency in kHz */ IAP_EXECUTE_CMD(au32Command, au32Result); u32Status = au32Result[0]; } INTERRUPT_RESTORE(IRQ, FIQ); return u32Status; } /***************************************************************************** ** Function name: u32IAP_BlankCheckSectors ** ** Description: Blank check a sector or multiple sectors of on-chip flash ** memory. ** ** Parameters: u32StartSector - Number of first sector to check. ** u32EndSector - Number of last sector to check. ** pu32Result[0] - Offset of the first non blank word location ** if the Status Code is IAP_STA_SECTOR_NOT_BLANK. ** pu32Result[1] - Contents of non blank word location. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_BlankCheckSectors(uint32_t u32StartSector, uint32_t u32EndSector, uint32_t *pu32Result) { uint32_t u32Status; uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); if (u32EndSector < u32StartSector) { u32Status = IAP_STA_INVALD_PARAM; } else { au32Command[0] = IAP_CMD_BLANK_CHECK_SECTORS; au32Command[1] = u32StartSector; au32Command[2] = u32EndSector; IAP_EXECUTE_CMD(au32Command, au32Result); if (au32Result[0] == IAP_STA_SECTOR_NOT_BLANK) { *pu32Result = au32Result[0]; *(pu32Result + 1) = au32Result[1]; } u32Status = au32Result[0]; } INTERRUPT_RESTORE(IRQ, FIQ); return u32Status; } /***************************************************************************** ** Function name: u32IAP_ReadPartID ** ** Description: Read the part identification number. ** ** Parameters: pu32PartID - Pointer to storage for part ID number. * ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_ReadPartID(uint32_t *pu32PartID) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_READ_PART_ID; IAP_EXECUTE_CMD(au32Command, au32Result); *pu32PartID = au32Result[1]; INTERRUPT_RESTORE(IRQ, FIQ); return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_ReadBootVersion ** ** Description: Read the boot code version number. ** ** Parameters: pu32Major - Major version number in ASCII format. ** pu32Minor - Minor version number in ASCII format. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major, uint32_t *pu32Minor) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_READ_BOOT_ROM_VERSION; IAP_EXECUTE_CMD(au32Command, au32Result); *pu32Major = (au32Result[1] & 0x0000FF00UL) >> 8; *pu32Minor = au32Result[1] & 0x000000FFUL; INTERRUPT_RESTORE(IRQ, FIQ); return au32Result[0]; } /***************************************************************************** ** Function name: u32IAP_ReadBootVersion ** ** Description: Read the boot code version number. ** ** Parameters: pu32Major - Major version number in ASCII format. ** pu32Minor - Minor version number in ASCII format. ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ void u32IAP_ReadSerialNumber(uint32_t *pu32byte0, uint32_t *pu32byte1, uint32_t *pu32byte2, uint32_t *pu32byte3) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_READ_SERIAL_NUMBER; IAP_EXECUTE_CMD(au32Command, au32Result); *pu32byte0 = au32Result[0]; *pu32byte1 = au32Result[1]; *pu32byte2 = au32Result[2]; *pu32byte3 = au32Result[3]; INTERRUPT_RESTORE(IRQ, FIQ); return; } /***************************************************************************** ** Function name: u32IAP_Compare ** ** Description: Compares the memory contents at two locations. ** ** Parameters: u32Len - Number of bytes to compare, must be a multiple of 4. ** pu32Offset - Offset of the first mismatch if the Status Code is COMPARE_ERROR ** ** Returned value: Status code returned by IAP ROM function. ** ******************************************************************************/ uint32_t u32IAP_Compare(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t *pu32Offset) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_COMPARE; au32Command[1] = u32DstAddr; au32Command[2] = u32SrcAddr; au32Command[3] = u32Len; IAP_EXECUTE_CMD(au32Command, au32Result); if (au32Result[0] == IAP_STA_COMPARE_ERROR) { if (pu32Offset != 0) { *pu32Offset = au32Result[1]; } } INTERRUPT_RESTORE(IRQ, FIQ); return au32Result[0]; } /***************************************************************************** ** Function name: vIAP_ReinvokeISP ** ** Description: Invoke the bootloader in ISP mode. ** ** Parameters: None. * ** Returned value: None. ** ******************************************************************************/ void vIAP_ReinvokeISP(void) { uint32_t au32Result[5]; uint32_t au32Command[5]; uint32_t IRQ; uint32_t FIQ; INTERRUPT_DISABLE_STORE(IRQ, FIQ); au32Command[0] = IAP_CMD_REINVOKE_ISP; IAP_EXECUTE_CMD(au32Command, au32Result); INTERRUPT_RESTORE(IRQ, FIQ); } /***************************************************************************** ** End Of File *****************************************************************************/ и к нему вот такой файл с функциями вызова, он приложения зависимый, но я надеюсь вы разберетесь, кстати в нем я обнаружил еще коменты, что массивы которые в память перепихиваются должны быть выровнены по 32 бита, важный момент в работе с флэш. Сектора у меня стираются по командно и пишутся по блоков, так что между вызовами есть пауза порядка миллисекунды. /***************************************************************************** *****************************************************************************/ #include "IAP.h" #include "IntFlashRoutines.h" #include "dbg_cfg.h" #include "general.h" #include <LPC17xx.h> #include <string.h> const uint32_t sector_start_map[MAX_FLASH_SECTOR] = {SECTOR_0_START, \ SECTOR_1_START,SECTOR_2_START,SECTOR_3_START,SECTOR_4_START,SECTOR_5_START, \ SECTOR_6_START,SECTOR_7_START,SECTOR_8_START,SECTOR_9_START,SECTOR_10_START, \ SECTOR_11_START,SECTOR_12_START,SECTOR_13_START,SECTOR_14_START,SECTOR_15_START, \ SECTOR_16_START,SECTOR_17_START,SECTOR_18_START,SECTOR_19_START,SECTOR_20_START, \ SECTOR_21_START,SECTOR_22_START,SECTOR_23_START,SECTOR_24_START,SECTOR_25_START, \ SECTOR_26_START,SECTOR_27_START,SECTOR_28_START,SECTOR_29_START }; const uint32_t sector_end_map[MAX_FLASH_SECTOR] = {SECTOR_0_END,SECTOR_1_END, \ SECTOR_2_END,SECTOR_3_END,SECTOR_4_END,SECTOR_5_END,SECTOR_6_END,SECTOR_7_END, \ SECTOR_8_END,SECTOR_9_END,SECTOR_10_END,SECTOR_11_END,SECTOR_12_END, \ SECTOR_13_END,SECTOR_14_END,SECTOR_15_END,SECTOR_16_END,SECTOR_17_END, \ SECTOR_18_END,SECTOR_19_END,SECTOR_20_END,SECTOR_21_END,SECTOR_22_END, \ SECTOR_23_END,SECTOR_24_END,SECTOR_25_END,SECTOR_26_END, \ SECTOR_27_END,SECTOR_28_END,SECTOR_29_END }; //const unsigned crp __attribute__((section(".ARM.__at_0x2FC"))) = CRP; /***************************************************************************** ******************************************************************************/ //----------------------------------------------------------// #pragma inline void ReadCPUSerialNumber(uint32_t *pu32byte0, uint32_t *pu32byte1, uint32_t *pu32byte2, uint32_t *pu32byte3) { u32IAP_ReadSerialNumber(pu32byte0, pu32byte1, pu32byte2, pu32byte3); } //----------------------------------------------------------// #pragma inline uint32_t ReadCPUPartID(uint32_t *pu32PartID) { return(u32IAP_ReadPartID(pu32PartID)); } //----------------------------------------------------------// //----------------------------------------------------------// uint32_t WriteSettingsToFlash(uint8_t *data, uint16_t length) { uint32_t rez = 0; uint32_t i; //параметр цикла //массив для записи во флэш, выровненный по 32 бита, для записи блоками по 256 байт uint32_t AlignData[FLASH_BLOCK_SIZE / 4]; //нулевая длинна данных, ошибка if(length == 0) return 1000; /* Prepare Sectors to be flashed, erese them */ rez = EraseSettingsFlashSegment(); //стираем данные настроек if( rez != IAP_STA_CMD_SUCCESS) return rez; //возвращаем код ошибки //записываем и проверяем запись блоками for(i = 0; i < length; i += FLASH_BLOCK_SIZE) { //очищаем массив, чтобы хвост данных записался дополненный нулями memset(AlignData, 0, FLASH_BLOCK_SIZE); if((length - i) > FLASH_BLOCK_SIZE) //если данных больше чем на блок memcpy(AlignData, (data + i), FLASH_BLOCK_SIZE); //копируем целый блок else memcpy(AlignData, (data + i), (length - i)); //копируем только конец данных /* Prepare Sectors to be flashed */ rez = u32IAP_PrepareSectors(SETTINGS_DATA_SECTOR, SETTINGS_DATA_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE2_SECTOR_ERR+rez);//2000 /* Copy data (already) located in RAM to flash */ //размер данных в байтах, пишем целыми 256 байтными блоками rez = u32IAP_CopyRAMToFlash((SETTINGS_DATA_FLASH_START + i), (uint32_t)AlignData, FLASH_BLOCK_SIZE); if( rez != IAP_STA_CMD_SUCCESS) return (COPY_RAM_TO_FLASH_ERR+rez); //4000 /* Verify the flash contents with the contents in RAM */ //размер данных в байтах, проверяем целыми 256 байтными блоками rez = u32IAP_Compare((SETTINGS_DATA_FLASH_START + i), (uint32_t)AlignData, FLASH_BLOCK_SIZE, 0); if( rez != IAP_STA_CMD_SUCCESS) return (COMPARE_SECTOR_ERR+rez); //5000 } //возвращаем результат - все хорошо return rez; } /***************************************************************************** ******************************************************************************/ void ReadSettingsFromFlash( uint8_t * DstAddr, uint32_t nBytes) { memcpy( DstAddr, (uint8_t *)(SETTINGS_DATA_FLASH_START) , nBytes ); } /***************************************************************************** ******************************************************************************/ //----------------------------------------------------------// uint32_t EraseSettingsFlashSegment( void ) { uint32_t rez = 0; /* Prepare Sectors to be erased */ rez = u32IAP_PrepareSectors(SETTINGS_DATA_SECTOR, SETTINGS_DATA_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE1_SECTOR_ERR+rez); rez = u32IAP_EraseSectors(SETTINGS_DATA_SECTOR, SETTINGS_DATA_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (ERASE_SECTOR_ERR+rez); return rez; } //----------------------------------------------------------// //----------------------------------------------------------// uint32_t WriteEthSettingsToFlash(uint8_t *data, uint16_t length) { uint32_t rez = 0; uint32_t i; //параметр цикла //массив для записи во флэш, выровненный по 32 бита, для записи блоками по 256 байт uint32_t AlignData[FLASH_BLOCK_SIZE / 4]; //нулевая длинна данных, ошибка if(length == 0) return 1000; /* Prepare Sectors to be flashed */ rez = EraseEthSettingsFlashSegment(); //стираем данные настроек езернет if( rez != IAP_STA_CMD_SUCCESS) return rez; //возвращаем код ошибки //записываем и проверяем запись блоками for(i = 0; i < length; i += FLASH_BLOCK_SIZE) { //очищаем массив, чтобы хвост данных записался дополненный нулями memset(AlignData, 0, FLASH_BLOCK_SIZE); if((length - i) > FLASH_BLOCK_SIZE) //если данных больше чем на блок memcpy(AlignData, (data + i), FLASH_BLOCK_SIZE); //копируем целый блок else memcpy(AlignData, (data + i), (length - i)); //копируем только конец данных /* Prepare Sectors to be flashed */ rez = u32IAP_PrepareSectors(ETH_SETTINGS_SECTOR, ETH_SETTINGS_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE2_SECTOR_ERR+rez);//2000 /* Copy data (already) located in RAM to flash */ //размер данных в байтах, пишем целыми 256 байтными блоками rez = u32IAP_CopyRAMToFlash((ETH_SETTINGS_FLASH_START + i), (uint32_t)AlignData, FLASH_BLOCK_SIZE); if( rez != IAP_STA_CMD_SUCCESS) return (COPY_RAM_TO_FLASH_ERR+rez); //4000 /* Verify the flash contents with the contents in RAM */ //размер данных в байтах, проверяем целыми 256 байтными блоками rez = u32IAP_Compare((ETH_SETTINGS_FLASH_START + i), (uint32_t)AlignData, FLASH_BLOCK_SIZE, 0); if( rez != IAP_STA_CMD_SUCCESS) return (COMPARE_SECTOR_ERR+rez); //5000 } //возвращаем результат return rez; } /***************************************************************************** ******************************************************************************/ void ReadEthSettingsFromFlash( uint8_t * DstAddr, uint32_t nBytes) { memcpy( DstAddr, (uint8_t *)(ETH_SETTINGS_FLASH_START) , nBytes ); } /***************************************************************************** ******************************************************************************/ //----------------------------------------------------------// uint32_t EraseEthSettingsFlashSegment( void ) { uint32_t rez = 0; /* Prepare Sectors to be erased */ rez = u32IAP_PrepareSectors(ETH_SETTINGS_SECTOR, ETH_SETTINGS_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE1_SECTOR_ERR+rez); rez = u32IAP_EraseSectors(ETH_SETTINGS_SECTOR, ETH_SETTINGS_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (ERASE_SECTOR_ERR+rez); return rez; } //----------------------------------------------------------// //----------------------------------------------------------// uint32_t WriteUserDataToFlash(uint8_t sector_sellect, uint8_t block_sellect, uint8_t *data, uint16_t length) { uint32_t rez = 0; uint32_t AlignData[FLASH_BLOCK_SIZE / 4]; //буфер для 32 битного выравнивания данных для флэш if(sector_sellect >= USER_DATA_SIZE) return WRONG_SECTOR_SELLECT; //выходим с ошибкой if(block_sellect >= BLOCK_NUM_IN_SECTOR) return WRONG_BLOCK_SELLECT; //выходим с ошибкой if(length == 0) return 1000; //запись идет максимально 1 блоком, если данных больше, конец отбрасываем if(length > FLASH_BLOCK_SIZE) length = FLASH_BLOCK_SIZE; /* Prepare Sectors to be flashed */ rez = u32IAP_PrepareSectors((USER_DATA_SECTOR + sector_sellect), (USER_DATA_SECTOR + sector_sellect)); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE1_SECTOR_ERR+rez);//1000 memset((uint8_t *)AlignData, 0, FLASH_BLOCK_SIZE); //обнуляем буфер /* Copy data (already) located in RAM to flash */ memcpy((uint8_t *)AlignData, data, length ); //копируем данные, оставшаяся часть будет 0 /* Copy data (already) located in RAM to flash */ rez = u32IAP_CopyRAMToFlash((sector_start_map[uSER_DATA_SECTOR + sector_sellect] + block_sellect * FLASH_BLOCK_SIZE) , (uint32_t)AlignData, FLASH_BLOCK_SIZE); if( rez != IAP_STA_CMD_SUCCESS) return (COPY_RAM_TO_FLASH_ERR+rez); //4000 /* Verify the flash contents with the contents in RAM */ rez = u32IAP_Compare((sector_start_map[uSER_DATA_SECTOR + sector_sellect] + block_sellect * FLASH_BLOCK_SIZE), (uint32_t)AlignData, FLASH_BLOCK_SIZE, 0); if( rez != IAP_STA_CMD_SUCCESS) return (COMPARE_SECTOR_ERR+rez); //5000 return rez; } /***************************************************************************** ******************************************************************************/ uint32_t ReadUserDataFromFlash(uint8_t sector_sellect, uint8_t block_sellect, uint8_t * DstAddr) { if(sector_sellect >= USER_DATA_SIZE) return WRONG_SECTOR_SELLECT; //выходим с ошибкой if(block_sellect >= BLOCK_NUM_IN_SECTOR) return WRONG_BLOCK_SELLECT; //выходим с ошибкой //читаем данные из блока memcpy( DstAddr, (uint8_t *)(sector_start_map[uSER_DATA_SECTOR + sector_sellect] + block_sellect * FLASH_BLOCK_SIZE), FLASH_BLOCK_SIZE); return 0; //выходим из функции } /***************************************************************************** ******************************************************************************/ //----------------------------------------------------------// uint32_t EraseUserDataFlashSegment(uint8_t sector_sellect) { uint32_t rez = 0; if(sector_sellect >= USER_DATA_SIZE) return WRONG_SECTOR_SELLECT; //выходим с ошибкой /* Prepare Sectors to be erased */ rez = u32IAP_PrepareSectors((USER_DATA_SECTOR + sector_sellect), (USER_DATA_SECTOR + sector_sellect)); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE1_SECTOR_ERR+rez); rez = u32IAP_EraseSectors((USER_DATA_SECTOR + sector_sellect), (USER_DATA_SECTOR + sector_sellect)); if( rez != IAP_STA_CMD_SUCCESS) return (ERASE_SECTOR_ERR+rez); return rez; } //функция проверки наличия данных настройки езернета /***************************************************************************** Return 1 if Code present Return 0 if Code NOT present ******************************************************************************/ uint32_t CheckForPresentEthSettingsData(void) { uint32_t Result[2]; if ( u32IAP_BlankCheckSectors(ETH_SETTINGS_SECTOR, ETH_SETTINGS_SECTOR, Result) == IAP_STA_CMD_SUCCESS ) return (0); else return (BLANK_CHECK_SECTOR_ERR); } //функция проверки наличия данных настройки /***************************************************************************** Return 1 if Code present Return 0 if Code NOT present ******************************************************************************/ uint32_t CheckForPresentSettingsData(void) { uint32_t Result[2]; if ( u32IAP_BlankCheckSectors(SETTINGS_DATA_SECTOR, SETTINGS_DATA_SECTOR, Result) == IAP_STA_CMD_SUCCESS ) return (0); else return (BLANK_CHECK_SECTOR_ERR); } //---------------------------------------------------------------------------// /***************************************************************************** Return rez if any errors Return 0 if success. ******************************************************************************/ uint32_t WriteBootModeOption(uint32_t BootMode) { uint32_t AlignData[FLASH_BLOCK_SIZE / 4]; //буфер для 32 битного выравнивания данных для флэш uint32_t rez; //переменная для кода возврвата /* Prepare Sectors to be flashed */ rez = u32IAP_PrepareSectors(BOOT_MODE_SECTOR, BOOT_MODE_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE1_SECTOR_ERR+rez); rez = u32IAP_EraseSectors(BOOT_MODE_SECTOR, BOOT_MODE_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (ERASE_SECTOR_ERR+rez); /* Prepare Sectors to be flashed */ rez = u32IAP_PrepareSectors(BOOT_MODE_SECTOR, BOOT_MODE_SECTOR); if( rez != IAP_STA_CMD_SUCCESS) return (PREPARE2_SECTOR_ERR+rez); memset((uint8_t *)AlignData, 0, FLASH_BLOCK_SIZE); //обнуляем буфер /* Copy data (already) located in RAM to flash */ memcpy((uint8_t *)AlignData, &BootMode, sizeof(BootMode) ); //копируем код бутлоадера //сохраняем данныне rez = u32IAP_CopyRAMToFlash(BOOTMODE_FLASH_START, (uint32_t)AlignData, FLASH_BLOCK_SIZE); if( rez != IAP_STA_CMD_SUCCESS) return (COPY_RAM_TO_FLASH_ERR+rez); /* Verify the flash contents with the contents in RAM */ //проверяем данные rez = u32IAP_Compare(BOOTMODE_FLASH_START, (uint32_t)AlignData, FLASH_BLOCK_SIZE, 0); if( rez != IAP_STA_CMD_SUCCESS) return (COMPARE_SECTOR_ERR+rez); return rez; } /***************************************************************************** ******************************************************************************/ void ReadBootModeOption(uint32_t *BootMode) { //читаем режим работы memcpy(BootMode, (uint8_t *)(BOOTMODE_FLASH_START) , sizeof(uint32_t)); } /***************************************************************************** ** End Of File *****************************************************************************/ там еще есть хедеры, они просто константы описывают, надеюсь из названия констант будет понятно что они значат%). Поглядите, может вам поможет, может найдете какие отличия. У меня сколько не пробовал пишет прошивку и пользовательские данные без глюков. А в начале глюки были. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Спасибо большое, сейчас опробую и отпишусь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Кстати, вы учли, что IAP использует немного вашей ОЗУ? Вот из даташита: Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack usage in the user allocated stack space is 128 bytes, growing downwards. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Кстати, вы учли, что IAP использует немного вашей ОЗУ? Вот из даташита: Да, программа использует только первые 8кб ОЗУ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба А причина почему вызываю загрузчик из приложения, что бы уменьшить код загрузчика. В основном приложении гружу прошивку в SDRAM через USB, прыгаю на загрузчик, на всё готовое, инициализированное =). И просто копирую с SDRAM в буфер в RAMe, кусочками по 256 байт и пишу во флеш. Правильная последовательность: 1. Загрузчик в начале флеш. Стартует первым. Проверяет валидность основной прошивки во флеш и наличие новой прошивки в SDRAM (инициализировав предварительно интерфейс SDRAM). 2. Если есть новая валидная прошивка в SDRAM - загрузчик шьёт её. В конце прошивки - сбрасывает флаг наличия новой прошивки. 3. Если имеется валидная прошивка во флеш (вновь прошита или имелась ранее), загрузчик передаёт управление на неё. Основная программа, по завершении приёма новой прошивки в SDRAM, ставит флаг новой прошивки и делает аппаратный сброс CPU (сторожевиком или через спец.регистр). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 1 июля, 2014 Опубликовано 1 июля, 2014 · Жалоба Правильная последовательность: 1. Загрузчик в начале флеш. Стартует первым. Проверяет валидность основной прошивки во флеш и наличие новой прошивки в SDRAM (инициализировав предварительно интерфейс SDRAM). 2. Если есть новая валидная прошивка в SDRAM - загрузчик шьёт её. В конце прошивки - сбрасывает флаг наличия новой прошивки. 3. Если имеется валидная прошивка во флеш (вновь прошита или имелась ранее), загрузчик передаёт управление на неё. Основная программа, по завершении приёма новой прошивки в SDRAM, ставит флаг новой прошивки и делает аппаратный сброс CPU (сторожевиком или через спец.регистр). Спасибо большое учту. Мысли примерно в этом же направлении и крутились.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dark0711 0 2 июля, 2014 Опубликовано 2 июля, 2014 · Жалоба Вобшем код от Golikov A., не очень помог, все осталось также. Поробую с частотой процессора поиграть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 2 июля, 2014 Опубликовано 2 июля, 2014 · Жалоба Поробую с частотой процессора поиграть.Угу. "Фигли думать, трясти надо". Что с ней играться, ее надо указать такой, как требует описание. И все. IAP уже давно используется во всех процессорах NXP и работает точно в соответствии с описанием. Надо искать причину. Делать это не видя вашего кода - невозможно (телепаты в отпуске). Ну выложу я вам свой код, он 100% рабочий. Подозреваю, что он точно так же не пойдет у вас - ведь этот код всего лишь обертка над вызовами IAP. Вам писали о резервировании ОЗУ - а стек у вас случайно не на конец ОЗУ устанавливается? #ifndef IAP_H__ #define IAP_H__ #include <stdint.h> class iap { public: // (NXP IAP) Status Codes enum status_t { CMD_SUCCESS, INVALID_CMD, SRC_ADDR_ERROR, DST_ADDR_ERROR, SRC_ADDR_NOT_MAPPED, DST_ADDR_NOT_MAPPED, COUNT_ERROR, INVALID_SECTOR, SECTOR_NOT_BLANK, SECTOR_NOT_PREPARED, COMPARE_ERROR, BUSY, PARAM_ERROR, ADDR_ERROR, ADDR_NOT_MAPPED, CMD_LOCKED, INVALID_CODE, INVALID_BAUD_RATE, INVALID_STOP_BIT, CODE_READ_PROT_ENABLED, MAX_ERROR }; enum cmd_code_t { PREPARE = 50, COPY, ERASE, BLANK_CHECK, GET_PART_ID, GET_BOOT_VER, COMPARE, REINVOKE_ISP, READ_UID, SIZE_ALIGN = 0xFFFFFFFF }; static uint_fast32_t const SECTOR_SIZE = 32 * 1024; static uint_fast32_t const MAX_SECTOR = 29; static uint_fast32_t const BLOCK_SIZE = 4096; static status_t check_blank(uint_fast8_t start_sector, uint_fast8_t end_sector); static status_t erase (uint_fast8_t start_sector, uint_fast8_t end_sector); static status_t erase (uint_fast8_t sector) { return erase (sector, sector); } static status_t write_block(uint32_t const *pDst, void const * pSrc); private: struct command_t { cmd_code_t Code; uint32_t Param[4]; }; struct result_t { status_t Status; uint32_t Result[4]; }; static void (* const IAP)(command_t *params, result_t *result); } static Flash __attribute__((unused)); #endif // IAP_H__ #include "iap.h" #include "../hardware.h" #include <macros.h> #include <scmRTOS.h> void (* const iap::IAP)(command_t *params, result_t *result) = (void(*)(command_t *params, result_t *result))0x1fff1ff1; iap::status_t iap::check_blank(uint_fast8_t start_sector, uint_fast8_t end_sector) { iap::command_t Command; iap::result_t Result; Command.Code = BLANK_CHECK; Command.Param[0] = start_sector; Command.Param[1] = end_sector; TCritSect cs; IAP(&Command, &Result); return Result.Status; } iap::status_t iap::erase (uint_fast8_t start_sector, uint_fast8_t end_sector) { if(check_blank(start_sector, end_sector) == CMD_SUCCESS) return CMD_SUCCESS; iap::command_t Command; iap::result_t Result; Command.Code = PREPARE; Command.Param[0] = start_sector; Command.Param[1] = end_sector; TCritSect cs; IAP(&Command, &Result); if (Result.Status == CMD_SUCCESS) { Command.Code = ERASE; Command.Param[0] = start_sector; Command.Param[1] = end_sector; Command.Param[2] = CCLK_FREQ / 1000; IAP(&Command, &Result); if (Result.Status == CMD_SUCCESS) { Command.Code = BLANK_CHECK; Command.Param[0] = start_sector; Command.Param[1] = end_sector; IAP(&Command, &Result); } } return Result.Status; } #include <string.h> iap::status_t iap::write_block(uint32_t const *pDst, void const * pSrc) { uint32_t Buffer[bLOCK_SIZE / sizeof(uint32_t)]; memcpy(Buffer, pSrc, sizeof(Buffer)); iap::command_t Command; iap::result_t Result; Command.Code = PREPARE; Command.Param[0] = 1; // do not overwrite bootloader Command.Param[1] = MAX_SECTOR; TCritSect cs; IAP(&Command, &Result); if (Result.Status != CMD_SUCCESS) return Result.Status; Command.Code = COPY; Command.Param[0] = (uint32_t) pDst; Command.Param[1] = (uint32_t) Buffer; Command.Param[2] = BLOCK_SIZE; Command.Param[3] = CCLK_FREQ / 1000; IAP(&Command, &Result); return Result.Status; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться