|
как работать с IAP? |
|
|
|
 |
Ответов
(1 - 55)
|
Jan 28 2009, 15:10
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(cornflyer @ Jan 28 2009, 17:26)  Кто-нибудь научился работать...
нашел как поставить внешний i2c eeprom.... A, что, кто-нибудь это (после чтения документации и многочисленных обсуждений на форуме ) не умеет  . А вообще смотря для чего, у меня I2C EEPROM почти всегда, не смотря на то, что и во FLASH многое что пишется (приложения, прошивки FPGA,.....).
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jan 29 2009, 12:47
|

Частый гость
 
Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729

|
на форуме нет внятного описания как работать с IAP, нет рабочего кода, только какие-то танцы с бубном  пробовал код с форума - то пишет, то не пишет... непонятно почему в самой документации на lpc2148 - только пару строк хотя я все делал как требуется: выключал прерывания вызывал функцию подготовки флеша потом писал туда массив байт из RAM'а выложи свой рабочий код, который пишет и читает внутреннюю FLASH через IAP
|
|
|
|
|
Jan 30 2009, 06:51
|

Частый гость
 
Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729

|
да, я читал application note AN10256 компилятор Keil, target опция USE THUMB MODE включена.... CODE /* * IAP In-System Application Programming */
#include <LPC21xx.H>
// Clock Frequency #define XTAL 12000000 // Oscillator Frequency
#ifdef BYPASS_IAP #define CPUCLK XTAL // CPU Clock without PLL #else #define CPUCLK (XTAL*4) // CPU Clock with PLL #endif
#define CCLK (XTAL / 1000) // CPU Clock without PLL in kHz
// Phase Locked Loop (PLL) definitions #define PLL_BASE 0xE01FC080 // PLL Base Address #define PLLCON_OFS 0x00 // PLL Control Offset #define PLLSTAT_OFS 0x08 // PLL Status Offset #define PLLFEED_OFS 0x0C // PLL Feed Offset #define PLLCON_PLLE 0x01 // PLL Enable #define PLLCON_PLLD 0x00 // PLL Disable #define PLLCON_PLLC 0x03 // PLL Connect(0x02) | PLL Enable #define PLLSTAT_PLOCK 0x0400 //1<<10 // PLL Lock Status
struct iap_in { unsigned int cmd; unsigned int par[4]; };
typedef void (*IAP)(struct iap_in *in, unsigned int *result); #define iap_entry ((IAP) 0x7FFFFFF1) // IAP entry point
/* Default Interrupt Function: may be called when interrupts are disabled */ void def_isr (void) __irq { ; }
#ifdef BYPASS_IAP /* * Switch CPU to PLL clock */ void start_pll (void) { __asm { LDR R0, =PLL_BASE MOV R1, #0xAA MOV R2, #0x55
// Enable PLL MOV R3, #PLLCON_PLLE STR R3, [R0, #PLLCON_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS]
// Wait until PLL Locked LDR R2, =PLLSTAT_PLOCK PLL_Loop: LDR R3, [R0, #PLLSTAT_OFS] CMP R3, R2 BEQ PLL_Loop
// Switch to PLL Clock MOV R2, #0x55 MOV R3, #PLLCON_PLLC STR R3, [R0, #PLLCON_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS] } }
/* * Switch CPU to standard XTAL */ void stop_pll(void) __arm { __asm { LDR R0, =PLL_BASE MOV R1, #0xAA MOV R2, #0x55
// Disable PLL MOV R3, #PLLCON_PLLD STR R3, [R0, #PLLCON_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS] } }
#endif
/* * Convert 'addr' to sector number */ unsigned int get_secnum (void *addr) { unsigned int n;
n = ((unsigned int) addr >> 13) & 0x1F; // pseudo sector number
if (n >= (0x30000 >> 13)) { n -= 14; // high small 8kB Sectors ( } else if (n >= (0x10000 >> 13)) { n = 7 + (n >> 3); // large 64kB Sectors } return (n); // sector number }
/* * Erase Sector between 'start' and 'end' * Return: IAP error code (0 when OK) * NOTES: start needs to be a 256 byte boundary * size should be 256, 512, 1024 or 4089 */ unsigned int erase (void* start, void* end) { struct iap_in iap; // IAP input parameters unsigned int result[16]; // IAP results unsigned int save_VicInt; // for saving of interrupt enable register
save_VicInt = VICIntEnable; // save interrupt enable status VICIntEnClr = 0xFFFFFFFF; // disable all interrupts
#ifdef BYPASS_IAP stop_pll(); // IAP requires to run without PLL #endif
iap.cmd = 50; // IAP Command: Prepare Sectors for Write iap.par[0] = get_secnum (start); // start sector iap.par[1] = get_secnum (end); // end sector iap_entry (&iap, result); // call IAP function if (result[0]) goto exit; // an error occured?
iap.cmd = 52; // IAP command: Erase Flash iap.par[0] = get_secnum (start); // start sector iap.par[1] = get_secnum (end); // end sector iap.par[2] = CCLK; // CPU clock iap_entry (&iap, result); // call IAP function
exit:
#ifdef BYPASS_IAP start_pll(); // start PLL #endif
VICIntEnable = save_VicInt; // enable interrupts return (result[0]); }
/* * Program *data to flash_addr. number of bytes specified by size * Return: IAP error code (0 when OK) * Note: */ unsigned int program (void *flash_addr, void *data, unsigned int size) { struct iap_in iap; // IAP input parameters unsigned int result[16]; // IAP results unsigned int save_VicInt; // for saving of interrupt enable register
save_VicInt = VICIntEnable; // save interrupt enable status VICIntEnClr = 0xFFFFFFFF; // disable all interrupts
#ifdef BYPASS_IAP stop_pll(); // IAP requires to run without PLL #endif
iap.cmd = 50; // IAP Command: Prepare Sectors for Write iap.par[0] = get_secnum (flash_addr); // start sector iap.par[1] = iap.par[0]; // end Sektor iap_entry (&iap, result); // call IAP function if (result[0]) goto exit; // an error occured?
iap.cmd = 51; // IAP Command: Copy RAM to Flash iap.par[0] = (unsigned int) flash_addr; // destination-addr iap.par[1] = (unsigned int) data; // source-addr iap.par[2] = size; // number of bytes iap.par[3] = CCLK; // CPU clock iap_entry (&iap, result); // call IAP function
exit:
#ifdef BYPASS_IAP start_pll(); // start PLL #endif
VICIntEnable = save_VicInt; // enable interrupts return (result[0]); }
unsigned char vals[512];
void main (void) { unsigned int i;
unsigned int volatile start;
for (start = 0; start < 1000000; start++) { ; // wait for debugger connection (about 0.3 sec) }
VICDefVectAddr = (unsigned int) def_isr; // for spurious interrupts
for (i = 0; i < sizeof (vals); i++) { vals[i] = (unsigned char) i; }
program (0x30000, vals, sizeof (vals)); program (0x31000, vals, sizeof (vals)); program (0x32000, vals, sizeof (vals)); erase (0x30000, 0x31FFF); erase (0x32000, 0x33FFF);
while (1); }
|
|
|
|
|
Jan 30 2009, 08:48
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(cornflyer @ Jan 29 2009, 15:47)  на форуме нет внятного описания как работать с IAP, нет рабочего кода, только какие-то танцы с бубном  Никаких танцев при шатном использовании. Цитата ..непонятно почему На вопрос "почему" отвечает сам IAP возвращая коды ошибок, только вот Вы их анализировать не считаете нужным  . Начните с этого Цитата в самой документации на lpc2148 - только пару строк Вообще-то там целый раздел...
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 2 2009, 07:21
|

Частый гость
 
Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729

|
внутренний flash стоит использовать для хранения редкоменяющейся инфы... часто писать во внутренний flash - плохой стиль у него ресурс всего 100000 циклов записи.... запись через IAP занимает время, причем проц не обрабатывает прерывания.... если 100 раз в сутки приходица сохранять инфу - лучше писать во внешний eeprom у него ресурс 1000000 циклов вот например можно поставить i2c eeprom M24C64 код для чтения/записи приведен ниже: Код #include "lpc214x.h" /*-------------------------------------------------------------------------*/ #define SDA_BIT (1<<3)//for olimex board #define SCL_BIT (1<<2)//for olimex board #define I2C_ADDR (0x50)//I2C Slave Address /*-------------------------------------------------------------------------*/ void I2C_DELAY(void){ volatile z=1000; while(z) z--; } /*-------------------------------------------------------------------------*/ unsigned char I2C_SDA(void){ return (IOPIN0&SDA_BIT); } /*-------------------------------------------------------------------------*/ void I2C_SDA_HIGH(void){ IODIR0 &=~ SDA_BIT;//input } /* -------------------------------------------------------------------------*/ void I2C_SDA_LOW(void){ IOCLR0 = SDA_BIT; IODIR0 |= SDA_BIT;//output low } /*-------------------------------------------------------------------------*/ void I2C_SCL_HIGH(void){ IODIR0 &=~ SCL_BIT;//input } /*-------------------------------------------------------------------------*/ void I2C_SCL_LOW(void){ IOCLR0 = SCL_BIT; IODIR0 |= SCL_BIT;//output low } /*-------------------------------------------------------------------------*/ unsigned char i2c_send_byte(unsigned char b){ unsigned char result = 0; unsigned int i = 0; for(i=0;i<8;i++){ //Set Data if(b&0x80){// == 1000 0000 I2C_SDA_HIGH(); }else{ I2C_SDA_LOW(); } b = b<<1;//shift left by one position I2C_DELAY(); I2C_SCL_HIGH();//make clock pulse I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); } //Acknowledge I2C_SDA_HIGH(); I2C_DELAY(); I2C_SCL_HIGH();//make clock pulse I2C_DELAY(); if(I2C_SDA()){//check i2c slave acknowledge result = 1; }else{ result = 0; } I2C_SCL_LOW(); I2C_DELAY(); return result; } /*-------------------------------------------------------------------------*/ unsigned char i2c_write(unsigned int addr,unsigned char b){ unsigned char result = 0; //Initial state (stop condition) I2C_SCL_HIGH(); I2C_DELAY(); I2C_SDA_HIGH(); I2C_DELAY(); //Start (start condition) I2C_SDA_LOW(); I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); //Send i2c address if(i2c_send_byte(I2C_ADDR<<1)){//RW=0 result = 1; }else{ if(i2c_send_byte(addr>>8))result = 1;//high addr if(i2c_send_byte(addr))result = 1;//low addr if(i2c_send_byte(b))result = 1; } //Stop (stop condition) I2C_SDA_LOW(); I2C_DELAY(); I2C_SCL_HIGH(); I2C_DELAY(); I2C_SDA_HIGH(); I2C_DELAY(); return result; } /*-------------------------------------------------------------------------*/ void i2c_write_byte(unsigned int addr, unsigned char b){ unsigned char result = 1; while(result)result = i2c_write(addr,b); } /*-------------------------------------------------------------------------*/ void i2c_read_page(unsigned int addr, unsigned char *page_buff, unsigned int page_length){ unsigned char data_byte = 0; int b; //Initial state I2C_SCL_HIGH(); I2C_DELAY(); I2C_SDA_HIGH(); I2C_DELAY(); //Start (start condition) I2C_SDA_LOW(); I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); //Send address i2c_send_byte(I2C_ADDR<<1);//RW=0 i2c_send_byte(addr>>8);//high addr i2c_send_byte(addr);//low addr //Start (start condition) I2C_SCL_HIGH(); I2C_DELAY(); I2C_SDA_LOW(); I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); i2c_send_byte((I2C_ADDR<<1)|0x01);//RW = 1 while(page_length){//read page I2C_SDA_HIGH(); for(b=8;b--;){ I2C_DELAY; I2C_SCL_HIGH(); I2C_DELAY(); data_byte = (data_byte<<1)|((I2C_SDA())?0x01:0x00); I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); } *page_buff = data_byte; page_buff++; data_byte = 0; page_length--; //Acknowledge if(page_length) I2C_SDA_LOW(); else I2C_SDA_HIGH(); I2C_DELAY(); I2C_SCL_HIGH(); I2C_DELAY(); I2C_DELAY(); I2C_SCL_LOW(); I2C_DELAY(); } //Stop (stop condition) I2C_SDA_LOW(); I2C_DELAY(); I2C_SCL_HIGH(); I2C_DELAY(); I2C_SDA_HIGH(); I2C_DELAY(); }
|
|
|
|
|
Feb 2 2009, 07:46
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

|
Цитата(cornflyer @ Feb 2 2009, 10:21)  вот например можно поставить i2c eeprom M24C64 код для чтения/записи приведен ниже: А почему софтовый I2C???
|
|
|
|
|
Feb 2 2009, 08:22
|
Частый гость
 
Группа: Свой
Сообщений: 163
Регистрация: 24-08-05
Пользователь №: 7 937

|
По поводу IAP можно посмотреть здесь: http://www.tnkernel.com/usb_fw_upgrader.html (usb-fwu-1-0-1-lpc214x.zip -> fwu_asm.s) По поводу I2C - здесь:
|
|
|
|
|
Feb 2 2009, 11:17
|

Частый гость
 
Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729

|
преимущества софтового i2c :- софтовый i2c меньше занимает, работает без глюков  (смотри еррату на lpc2148) - SDA и SCL можно на любые ноги повесить мой личный опыт показывает что код, написанный на все случаи жизни - работает медленно, глючит и много жрет ресурсов.... поэтому я стараюсь кодить только то, что нужно для решения поставленной задачи
|
|
|
|
|
Feb 2 2009, 12:48
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(cornflyer @ Feb 2 2009, 14:17)  софтовый i2c меньше занимает, работает без глюков  (смотри еррату на lpc2148) Смотреть нечего - уже ДЕСЯТКИ лет I2C на любых Филипсовских контролерах никаких errata и глюков не имеет, является отлитым в бронзе стандартом. И, как Вам показалось, заработавший copy-paste из интернету софтового I2C не повод изрекать глупости про "глюки", "ресурсы" и "медленность".
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 7 2009, 07:32
|
Участник

Группа: Новичок
Сообщений: 52
Регистрация: 5-12-08
Пользователь №: 42 221

|
CODE ===========IAP.C============= #include "IAP.h" #define IAP_CLK Fcclk #define IAP_LOCATION 0x7FFFFFF1 #define iap_entry(a,  ((void (*)())(IAP_LOCATION))(a, unsigned long command[5] = {0,0,0,0,0}; unsigned long result[3]= {0,0,0}; /************************************************************************* * Function Name: IAP_PrepareSec * Parameters: unsigned long StartSecNum -- Start Sector Number * unsigned long EndSecNum -- End Sector Number * Return: unsigned long -- Status Code * * Description: This command must be executed before executing "Copy RAM to Flash" or * "Erase Sector(s)" command. * *************************************************************************/ unsigned long IAP_PrepareSec (unsigned long StartSecNum, unsigned long EndSecNum) { if (EndSecNum < StartSecNum) return IAP_STA_INVALD_PARAM; command[0] = IAP_CMD_PrepareSec; command[1] = StartSecNum; command[2] = EndSecNum; iap_entry(command, result); return result[0]; } /************************************************************************* * Function Name: IAP_CopyRAMToFlash * Parameters: unsigned long dst -- Destination Flash address, should be a 256 byte boundary. * unsigned long src -- Source RAM address, should be a word boundary * unsigned long number -- 256 | 512 |1024 |4096 * Return: unsigned long -- Status Code * * Description: This command is used to program the flash memory. * *************************************************************************/ unsigned long IAP_CopyRAMToFlash (unsigned long dst, unsigned long src, unsigned long number) { command[0] = IAP_CMD_CopyRAMToFlash; command[1] = dst; command[2] = src; command[3] = number; command[4] = IAP_CLK / 1000; // Fcclk in KHz iap_entry(command, result); return result[0]; } /************************************************************************* * Function Name: IAP_EraseSec * Parameters: unsigned long StartSecNum -- Start Sector Number * unsigned long EndSecNum -- End Sector Number * Return: unsigned long -- Status Code * * Description: This command is used to erase a sector or multiple sectors of on-chip Flash * memory. * *************************************************************************/ unsigned long IAP_EraseSec (unsigned long StartSecNum, unsigned long EndSecNum) { if (EndSecNum < StartSecNum) return IAP_STA_INVALD_PARAM; command[0] = IAP_CMD_EraseSec; command[1] = StartSecNum; command[2] = EndSecNum; command[3] = IAP_CLK / 1000; iap_entry(command, result); return result[0]; } /************************************************************************* * Function Name: IAP_BlankChkSec * Parameters: unsigned long StartSecNum -- Start Sector Number * unsigned long EndSecNum -- End Sector Number * Return: unsigned long -- Status Code * * Description: This command is used to blank check a sector or mutilple sectors of on-chip * Flash memory. * *************************************************************************/ unsigned long IAP_BlankChkSec (unsigned long StartSecNum, unsigned long EndSecNum, unsigned long * pResult) { if (EndSecNum < StartSecNum) return IAP_STA_INVALD_PARAM; command[0] = IAP_CMD_BlankChkSec; command[1] = StartSecNum; command[2] = EndSecNum; iap_entry(command, result); if (result[0] == IAP_STA_SECTOR_NOT_BLANK) { *pResult = result[0]; *(pResult+1) = result[1]; } return result[0]; } /************************************************************************* * Function Name: IAP_ReadParID * Parameters: unsigned long * PartID * Return: unsigned long -- Status Code * * Description: This command is used to read the part identification number. * *************************************************************************/ unsigned long IAP_ReadParID (unsigned long * PartID) { command[0] = IAP_CMD_ReadParID; iap_entry(command, result); *PartID = result[1]; return result[0]; } /************************************************************************* * Function Name: IAP_ReadBootVer * Parameters: char * MajorVer * char * MinorVer * Return: unsigned long -- Status Code * * Description: This command is used to read the boot code version number. * *************************************************************************/ unsigned long IAP_ReadBootVer (unsigned long * MajorVer, unsigned long * MinorVer) { command[0] = IAP_CMD_ReadBootVer; iap_entry(command, result); *MajorVer = (result[1] & 0xff00)>>8; *MinorVer = result[1] & 0xff; return result[0]; } /************************************************************************* * Function Name: IAP_Compare * Parameters: unsigned long dst -- Destination Flash address * unsigned long src -- Source RAM address * unsigned long number -- Should be in mutilple of 4 * Return: unsigned long -- Status Code * * Description: This command is used to compary the memory contents at two locations. * * NOTE: Compary result may not be correct when source or destination address contains * any of the first 64 bytes starting from address zero. First 64 bytes can be re-mapped * to RAM. * *************************************************************************/ unsigned long IAP_Compare (unsigned long dst, unsigned long src, unsigned long number, unsigned long *offset) { command[0] = IAP_CMD_Compare; command[1] = dst; command[2] = src; command[3] = number; iap_entry(command, result); if (result[0] == IAP_STA_COMPARE_ERROR) *offset = result[1]; return result[0]; } void IAP_ReinvokeISP(void) { command[0] = IAP_CMD_REINVOKEISP; iap_entry(command, result);; } ===================================== ===========IAP.H============= #ifndef __IAP_H #define __IAP_H /* IAP Command */ #define IAP_CMD_PrepareSec 50 //select sector #define IAP_CMD_CopyRAMToFlash 51 //copy data from ram to flash #define IAP_CMD_EraseSec 52 //erase sector #define IAP_CMD_BlankChkSec 53 //check if sector is blank #define IAP_CMD_ReadParID 54 //read chip ID #define IAP_CMD_ReadBootVer 55 //read BOOT version #define IAP_CMD_Compare 56 //compare #define IAP_CMD_REINVOKEISP 57 //reinvoke ISP command /* IAP Status Codes */ #define IAP_STA_CMD_SUCCESS 0 #define IAP_STA_INVALID_COMMAND 1 #define IAP_STA_SRC_ADDR_ERROR 2 #define IAP_STA_DST_ADDR_ERROR 3 #define IAP_STA_SRC_ADDR_NOT_MAPPED 4 #define IAP_STA_DST_ADDR_NOT_MAPPED 5 #define IAP_STA_COUNT_ERROR 6 #define IAP_STA_INVALID_SECTOR 7 #define IAP_STA_SECTOR_NOT_BLANK 8 #define IAP_STA_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9 #define IAP_STA_COMPARE_ERROR 10 #define IAP_STA_BUSY 11 #define IAP_STA_INVALD_PARAM 12 extern unsigned long IAP_PrepareSec (unsigned long, unsigned long); extern unsigned long IAP_CopyRAMToFlash (unsigned long dst, unsigned long src, unsigned long number); extern unsigned long IAP_EraseSec (unsigned long StartSecNum, unsigned long EndSecNum); extern unsigned long IAP_BlankChkSec (unsigned long StartSecNum, unsigned long EndSecNum, unsigned long * pResult); extern unsigned long IAP_ReadParID (unsigned long * PartID); extern unsigned long IAP_ReadBootVer (unsigned long * MajorVer, unsigned long * MinorVer); extern unsigned long IAP_Compare (unsigned long dst, unsigned long src, unsigned long number, unsigned long *offset); extern void IAP_ReinvokeISP(void); #endif
|
|
|
|
|
Feb 18 2009, 12:27
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Позвольте задать вопрос в этой теме касаемо IAP. В мануале на LPC2378, который использую, написанно чёрным по-нерусски: "Up to 512 kB on-chip Flash Program Memory with In-System Programming (ISP) and In-Application Programming (IAP) capabilities. Single Flash sector or full-chip erase in 400 ms and 256 bytes programming in 1 ms". То есть для стирания !одного! или !всех! секторов без разницы надо 400 мс, а для записи 4кб=256*16=16мс? а сколько надо для подготовки сектора к записи и стиранию, и сравнения двух секторов? по этим операциям временных рамок не нашёл.
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 18 2009, 18:16
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(TanT @ Feb 18 2009, 15:27)  а сколько надо для подготовки сектора к записи и стиранию D В миллисекундном измерении приблизительно "нисколько". Цитата , и сравнения двух секторов? А это вообще бесполезность - сами можете сравнить - за сколько сравните, за столько и будет.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Feb 19 2009, 05:49
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Я так и думал  . А касаемо стирания одного сектора? "Single Flash sector or full-chip erase in 400 ms " И вообще имеет смысл каждый раз чистить сектор перед употреблением? То есть, не правильно выразился, какова вероятность ошибочной записи сектора без его предворительного стирания?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 19 2009, 06:45
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Цитата (TanT @ Feb 19 2009, 08:49) И вообще имеет смысл каждый раз чистить сектор перед употреблением? То есть, не правильно выразился, какова вероятность ошибочной записи сектора без его предворительного стирания? Глупый вопрос,  Следующий раз буду внимательнее слушать старших товарищей. Однако, всё таки кто-нибудь сможет ответить на вопрос: сколько требуется времени для стирания одного сектора по IAP для LPC2378?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 19 2009, 07:11
|
Участник

Группа: Новичок
Сообщений: 57
Регистрация: 7-11-06
Пользователь №: 22 054

|
TanTЦитата Однако, всё таки кто-нибудь сможет ответить на вопрос: сколько требуется времени для стирания одного сектора по IAP для LPC2378? А просто взять и измерить? 1. Таймером - считать значение до входа в процедуру стирания, считать значение после выхода, вывести в UART разницу 2. Осциллом - установить пин из 0 в 1 до входа, из 1 в 0 после выхода
|
|
|
|
|
Feb 19 2009, 10:04
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Цитата Производитель документирует 400 - их и нужно придерживаться. Игорь, простите, конечно, настырность, но эти милисекунды очень критичны. Развейте наконец мои сомнения. Сколько времени требуется для стирания одного сектора? А десяти?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 19 2009, 11:22
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Спасибо большое, именно это хотел услышать. А радиолюбительством я вроде и не собирался заниматься, не тот случай.
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 24 2009, 16:26
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 7-03-06
Из: Санкт-Петербург
Пользователь №: 15 038

|
Цитата(etoja @ Feb 24 2009, 18:18)  Прилагаю подробную инструкцию по IAP для использования с компилятором Crossworks. Извиняюсь перед автором этого документа, что не записал его адрес в интернете. Спасибо за пример, разбираюсь  Вопрос по прерываниям в основной программой. Если я линкеру укажу файлик "LPC2148_flash.xcl" в котором ручками поправлю начало флеш Код -DROMSTART=00001000 вместо Код -DROMSTART=00000040 и прерывания Код -Z(CODE)INTVEC=00001000-0000103f вместо Код -Z(CODE)INTVEC=00000000-0000003f будут ли корректно работать прерывания? Камешек lpc2148 Всем спасибо.
|
|
|
|
|
Feb 26 2009, 05:05
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Вопрос в продолжении темы IAP: команда 56 - сравнение секторов. насколько быстро и надёжно всё это происходит, например, для сектора в 4кб? Вообще, в принципе какая вероятность записать с ошибкой сектор по IAP?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 26 2009, 07:52
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Если сравнение гарантирует 100% выявление ошибок, то за чем лишнии действия? Однако, кто ответит что быстрее и надёжнее - вычисление 32-битной(16-битной) контрольной суммы или стандартная операция сравнения IAP?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Feb 26 2009, 17:02
|
Частый гость
 
Группа: Участник
Сообщений: 141
Регистрация: 7-03-06
Из: Санкт-Петербург
Пользователь №: 15 038

|
Цитата(TanT @ Feb 26 2009, 10:52)  Если сравнение гарантирует 100% выявление ошибок, то за чем лишнии действия? Однако, кто ответит что быстрее и надёжнее - вычисление 32-битной(16-битной) контрольной суммы или стандартная операция сравнения IAP? Какая-то у вас тяга к быстрым вычислениям  Для чего?
|
|
|
|
|
Mar 2 2009, 06:16
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Цитата Контрольная сумма нужна обязательно, поскольку в момент программирования может выключиться питание прибора. Но это - для профессионального оборудования. контрольная сумма будет обязательно будет, точнее она есть (16). И данные будут записываться уже достоверные, то есть требуется сличить записанные и записываемые данные. Совет KRS я считаю правильным и не пременно им воспользуюсь. Уцепился сразу за эту команду сравнения IAP, казалось что специально написанная функция должна быть оптимизированна и прочее Цитата Какая-то у вас тяга к быстрым вычислениям Для чего? Кроме записи по IAP много чего ещё должно работать, и запись далеко не приоритетная задача, и чем меньше времени она будет крутиться тем лучше. Вообще запись данных требуется проводить не заметно для остальных процессов, что сильно затрудняет обязательное требование запрета прерываний. Поэтому и стараюсь точно определить все временные рамки и по возможности их минимизировать, в частности на проверку данных. Большие трудности создаёт возможность неудачной записи (вероятность ошибки, думаю, никому неизвестна) 400 мс для стирания и повторной записи у меня нет.
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Mar 2 2009, 09:56
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(TanT @ Mar 2 2009, 08:16)  Вообще запись данных требуется проводить не заметно для остальных процессов, что сильно затрудняет обязательное требование запрета прерываний. Запрет прерываний - требование не обязательное. Обязательное требование - отсутствие доступа к Flash. Прерывания могут спокойно работать в RAM. Цитата The on-chip flash memory is not accessible during erase/write operations. When the user application code starts executing the interrupt vectors from the user flash area are active. The user should either disable interrupts, or ensure that user interrupt vectors are active in RAM and that the interrupt handlers reside in RAM, before making a flash erase/write IAP call. The IAP code does not use or disable interrupts.
|
|
|
|
|
Mar 2 2009, 12:23
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Цитата Запрет прерываний - требование не обязательное. Обязательное требование - отсутствие доступа к Flash. Прерывания могут спокойно работать в RAM. угу, читал. для меня обязательное
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Mar 16 2009, 02:31
|
self made
   
Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795

|
Цитата(cornflyer @ Jan 29 2009, 07:47)  на форуме нет внятного описания как работать с IAP, нет рабочего кода, только какие-то танцы с бубном  пробовал код с форума - то пишет, то не пишет... непонятно почему в самой документации на lpc2148 - только пару строк хотя я все делал как требуется: выключал прерывания вызывал функцию подготовки флеша потом писал туда массив байт из RAM'а выложи свой рабочий код, который пишет и читает внутреннюю FLASH через IAP  Может вы не ту доку читали? Я пользовался LPC2478, в доке все внятно прописано более менее. Не пара строк. За пару часов запись удалось осуществить.
|
|
|
|
|
Mar 17 2009, 06:19
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
Вопрос к etoja по поводу записи, точнее верификации. Пишу себе спокойно по IAP, проверяю двумя способами: в лоб по рекомендации KRS и IAPовским сравнением. И нет такого момента, чтобы без ошибок обошлось на 32 кб записи 2-3 ошибки в среднем. Ну это ещё полбеды. Смотрю где ошибка - записанно всё что требуется (покрайней мере в том месте куда указывают функции сравнения). Ладно, думаю, по не опытности накосячил где-нить с указателями и не то сравниваю, однако, прошивка не запускается. Но стоит повторить целиком запись прошивки "поверх" старой, и - о чудо - всё работает и ошибок проверки не возникает. Чем это может быть обоснованно? Как всё таки достоверно сравнивать данные из ОЗУ и флеш?
P.S. Записывал массив одинаковых символов, смотрел глазками что вышло, всё в идеале, хотя ошибки всё равно лезут. Прерывания естественно все отключены, даже пробовал модуль акселератора памяти отключать (МАМ), думалось может при обращении к флеш не-то читается - не помогло в общем.
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Mar 17 2009, 12:14
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 22-11-05
Из: Россия->Омск
Пользователь №: 11 210

|
а вы правы, ar__systems. частота стояла из старого проекта в 4 раза меньше требуемой. Для надёжного прописывания флеш сколько времени требуется - то есть после записи, требуется провести проверку, что же там написанно. Паузы не требуется между записью блока и проверкой?
--------------------
Если вы не можете объяснить что-то шестилетнему ребенку, значит, вы сами этого не понимаете. Альберт Эйнштейн
|
|
|
|
|
Aug 3 2009, 09:32
|
Местный
  
Группа: Свой
Сообщений: 272
Регистрация: 3-06-06
Пользователь №: 17 737

|
Подскажите всё ли правильно делаю,чтобы зашить в LPC2134 число: 1) в кейле Options for Target задаю два раздела IROM1 от 0х0 до 0x17FFF IROM2 от 0х18000 до 0x20000, тоесть планирую писать в последний сектор,для этого создаю раздел IROM2. 2) в прогу определяю переменную как const unsigned int i __attribute__((at(0x18000)));3) следующей функцией стираю последний сектор и записываю туда какой-то массив, в первом элементе которого хранится будущее значение i Код typedef void (*IAP)(unsigned int *in, unsigned int *result); #define iap_entry ((IAP) 0x7FFFFFF1)
unsigned int program (unsigned int * data) { unsigned int command[5]; unsigned int result[5]; unsigned int save_VicInt;
save_VicInt = VICIntEnable; VICIntEnClr = 0xFFFFFFFF; //запрет прерываний
command[0] = 50;//подготовка command[1] = 10; command[2] = 10; iap_entry (command, result); if (result[0])goto exit;
command[0] = 52;//стирание command[1] = 10; // начало command[2] = 10;// конец command[3] = 60000;// частота проца iap_entry (command, result); if (result[0])goto exit;
command[0] = 50;//подготовка command[1] = 10; command[2] = 10; iap_entry (command, result); if (result[0])goto exit;
command[0] = 51;//запись command[1] = (unsigned int) 0x0018000; // куда пишется command[2] = (unsigned int) data;//что пишется command[3] = 256;// число байт command[4] = 60000; iap_entry (command, result); if (result[0])goto exit;
exit:
VICIntEnable = save_VicInt; return (result[0]); } Проблема состоит в том, что в таком случае на команде стирания проц вылетает в PAbt_Handler. Если не объявлять раздел IROM2,тогда всё нормально проходит,но тогда как проконтролировать не залезет ли прога в область,где предполагается перезапись.
|
|
|
|
|
Aug 27 2009, 19:57
|

Участник

Группа: Участник
Сообщений: 61
Регистрация: 5-10-05
Из: Зеленоград
Пользователь №: 9 268

|
Цитата(GetSmart @ Mar 15 2009, 23:34)  В векторах программ чаще всего используется IRQ. Если по адресу 0x18 в нулевом секторе (загрузчике) стоит команда LDR PC,[PC,#-0xFF0], то этого достаточно чтобы IRQ прикладной программы нормально действовали. Для FIQ тоже можно сделать похожим образом. Ну а остальные вестора исключительных ситуаций обычно не возникают и для большинства программ не имеют значения. Обычно там вообще стоят заглушки типа зависона. Это отличное решение для IRQ (главное не забыть запрограммировать VICDefVectAddr, иначе при spurious interrupt поимеем переход на нулевой адрес). Но я не уверен что для FIQ такой номер прокатит. Если мне не изменяет память, то инструкция LDR PC,[PC,#-0xFF0] загружает в PC значение, считанное по адресу PC,#-0xFF0, то есть VICVectAddr, и это хорошо подходит для векторных прерываний. FIQ к ним не относится. Могу ошибаться, поправьте, если я не прав (сам не пробовал). Но вряд ли FIQ понадобятся самому бутлоадеру, можно сделать обычный переход в нужную страницу.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|