Jump to content

    

ДЕЙЛ

Участник
  • Content Count

    258
  • Joined

  • Last visited

Everything posted by ДЕЙЛ


  1. У меня было ошибочное предположение, что адреса таблиц нужно вписывать в регистры вручную перед вызовом IAP, что я и делал: asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал.
  2. Спасибо, заработало :-) Выкинул ассемблер, упростил и в итоге получился работающий код: #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?
  3. среда IAR В мануале написано, что нужно зарезервировать верхние байты. Что имеется ввиду под верхними байтами, если считать за начало адрес 0x2000000, а за конец 0x2008000? Эти 32 байта распложены в области 0x2000000 - 0x200001F или в другом конце?
  4. С этим тоже вопрос. Как зарезервировать место в памяти?
  5. Решил данный вопрос задать в отдельной теме, ответвив от темы про стартовый загрузчик 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
  6. Но ведь хочется спросить и тут разжёваный ответ получить :rolleyes: Спасибо за направляющий ответ, буду копать. Как в общих чертах происходит запись блока? Какие шаги нужно проделать?
  7. Пока в исходник загрузчика глубоко не влазил. Хочу попробовать что-либо записать во флеш из программы. т.е. если написать вот так: adres = (unsigned int*)0x20000200; //область оперативной памяти *adres = 0x12345678; то всё нормально - в ячейку с указанным адресом записывается число, а если написать вот так adres = (unsigned int*)0x1000; //область флеш-памяти *adres = 0x12345678; то ничего не записывается. Тут нужно предварительно какие-то настройки делать. В мануале что-то написано, но нет примеров. Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778
  8. Тут надо разделить магнитные помехи и электрические. От магнитных помех спасёт пермаллой, а от высокочастотных электрических обычно экранируют не сплошным металлом, а сеткой с круглыми отверстиями, как Вы наверно видели внутри сотовых телефонов. Если правильно помню из курса технической электродинамики, такие отверстия называются вырожденными волноводами, т.е. такие волноводы, которые физически не могут пропустить электромагнитные волны выше определённой частоты. На 100% правильность совета не претендую ввиду почти полностью забытых мной лекций по СВЧ, но я бы поэкспериментировал бы с дырчатыми экранами.
  9. я бы выложил последовательность действий скринами, понятнее стало бы
  10. А если заменить кварц? Среди них тоже бывают бракованные. И ещё смущает такая частота, для MSP430 это как-то многовато, я разгонял PLL максимум до 20МГц, а кварц ставил до 8-10 МГц. Может МК работает на пределе частоты и повышение температуры его добивает? Остальной код нормально работает?
  11. смущает нестандартность функции. Для её использования нужно сначала подключить библиотеку(какую?) и выполнить соответствующие настройки. Простор для появления ошибок тут широкий, хотя появилась мысль прицепить параллельно линии COM-порт компа и смотреть обмен. В какой библиотеке следует искать функцию USART_WriteString()? И как её приспособить к LPC1778?
  12. Хочется до сути докопаться. Напишу я эту функцию и как потом понять - она не работает или что-то с модемом? В самом начале мне проще сначала с осциллографом своими глазами байты смотреть для уверенности в совпадении своих представлений о работе функции. Иначе можно было бы всё запихать в одну функцию вроде DeviceInit(), Device_Rabota(), Device_Off();
  13. т.е. команда AT+CREG? соответствует последовательности {0x41, 0x54, 0x2B, 0x43, 0x52, 0x45, 0x47, 0x3F, 0x0D}? где можно подробнее на эту тему почитать? В мануале сразу начинают с АТ-команд без их представления в HEX
  14. в тонкости пока не вникаю, хочу понять - команда AT+CREG? соответствует последовательности {0x41, 0x54, 0x2B, 0x43, 0x52, 0x45, 0x47, 0x3F}?
  15. Есть GSM-модуль, основу описания работы с которым составляют AT-команды для общения с МК. Обмен данными выполняется по UART, который настроен на определённую скорость обмена. Тут вопросов нет. Далее читаю мануал и некоторые статьи вроде этой Для меня пока непонятно, что собой представляет к примеру команда AT+CREG? Как будет выглядеть одномерный массив для передачи в UART? Правильно я понимаю, что каждый символ из данной строки нужно перевести в ASCII-коды? Т.е. руководствуясь вот этой таблицей имеем A - 0x41 T - 0x54 "+"- 0x2B C - 0x43 R - 0x52 E - 0x45 G - 0x47 "?" - 0x3F В итоге для отправки команды AT+CREG? по UART микроконтроллер должен отправить строку {0x41, 0x54, 0x2B, 0x43, 0x52, 0x45, 0x47, 0x3F}. Мои представления правильные или где-то не так думаю?
  16. В генераторах на логических элементах с применением RC цепочек стабильно скважности строго 50% добиться сложно, надёжнее применить высокочастотный генератор и какой-нибудь делитель частоты, работающий по фронту или спаду входного сигнала. Стабильность скважности и точность частоты на выходе будет пропорциональна частоте генератора перед делителем - чем выше частота на входе и больше коэффициент деления, тем лучше характеристики сигнала на выходе. Для примера посмотри схему металлоискателя http://anker50.narod.ru/a_50m.htm На прикреплённом рисунке показан участок схемы с генератором и делителем.
  17. предполагаю, что таким образом увеличили рассеиваемую мощность на резисторах. Есть способ параллельного включения резисторов для разветвления общего тока при общем напряжении, а тут похоже на распределения напряжений при общем токе. Похожее включение резисторов видел в схемах искрозащиты.
  18. В чём трудность? Если нужно ловить микровольты, то мошть и нужно обвешивать всё частотными преобразователями, а если следить за разрядом аккумуляторов, то тут ошибкой 100 мВ на фоне 12 вольт можно пренебречь, а это чуть меньше одного процента. Можно и точный расчёт сделать, но думаю, что 12-16битного АЦП хватит за глаза. Калибровку или подгонку тоже никто не отменял. Ну и простота есть залог надёжности ;)
  19. Почему бы не применить такую схему? Контроль за каждым аккумулятором можно выполнять всего одним микроконтроллером, у которого имеется 4 входа АЦП. Если мы знаем напряжение в точке А1, то легко можем пересчитать напряжение в точке 1, т.е. имеем информацию о разряде нижнего аккумулятора. Далее, мы знаем напряжение в точке А2, которое пересчитываем в напряжение точки 2, т.е. измеряем напряжение на последовательно соединённых нижних двух аккумуляторах, из этого напряжения вычтем чуть ранее высчитанное напряжение самого нижнего аккумулятора и отсюда будем знать напряжение на втором снизу, т.е. разницу между точками 1 и 2. И т.д. до самого верхнего.
  20. конечная цель такая: имеется LPC1778, имеется скомпилированный файл proga.bin. Нужно сделать так, чтобы я мог по какому-нибудь интерфейсу с ПК этот файл побайтно отправить своей программой, а в контроллере эти байты встретит чуть ранее загруженный самопальный бутлоадер, который всё принятое разложит в памяти и запустит на выполнение. С написанием программы для ПК проблем не вижу, больше вопросов по принимающей стороне, т.е. с организацией записи прошивки в МК самопальным загрузчиком. Далее предполагаю передавать прошивку по радиоканалу и тем самым иметь возможность удалённо перепрошивать девайс.
  21. А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код: void main (void) { while(1) { } } и ещё вопрос Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет? Пока в матчасть вникаю, до железа руки не доходят. Вот ещё непонятность. в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника.
  22. С этим разобрался, для программного сброса перезапуска программы и соответственно для передачи управления по какому-либо адресу младший бит этого адреса должен быть всегда установлен, если используется Cortex-M3. Т.е. для программного перезапуска нужно написать: asm (" B 1 "); Для меня этот эксперимент принципиален для уяснения принципа передачи управления по конкретному адресу флеш, т.к. бутлоадер таким способом запускает программу, как я представляю.
  23. Есть ещё вопрос по безусловному переходу. если написать такой код: int i; void main (void) { for (i = 0; i<20; i++) { asm (" nop "); } asm (" B 0x???? "); } то по какому адресу нужно сделать безусловный переход, чтобы программа стала заново выполняться и возможно ли это? МК LPC1778, среда IAR.
  24. Мне нужно в перспективе реализовать удалённую смену прошивки, а для этого нужен тот самый пользовательский загрузчик, ожидающий программу извне. Но т.к. в этом деле пока ноль, то хочу сначала освоить основы. Это как с освоением способов обмена данными между программой на ПК и МК: сначала учимся отправлять-принимать байт, потом групповую передачу массива байтов, потом осваиваем алгоритмы обнаружения ошибок и т.д. Мало кто сразу начинает с освоения протоколов, минуя этап лицезрения отправки байта. Вот и я сначала хочу азы освоить. Уже интереснее. :) Как это сделать в IAR? И можно ли таким способом по одному адресу раздельно записать загрузчик, а по другому программу? Т.е. по очереди два файла загрузить. Флеш полностью не стирается перед записью? UP1: В IAR нашёл настройку начальных адресов: Options -> Linker -> вкладка Config -> кнопка Edit
  25. Пробежался по ссылкам. Я пока хочу понять сами основы, а не тонкости реализации. Пока понял так, что загрузчик и программе есть абсолютно независимые программы, связь между которыми в самом простом случае на уровне ассемблерной инструкции JMP Program_addres или JMP Bootloader_addres. Так? Если скомпилировать бинарный файл прошивки и записать его по нестандартному адресу флеш (не 0x0000, а, допустим, по адресу 0x30000, вставив по адресу 0x0000 инструкцию JMP 0x30000), то программа будет работоспособной или компилятор делает привязку к абсолютным адресам? Пока не рассматриваю конкретный МК. Как реализовать на Си запись данных во флеш по конкретным адресам в LPC1778? Интересно посмотреть пример кода. Можно даташит пожевать или у гугла спросить, но если кто-то может за пять минут сказать то, что я могу полдня искать, то лучше спросить. Иначе на форуме тогда не было бы смысла читать-писать :) я свои измышления пишу, в этой теме пока на нуле