Перейти к содержанию
    

Запись флеш в LPC1778

Решил данный вопрос задать в отдельной теме, ответвив от темы про стартовый загрузчик 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

Изменено пользователем ДЕЙЛ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Работать почему-то не хочет
Перед командой стирания надо выполнить команду подготовки сектора. Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами. Во стальном похоже на правду. Вы зарезервировали для IAP место в конце ОЗУ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Перед командой стирания надо выполнить команду подготовки сектора. Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами. Во стальном похоже на правду. Вы зарезервировали для IAP место в конце ОЗУ?

С этим тоже вопрос. Как зарезервировать место в памяти?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как зарезервировать место в памяти?
Читать документацию на среду разработки. Или хотя бы указать ее название - возможно кто-то и подскажет. Но читать полезнее :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Читать документацию на среду разработки. Или хотя бы указать ее название - возможно кто-то и подскажет. Но читать полезнее :)

среда IAR

 

Вы зарезервировали для IAP место в конце ОЗУ?

В мануале написано, что нужно зарезервировать верхние байты. Что имеется ввиду под верхними байтами, если считать за начало адрес 0x2000000, а за конец 0x2008000? Эти 32 байта распложены в области 0x2000000 - 0x200001F или в другом конце?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

среда IAR
Читайте про линкер и его скрипт. Возможно можно где-то в менюшках уменьшить доступный размер ОЗУ. Просто скажите линкеру, что у вашего процессора ОЗУ меньше на 32 байта.

или в другом конце?
В другом - в самом конце ОЗУ.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Запись в регистры асм-вставками бессмысленна - вы делаете то же самое вызывая iap_entry() с параметрами.
Не совсем. ТС модифицировал command перед тем, как передавать его в iap_entry(). Так что работать не будет :rolleyes:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, заработало :-)

 

Выкинул ассемблер, упростил и в итоге получился работающий код:

#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?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, заработало :-)
"И совсем не страшно" :)

 

Интересно узнать, в чём суть подготовки памяти?
Это знают только авторы IAP.

Правильно я понимаю, что 0x1fff1ff1 есть адрес начала отдельной программы IAP?
Да.

 

 

Не совсем. ТС модифицировал command перед тем, как передавать его в iap_entry(). Так что работать не будет :rolleyes:
Недопонял. Ну сделал он его указателем, как это повлияло на неработу? Адрес массива передается в функцию точно таким же указателем. Место в памяти под command он выделяет статически. Да, абсолютные адреса-"магические цифры", криво но как может влиять на неработу? Или я чего-то другого не заметил?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Недопонял. Ну сделал он его указателем, как это повлияло на неработу? Адрес массива передается в функцию точно таким же указателем.

Он несколько раз инкрементировал этот указатель, прежде чем передать в функцию:

command = (unsigned long*)0x20006000;   //адрес таблицы параметров

*command = 51;         //код команды
*command++;  // <<< тут
*command = 0x4000;     //начальный адрес перезаписываемой флеш
*command++; // <<< тут
*command = 0x20001000; //начальный адрес оперативной памяти, откуда нужно копировать

*command++; // <<< тут
*command = 512;        //число байт для копирования
*command++; // <<< и тут
*command = 120000;     //системная тактовая частота в кГц

iap_entry (command, result); // В результате тут command смотрит не на команды, а сразу ЗА НИМИ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня было ошибочное предположение, что адреса таблиц нужно вписывать в регистры вручную перед вызовом IAP, что я и делал:

asm ("mov  r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта
asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц

asm ("mov  r1, #0x6100");
asm ("movt r1, #0x2000");

Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал.

Изменено пользователем ДЕЙЛ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал.
Так по этому и не работал - передача параметрами command и result полностью забивали то, что вы сделали в ассемблерной вставке. Причем меняли правильные значения в регистрах (после ассемблерной вставки) на неправильные (из модифицированного command)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Так по этому и не работал - передача параметрами command и result полностью забивали то, что вы сделали в ассемблерной вставке. Причем меняли правильные значения в регистрах (после ассемблерной вставки) на неправильные (из модифицированного command)

не работало по причине неправильной программы, это я уже выяснил :) Этот вопрос можно пока закрыть. Лучше посоветуйте в теме про стартовый загрузчик.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...