реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> lpc1788 iap, Портит данные
Тоша
сообщение Jun 30 2014, 15:09
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Всем привет! Нужна помошь, никак не могу разобраться. Решил Я написать свой bootloader, и разместил его в конце флеша. Основная программа вызываеть его когда хочет обновиться. Сделал, все залил. Бутлодер грузиться, находит файл прошивки и должен запихать ее с нолевого адреса флеша. Но при записи(256 512 байит или более)портиться первый две или три пачки, пишиться какаято чушь, а далее все как положено записываеться.Сектора флеша форматирую перед записью. Может кто сталкивался с проблемой???
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jun 30 2014, 15:51
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



1. Лучше наоборот сделать%)
Бутлоадер в начало положить, а прошивку боевую ближе к концу.
Стартуете с бутлоадера, он проверяет прошивку боевую (целостность и прочее), если все ок переходит к ней,если нет ждет новую.

Ну не важно...

2. Была такая фигня (на 1768, но они близнецы братья как понимаю) , нужно запрещать прерывания, если брали стандартные примеры, то там есть запреты, но вместо них пустые заглушки, а иногда ваще нет запретов. А запреты ОЧЕНЬ строго нужны. Даже таймер может сбивать процесс.
Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 1 2014, 02:50
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Цитата(Golikov A. @ Jun 30 2014, 19:51) *
1. Лучше наоборот сделать%)
Бутлоадер в начало положить, а прошивку боевую ближе к концу.
Стартуете с бутлоадера, он проверяет прошивку боевую (целостность и прочее), если все ок переходит к ней,если нет ждет новую.

Идея была в том, что бутлодел заливает прошивку и просто ресетит микроконтроллер и он весело стартует с новой прошивкой

Цитата
2. Была такая фигня (на 1768, но они близнецы братья как понимаю) , нужно запрещать прерывания, если брали стандартные примеры, то там есть запреты, но вместо них пустые заглушки, а иногда ваще нет запретов. А запреты ОЧЕНЬ строго нужны. Даже таймер может сбивать процесс.

Прерывания отрубаю, таблицы векторов перемешаю. В errata вычитал что нужно в Pboost тройку вставить и в Matrix arb еденицу в бит rom lat, не помогло !
Как Я понял из errata что еще частоту можно понизить и типо все пучком будет.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 1 2014, 04:59
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Почему не работает, не знаю, но прокомментирую саму реализацию. Размещать бутлоадер в конце вполне разумно, у меня так же сделано. Но идея вызывать загрузчик из приложения не очень хорошая. Тут многие сталкивались с проблемами при таком подходе и в итоге переходили к другой схеме: сначала всегда стартует загрузчик и проверяет, нужно ли обновлять приложение или стартовать имеющееся.
Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 1 2014, 05:18
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Цитата(andrewlekar @ Jul 1 2014, 08:59) *
Почему не работает, не знаю, но прокомментирую саму реализацию. Размещать бутлоадер в конце вполне разумно, у меня так же сделано. Но идея вызывать загрузчик из приложения не очень хорошая. Тут многие сталкивались с проблемами при таком подходе и в итоге переходили к другой схеме: сначала всегда стартует загрузчик и проверяет, нужно ли обновлять приложение или стартовать имеющееся.

Вот скорей всего так и буду делать, размешать в начале и проверять есть чего или нет.
А причина почему вызываю загрузчик из приложения, что бы уменьшить код загрузчика. В основном приложении гружу прошивку в SDRAM через USB, прыгаю на загрузчик, на всё готовое, инициализированное =). И просто копирую с SDRAM в буфер в RAMe, кусочками по 256 байт и пишу во флеш.

Просто обидно, хочется разобрать в причинах нестабильной работе IAP, а то он так в середине флеша напишет мне лабуду, а Я потом буду гадать, чего это основная программа падает.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение Jul 1 2014, 05:49
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



Ну потому обычно и грузят загрузчик первым, он проверяет контрольную сумму прошивки, и если что не переходит на нее. В вашей же схеме залей вы кривую программу (в момент переписывания из рам во флэш), после ресета проц превратиться в кирпич. Естественно после записи программы во флэш ее стоит проверить, что записалось именно то что хотели, но стремление 100% записи понятно.

А таймауты все выдерживаются, на стирание страниц и так далее?

вот у меня такой IAP, это LPCешный, с некоторыми правками, в частности переделаны макросы запрета прерывания

CODE
/*****************************************************************************
* $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, cool.gif ((void (*)())(IAP_ROM_LOCATION))(a, cool.gif

//макрос запрета прерывания с сохранением статуса
#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 бита, важный момент в работе с флэш. Сектора у меня стираются по командно и пишутся по блоков, так что между вызовами есть пауза порядка миллисекунды.

CODE

/*****************************************************************************
*****************************************************************************/
#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
*****************************************************************************/



там еще есть хедеры, они просто константы описывают, надеюсь из названия констант будет понятно что они значат%). Поглядите, может вам поможет, может найдете какие отличия. У меня сколько не пробовал пишет прошивку и пользовательские данные без глюков. А в начале глюки были.

Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 1 2014, 06:04
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Спасибо большое, сейчас опробую и отпишусь.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jul 1 2014, 06:11
Сообщение #8


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Кстати, вы учли, что 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.
Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 1 2014, 06:33
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Цитата(andrewlekar @ Jul 1 2014, 10:11) *
Кстати, вы учли, что IAP использует немного вашей ОЗУ? Вот из даташита:

Да, программа использует только первые 8кб ОЗУ
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 1 2014, 06:39
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Тоша @ Jul 1 2014, 11:18) *
А причина почему вызываю загрузчик из приложения, что бы уменьшить код загрузчика. В основном приложении гружу прошивку в SDRAM через USB, прыгаю на загрузчик, на всё готовое, инициализированное =). И просто копирую с SDRAM в буфер в RAMe, кусочками по 256 байт и пишу во флеш.

Правильная последовательность:
1. Загрузчик в начале флеш. Стартует первым. Проверяет валидность основной прошивки во флеш и наличие новой прошивки в SDRAM (инициализировав предварительно интерфейс SDRAM).
2. Если есть новая валидная прошивка в SDRAM - загрузчик шьёт её. В конце прошивки - сбрасывает флаг наличия новой прошивки.
3. Если имеется валидная прошивка во флеш (вновь прошита или имелась ранее), загрузчик передаёт управление на неё.
Основная программа, по завершении приёма новой прошивки в SDRAM, ставит флаг новой прошивки и делает аппаратный сброс CPU (сторожевиком или через спец.регистр).
Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 1 2014, 06:43
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Цитата(jcxz @ Jul 1 2014, 10:39) *
Правильная последовательность:
1. Загрузчик в начале флеш. Стартует первым. Проверяет валидность основной прошивки во флеш и наличие новой прошивки в SDRAM (инициализировав предварительно интерфейс SDRAM).
2. Если есть новая валидная прошивка в SDRAM - загрузчик шьёт её. В конце прошивки - сбрасывает флаг наличия новой прошивки.
3. Если имеется валидная прошивка во флеш (вновь прошита или имелась ранее), загрузчик передаёт управление на неё.
Основная программа, по завершении приёма новой прошивки в SDRAM, ставит флаг новой прошивки и делает аппаратный сброс CPU (сторожевиком или через спец.регистр).

Спасибо большое учту. Мысли примерно в этом же направлении и крутились..
Go to the top of the page
 
+Quote Post
Тоша
сообщение Jul 2 2014, 03:11
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 39
Регистрация: 13-08-10
Пользователь №: 58 896



Вобшем код от Golikov A., не очень помог, все осталось также. Поробую с частотой процессора поиграть.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 2 2014, 06:40
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Тоша @ Jul 2 2014, 06:11) *
Поробую с частотой процессора поиграть.
Угу. "Фигли думать, трясти надо". Что с ней играться, ее надо указать такой, как требует описание. И все. IAP уже давно используется во всех процессорах NXP и работает точно в соответствии с описанием. Надо искать причину. Делать это не видя вашего кода - невозможно (телепаты в отпуске). Ну выложу я вам свой код, он 100% рабочий. Подозреваю, что он точно так же не пойдет у вас - ведь этот код всего лишь обертка над вызовами IAP.
Вам писали о резервировании ОЗУ - а стек у вас случайно не на конец ОЗУ устанавливается?

CODE

#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;
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 02:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01527 секунд с 7
ELECTRONIX ©2004-2016