|
IAP. Лыжи не едут или как... |
|
|
|
Apr 2 2008, 08:51
|
Частый гость
 
Группа: Свой
Сообщений: 182
Регистрация: 30-01-05
Из: Volgograd
Пользователь №: 2 305

|
В общем надо записывать флэш. Определения: Код #define IAP_LOCATION 0x7FFFFFF1 typedef void (*IAP)(unsigned int [], unsigned int []); #define iap_entry ((IAP) IAP_LOCATION)
unsigned int command[5]; unsigned int result[2]; Собственно функция стирания секторов: Код unsigned int erase (unsigned int start, unsigned int end) { command[0]= IAP_PREPARE_SECTOR; // IAP Command: Prepare Sectors for Write (50) command[1] = 3;//Get_sector(start); // Start Sector command[2] = 3; //Get_sector(end-1); // End Sector iap_entry(command, result); // Call IAP Function if (result[0]==0) { u0putstr("Preparing sector`s ok. Erasing...\r\n"); command[0] = IAP_ERASE_SECTOR; // IAP Command: Erase Flash (52) command[1] = Get_sector (start); // Start Sector command[2] = Get_sector (end-1); // End Sector command[3] = PCLK/1000; // CPU Clock iap_entry(command,result); // Call IAP Function } } При вызове IAP_PREPARE_SECTOR возвращает ошибку 7: INVALID_SECTOR. Я уже по всякому и объявлять пытался и т.п. - ни в какую. И номера секторов ручками пишу и по всякому. Результат один. массив команд заполнен вроде как верно. Примеры смотрел, документацию читал. Все вроде как там. И не работает. Камень LPC2106, LPC2103. PLL и т.п. отключены. Кварц 14.7456 Может гитьки какие есть? Если когда-то была установлена защита - она стирается при полнеом стирании флэша? И влияет ли она на эти процедуры?
|
|
|
|
|
 |
Ответов
(1 - 14)
|
Apr 2 2008, 09:44
|

Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 7-07-04
Из: Ukraine
Пользователь №: 291

|
У меня вот так все работает, правда для LPC2136:
// Вызов команды IAP static u32 IapCommand(u32 cmd, u32 p0, u32 p1, u32 p2, u32 p3, u32 *r0) { u32 command[5] = { cmd, p0, p1, p2, p3 }; u32 result[2]; // Запускаю команду IAP ((void(*)(u32 [],u32 []))0x7FFFFFF1)(command, result); // Возвращаю результат if (r0) { *r0 = result[1]; } return result[0]; }
static u32 IAP_ERASE(u32 curr_sec, u32 FcclkKHZ) { u32 state; // Готовлю сектор к стиранию iap_prepare_erase: state = IapCommand( IAP_CMD_PREPARE, curr_sec, curr_sec, 0, 0, 0); switch(state) { case IAP_CMD_SUCCESS: break; case IAP_BUSY: goto iap_prepare_erase; default: return state; } // Стираю сектор iap_erase: state = IapCommand(IAP_CMD_ERASE, curr_sec, curr_sec, FcclkKHZ, 0, 0); switch(state) { case IAP_CMD_SUCCESS: break; case IAP_BUSY: goto iap_erase; default: return state; } return IAP_CMD_SUCCESS; }
--------------------
|
|
|
|
|
Apr 2 2008, 12:28
|

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

|
Цитата(EXeGLuMATOR @ Apr 2 2008, 11:51)  command[0]= IAP_PREPARE_SECTOR; // IAP Command: Prepare Sectors for Write (50) а чему равно IAP_PREPARE_SECTOR? Бывает указывают 0x50... Прерывания не забываете запрещать? В конце ОЗУ не забыли зарезервировать область 32 байта для IAP чтобы в нее случайно стек не залез? Код // (Philips) Status Codes enum iap_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, OUT_OF_MEMORY, MAX_ERROR };
enum iap_cmd_t { PREPARE = 50, COPY, ERASE, BLANK_CHECK, GET_PART_ID, GET_BOOT_VER, COMPARE, SIZE_ALIGN = 0xFFFFFFFF // make iap_cmd_t 4-bytes width };
struct iap_command_t { iap_cmd_t Command; uint32_t Param[4]; }; struct iap_result_t { iap_status_t Status; uint32_t Result[4]; };
extern "C" __thumb void IAP(iap_command_t *params, iap_result_t *result); // IAP объявлено в скрипте линкера, компилится более эффективный вызов, чем по указателю.
iap_status_t Erase (uint_fast8_t start_sector, uint_fast8_t end_sector) { iap_command_t Cmd; iap_result_t Res;
Cmd.Command = PREPARE; Cmd.Param[0] = start_sector; Cmd.Param[1] = end_sector;
critical_t cs; IAP(&Cmd, &Res); if (Res.Status == CMD_SUCCESS) { Cmd.Command = ERASE; Cmd.Param[0] = start_sector; Cmd.Param[1] = end_sector; Cmd.Param[2] = CCLK / 1000;
IAP(&Cmd, &Res); } return Res.Status; }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 2 2008, 13:22
|

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

|
Цитата(EXeGLuMATOR @ Apr 2 2008, 16:15)  Так... А как резервировать область? Зависит от компилятора (точнее линкера). Для IAR 4.xx указываю в скрипте Код -DRAMEND=(40003fff-.32) // reserve RAM for IAP .... -Z(DATA)CSTACK+_CSTACK_SIZE#RAMSTART-RAMEND -Z(DATA)SVC_STACK+_SVC_STACK_SIZE#RAMSTART-RAMEND -Z(DATA)IRQ_STACK+_IRQ_STACK_SIZE#RAMSTART-RAMEND ..... для GCC наверное писал бы что-нибудь вроде Код MEMORY { ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x00008000 RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x00004000 - 0x20 // reserve RAM for IAP REMAPED (rwx) : ORIGIN = 0x00000000, LENGTH = 0x40 }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 2 2008, 14:12
|

Частый гость
 
Группа: Свой
Сообщений: 163
Регистрация: 22-06-06
Из: Киев
Пользователь №: 18 292

|
Цитата(EXeGLuMATOR @ Apr 2 2008, 16:54)  Попробовал определения как описал - результат тот-же. Компилятор Keil, RealView. зарезервировать наверное можно просто указав в настройках проекта длину за вычетом этих байтов? Может сначала попробовать стереть всю флеш вместе с битами защиты через FLASH MAGIC? Если заработает - потом играться дальше
|
|
|
|
|
Apr 3 2008, 06:26
|
Участник

Группа: Свой
Сообщений: 55
Регистрация: 6-04-06
Из: Москва, Зеленоград
Пользователь №: 15 863

|
Цитата(EXeGLuMATOR @ Apr 2 2008, 20:33)  Да там и не стояло их отродясь. Причем и на новых процах, только с завода - один фиг. Та-же проблема. Походу где-то есть что-то что не дает работать с флэшем. Либо не так передаются параметры. Хотя у всех работает - у меня нет. Ну не может быть. Походу что-то не так в проекте всетаки. Вот только что... Пока не поставил command[3] = 512; процик тоже гнал всякую пургу. Почему-то не все описанные в ДШ размеры поддерживаются. Камень - LPC2119, одной из первых партий, у которых еще сброс не с первого раза. Код command[0] = IAP_CMD_WRITE; command[1] = (U32)(Buf_Dst); command[2] = (U32)(Buf_Src); command[3] = 512;//0x2000; command[4] = 14745;
|
|
|
|
|
Apr 3 2008, 19:34
|

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

|
Цитата(EXeGLuMATOR @ Apr 3 2008, 18:35)  Типа фича компилера? Вот если вы покажете конкретный участок листинга, который компилятор сделал по вашему мнению неправильно - можно будет говорить что-то о причастности компилятора. У меня с этим кодом была почти мистическая ситуация - программирование то работало, то не работало. Один день могло работать, второй - нет. Я уже начал вслух повторять "чудес не бывает" и думать насчет показаться психологу  Смотрю передающуюся структуру в отладчике - все правильно. Command = 50, Param[0] = 1, Param[1] = 2 а оно мне возвращает ошибку INVALID_CMD. Долго медитировал, несколько подходов делал. А в другой день отладчик показывает то же самое содердимое структуры, и все работает. Потом однажды посмотрел содержимое памяти на стеке в том месте, где лежит структура. А компилятор честно отвел под enum команды один байт и заполнял только его. В остальных трех был мусор, который иногда случайно был равен нулям и все работало. И отладчик тоже честно показывал мне содержимое только одного байта. После этого добавил в enum фиктивное значение SIZE_ALIGN = 0xFFFFFFFF и с тех пор все работает. Если кто-то захочет возразить, что enum занимает минимум int - у меня сознательно включена опция использовать короткие enumы и это активно используется в других частях программы.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jan 22 2009, 12:30
|

Частый гость
 
Группа: Свой
Сообщений: 163
Регистрация: 22-06-06
Из: Киев
Пользователь №: 18 292

|
Цитата(Сергей Борщ @ Apr 2 2008, 15:28)  Код extern "C" __thumb void IAP(iap_command_t *params, iap_result_t *result); // IAP объявлено в скрипте линкера, компилится более эффективный вызов, чем по указателю. } А как в скрипте линкера (.icf - IAR520) объявить IAP? Это не работает: define symbol IAP = 0x7FFFFFF1;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|