ДЕЙЛ 31 2 октября, 2014 Опубликовано 2 октября, 2014 (изменено) · Жалоба Решил данный вопрос задать в отдельной теме, ответвив от темы про стартовый загрузчик http://electronix.ru/forum/index.php?showt...15&start=15 Там подсказали насчёт организации записи флеш из пользовательской программы. Сделал по мануалу, т.к. примеров пока не видел. Получилось вот так: #include "iolpc1778.h" #include "LPC17xx.h" #define IAP_LOCATION 0x1fff1ff1 //точка входа в IAP (страница 896 мануала) unsigned long *command; unsigned long *result; unsigned int *test; typedef void (*IAP)(unsigned int*, unsigned int*); void main(void) { { //INIT SCS |= 0x20; //подключение осциллятора 12МГц while(!( SCS & 0x40 )) {} //ожидание запуска PLL0CON |= 0x01; //включение PLL0 PLL0CFG |= 0x09; //умножение частоты тактирования на (1+9) - 120МГц PLL0FEED = 0xAA; // PLL0FEED = 0x55; // CCLKSEL |= 0x100; //тактирование CPU от PLL0 } test = (unsigned int*)0x20001004; //записал контрольный байт в копируемую область RAM *test = 0xAA; IAP iap_entry; //так в мануале написано iap_entry = (IAP) IAP_LOCATION; //---//--- //_______СТЕРЕТЬ СЕКТОР_______// { result = (unsigned long*)0x20006100; //адрес расположения таблицы результатов command = (unsigned long*)0x20006000; //адрес таблицы параметров *command = 52; //код команды *command++; *command = 4; //начальный номер сектора *command++; *command = 4; //конечный номер сектора *command++; *command = 120000; //системная тактовая частота в кГц asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); iap_entry (command, result); } //_______СТЁРЛИ СЕКТОР______// //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______// { result = (unsigned long*)0x20006100; //адрес расположения таблицы результатов command = (unsigned long*)0x20006000; //адрес таблицы параметров *command = 50; //код команды *command++; *command = 4; //начальный номер сектора *command++; *command = 4; //конечный номер сектора asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); iap_entry (command, result); } //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// //_______КОПИРОВАТЬ ОПЕРАТИВНУЮ ПАМЯТЬ ВО ФЛЕШ_______// { result = (unsigned long*)0x20006100; //адрес расположения таблицы результатов command = (unsigned long*)0x20006000; //адрес таблицы параметров *command = 51; //код команды *command++; *command = 0x4000; //начальный адрес перезаписываемой флеш *command++; *command = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать *command++; *command = 512; //число байт для копирования *command++; *command = 120000; //системная тактовая частота в кГц asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); iap_entry (command, result); } //_______СКОПИРОВАЛИ СЕКТОР______// while(1) { test = (unsigned int*)0x4004; //для просмотра ячейки в отладчике в пошаговом режиме. } } Работать почему-то не хочет - как было во флеш FFFFFFFFFFFF, так и остались. Ещё в мануале написано, что содержимое регистров r0 и r1 остаётся постоянным во время работы с флеш-памятью, но у меня в пошаговом режиме видно, что после функции iap_entry (command, result); они меняются. Так же там написано, что в регистры r0 и r1 записываются начальные адреса таблиц параметров и результатов. Можно ли в моём коде избавиться от ассемблерных вставок, т.к. каждый раз вручную назначать адреса таблиц в памяти неудобно и нежелательно. Ещё там написано, что верхние 32 байта RAM не должны использоваться пользовательской программой, но как программе запретить пользоваться этими байтами? UP1: добавил файл проекта в IAR 20141001LPC.rar Изменено 2 октября, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 2 октября, 2014 Опубликовано 2 октября, 2014 · Жалоба Работать почему-то не хочетПеред командой стирания надо выполнить команду подготовки сектора. Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами. Во стальном похоже на правду. Вы зарезервировали для IAP место в конце ОЗУ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 2 октября, 2014 Опубликовано 2 октября, 2014 · Жалоба Перед командой стирания надо выполнить команду подготовки сектора. Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами. Во стальном похоже на правду. Вы зарезервировали для IAP место в конце ОЗУ? С этим тоже вопрос. Как зарезервировать место в памяти? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 2 октября, 2014 Опубликовано 2 октября, 2014 · Жалоба Как зарезервировать место в памяти?Читать документацию на среду разработки. Или хотя бы указать ее название - возможно кто-то и подскажет. Но читать полезнее :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 2 октября, 2014 Опубликовано 2 октября, 2014 · Жалоба Читать документацию на среду разработки. Или хотя бы указать ее название - возможно кто-то и подскажет. Но читать полезнее :) среда IAR Вы зарезервировали для IAP место в конце ОЗУ? В мануале написано, что нужно зарезервировать верхние байты. Что имеется ввиду под верхними байтами, если считать за начало адрес 0x2000000, а за конец 0x2008000? Эти 32 байта распложены в области 0x2000000 - 0x200001F или в другом конце? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 2 октября, 2014 Опубликовано 2 октября, 2014 · Жалоба среда IARЧитайте про линкер и его скрипт. Возможно можно где-то в менюшках уменьшить доступный размер ОЗУ. Просто скажите линкеру, что у вашего процессора ОЗУ меньше на 32 байта. или в другом конце?В другом - в самом конце ОЗУ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 3 октября, 2014 Опубликовано 3 октября, 2014 · Жалоба Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами.Не совсем. ТС модифицировал command перед тем, как передавать его в iap_entry(). Так что работать не будет :rolleyes: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 3 октября, 2014 Опубликовано 3 октября, 2014 · Жалоба Спасибо, заработало :-) Выкинул ассемблер, упростил и в итоге получился работающий код: #include "iolpc1778.h" #include "LPC17xx.h" #define IAP_LOCATION 0x1fff1ff1 //точка входа в IAP (страница 896 мануала) unsigned int command[5]; unsigned int result[2]; unsigned int *test; typedef void (*IAP)(unsigned int[], unsigned int[]); void main(void) { { //INIT SCS |= 0x20; //подключение осциллятора 12МГц while(!( SCS & 0x40 )) {} //ожидание запуска PLL0CON |= 0x01; //включение PLL0 PLL0CFG |= 0x09; //умножение частоты тактирования на (1+9) - 120МГц PLL0FEED = 0xAA; // PLL0FEED = 0x55; // CCLKSEL |= 0x100; //тактирование CPU от PLL0 } test = (unsigned int*)0x20001004; *test = 0xAA; IAP iap_entry; iap_entry = (IAP) IAP_LOCATION; //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______// { command[0] = 50; //код команды command[1] = 4; //начальный номер сектора command[2] = 4; //конечный номер сектора iap_entry (command, result); } //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// //_______СТЕРЕТЬ СЕКТОР_______// { command[0] = 52; //код команды command[1] = 4; //начальный номер сектора command[2] = 4; //конечный номер сектора command[3] = 120000; //системная тактовая частота в кГц iap_entry (command, result); } //_______СТЁРЛИ СЕКТОР______// //_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______// { command[0] = 50; //код команды command[1] = 4; //начальный номер сектора command[2] = 4; //конечный номер сектора iap_entry (command, result); } //_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______// //_______КОПИРОВАТЬ ОПЕРАТИВНУЮ ПАМЯТЬ ВО ФЛЕШ_______// { command[0] = 51; //код команды command[1] = 0x4000; //начальный адрес перезаписываемой флеш command[2] = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать command[3] = 512; //число байт для копирования command[4] = 120000; //системная тактовая частота в кГц iap_entry (command, result); } //_______СКОПИРОВАЛИ СЕКТОР______// while(1) { test = (unsigned int*)0x4004; } } Интересно узнать, в чём суть подготовки памяти? Со стиранием вроде понятно - наверно FFFFFFFами заполняет всё. И ещё есть не совсем понятная команда заполнения пробелами. Правильно я понимаю, что 0x1fff1ff1 есть адрес начала отдельной программы IAP? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 3 октября, 2014 Опубликовано 3 октября, 2014 · Жалоба Спасибо, заработало :-)"И совсем не страшно" :) Интересно узнать, в чём суть подготовки памяти?Это знают только авторы IAP. Правильно я понимаю, что 0x1fff1ff1 есть адрес начала отдельной программы IAP?Да. Не совсем. ТС модифицировал command перед тем, как передавать его в iap_entry(). Так что работать не будет :rolleyes:Недопонял. Ну сделал он его указателем, как это повлияло на неработу? Адрес массива передается в функцию точно таким же указателем. Место в памяти под command он выделяет статически. Да, абсолютные адреса-"магические цифры", криво но как может влиять на неработу? Или я чего-то другого не заметил? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 3 октября, 2014 Опубликовано 3 октября, 2014 · Жалоба Недопонял. Ну сделал он его указателем, как это повлияло на неработу? Адрес массива передается в функцию точно таким же указателем. Он несколько раз инкрементировал этот указатель, прежде чем передать в функцию: command = (unsigned long*)0x20006000; //адрес таблицы параметров *command = 51; //код команды *command++; // <<< тут *command = 0x4000; //начальный адрес перезаписываемой флеш *command++; // <<< тут *command = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать *command++; // <<< тут *command = 512; //число байт для копирования *command++; // <<< и тут *command = 120000; //системная тактовая частота в кГц iap_entry (command, result); // В результате тут command смотрит не на команды, а сразу ЗА НИМИ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 3 октября, 2014 Опубликовано 3 октября, 2014 · Жалоба Да, действительно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 6 октября, 2014 Опубликовано 6 октября, 2014 (изменено) · Жалоба У меня было ошибочное предположение, что адреса таблиц нужно вписывать в регистры вручную перед вызовом IAP, что я и делал: asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал. Изменено 6 октября, 2014 пользователем ДЕЙЛ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 7 октября, 2014 Опубликовано 7 октября, 2014 · Жалоба Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал.Так по этому и не работал - передача параметрами command и result полностью забивали то, что вы сделали в ассемблерной вставке. Причем меняли правильные значения в регистрах (после ассемблерной вставки) на неправильные (из модифицированного command) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ДЕЙЛ 31 7 октября, 2014 Опубликовано 7 октября, 2014 · Жалоба Так по этому и не работал - передача параметрами command и result полностью забивали то, что вы сделали в ассемблерной вставке. Причем меняли правильные значения в регистрах (после ассемблерной вставки) на неправильные (из модифицированного command) не работало по причине неправильной программы, это я уже выяснил :) Этот вопрос можно пока закрыть. Лучше посоветуйте в теме про стартовый загрузчик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться