![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
ДЕЙЛ
Свой-
Постов
776 -
Зарегистрирован
-
Посещение
-
Победитель дней
5
Весь контент ДЕЙЛ
-
Проигрывание файлов с SD карты
ДЕЙЛ ответил Слесарь тема в В помощь начинающему
Насколько помню, в конце сектора имеется какая-то контрольная сумма, поэтому для надёжности его нужно весь в буфер считывать и проверять правильность данных. Этот момент уточни. -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Покопался в настройках линкера, нашёл настройки линкера: Config->Edit->Linker configuration file editor->Vector Table-> .intvec start = 0x7000 Config->Edit->Linker configuration file editor->Memory Regions-> ROM = 0x7000 - 0x7FFFF После компилирования и запуска в пошаговом режиме видно, что программа раположена по адресу, начиная с 0x7000, на этом этапе всё работает нормально - данные бегут из UART0. Получается, что программа уже нормально записана в память и работоспособна. Далее пробую написать маленькую программу, расположенную в обычном месте, т.е. в начальном секторе флеш. Пишу такой текст: main() { asm ("B 0x7000"); } Перебрал несколько возможных адресов, но всегда зависает в Hard Fault. В каком известном векторе прерывания находится адрес обработчика? Как узнать этот адрес? Написал маленькую тестовую программу без подключения библиотек и лишних файлов unsigned int *VTOR int main() { VTOR = (unsigned int*)0xE000ED08; //адрес регистра смещения таблицы *VTOR = 0x7000; //смещение адреса таблицы веторов прерываний asm ("B 0x7000"); //адрес перехода } Т.е. 1. Прерывания не разрешал, близко к ним не подходил в этом коде. 2. Переферию не трогал 3. С этим вопрос - как узнать адрес? 4. По какому адресу переходить? Как его узнать? UP1: в прикреплённом архиве проект основного ПО и второй проект тестовой программы, которая должна запускть основное ПО ______________________________________________.rar -
Запись флеш в LPC1778
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
У меня было ошибочное предположение, что адреса таблиц нужно вписывать в регистры вручную перед вызовом IAP, что я и делал: asm ("mov r0, #0x6000"); //Запись в регистры отдельно младшие 2 байта asm ("movt r0, #0x2000"); //и старшие два байта адресов таблиц asm ("mov r1, #0x6100"); asm ("movt r1, #0x2000"); Поэтому в моём представлении инкременты ничего не меняли, но в любом случае вариант кода из первого поста не работал. -
Запись флеш в LPC1778
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Спасибо, заработало :-) Выкинул ассемблер, упростил и в итоге получился работающий код: #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? -
Запись флеш в LPC1778
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
среда IAR В мануале написано, что нужно зарезервировать верхние байты. Что имеется ввиду под верхними байтами, если считать за начало адрес 0x2000000, а за конец 0x2008000? Эти 32 байта распложены в области 0x2000000 - 0x200001F или в другом конце? -
Запись флеш в LPC1778
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
С этим тоже вопрос. Как зарезервировать место в памяти? -
Запись флеш в 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 -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Но ведь хочется спросить и тут разжёваный ответ получить :rolleyes: Спасибо за направляющий ответ, буду копать. Как в общих чертах происходит запись блока? Какие шаги нужно проделать? -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Пока в исходник загрузчика глубоко не влазил. Хочу попробовать что-либо записать во флеш из программы. т.е. если написать вот так: adres = (unsigned int*)0x20000200; //область оперативной памяти *adres = 0x12345678; то всё нормально - в ячейку с указанным адресом записывается число, а если написать вот так adres = (unsigned int*)0x1000; //область флеш-памяти *adres = 0x12345678; то ничего не записывается. Тут нужно предварительно какие-то настройки делать. В мануале что-то написано, но нет примеров. Хотелось бы увидеть самый простой пример включения возможности записи в ячейку флеш. МК LPC1778 -
Как бороться с внешними помехами?
ДЕЙЛ ответил ArtDenis тема в Схемотехника
Тут надо разделить магнитные помехи и электрические. От магнитных помех спасёт пермаллой, а от высокочастотных электрических обычно экранируют не сплошным металлом, а сеткой с круглыми отверстиями, как Вы наверно видели внутри сотовых телефонов. Если правильно помню из курса технической электродинамики, такие отверстия называются вырожденными волноводами, т.е. такие волноводы, которые физически не могут пропустить электромагнитные волны выше определённой частоты. На 100% правильность совета не претендую ввиду почти полностью забытых мной лекций по СВЧ, но я бы поэкспериментировал бы с дырчатыми экранами. -
я бы выложил последовательность действий скринами, понятнее стало бы
-
А если заменить кварц? Среди них тоже бывают бракованные. И ещё смущает такая частота, для MSP430 это как-то многовато, я разгонял PLL максимум до 20МГц, а кварц ставил до 8-10 МГц. Может МК работает на пределе частоты и повышение температуры его добивает? Остальной код нормально работает?
-
AT-команды
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
смущает нестандартность функции. Для её использования нужно сначала подключить библиотеку(какую?) и выполнить соответствующие настройки. Простор для появления ошибок тут широкий, хотя появилась мысль прицепить параллельно линии COM-порт компа и смотреть обмен. В какой библиотеке следует искать функцию USART_WriteString()? И как её приспособить к LPC1778? -
AT-команды
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Хочется до сути докопаться. Напишу я эту функцию и как потом понять - она не работает или что-то с модемом? В самом начале мне проще сначала с осциллографом своими глазами байты смотреть для уверенности в совпадении своих представлений о работе функции. Иначе можно было бы всё запихать в одну функцию вроде DeviceInit(), Device_Rabota(), Device_Off(); -
AT-команды
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
т.е. команда AT+CREG? соответствует последовательности {0x41, 0x54, 0x2B, 0x43, 0x52, 0x45, 0x47, 0x3F, 0x0D}? где можно подробнее на эту тему почитать? В мануале сразу начинают с АТ-команд без их представления в HEX -
AT-команды
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
в тонкости пока не вникаю, хочу понять - команда AT+CREG? соответствует последовательности {0x41, 0x54, 0x2B, 0x43, 0x52, 0x45, 0x47, 0x3F}? -
AT-команды
ДЕЙЛ опубликовал тема в Программирование
Есть 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}. Мои представления правильные или где-то не так думаю? -
Задержка для ГТИ
ДЕЙЛ ответил Avrpmpop тема в Схемотехника
В генераторах на логических элементах с применением RC цепочек стабильно скважности строго 50% добиться сложно, надёжнее применить высокочастотный генератор и какой-нибудь делитель частоты, работающий по фронту или спаду входного сигнала. Стабильность скважности и точность частоты на выходе будет пропорциональна частоте генератора перед делителем - чем выше частота на входе и больше коэффициент деления, тем лучше характеристики сигнала на выходе. Для примера посмотри схему металлоискателя http://anker50.narod.ru/a_50m.htm На прикреплённом рисунке показан участок схемы с генератором и делителем. -
предполагаю, что таким образом увеличили рассеиваемую мощность на резисторах. Есть способ параллельного включения резисторов для разветвления общего тока при общем напряжении, а тут похоже на распределения напряжений при общем токе. Похожее включение резисторов видел в схемах искрозащиты.
-
Контроль напряжения на отдельном элементе батареи
ДЕЙЛ ответил Toni43 тема в Схемотехника
В чём трудность? Если нужно ловить микровольты, то мошть и нужно обвешивать всё частотными преобразователями, а если следить за разрядом аккумуляторов, то тут ошибкой 100 мВ на фоне 12 вольт можно пренебречь, а это чуть меньше одного процента. Можно и точный расчёт сделать, но думаю, что 12-16битного АЦП хватит за глаза. Калибровку или подгонку тоже никто не отменял. Ну и простота есть залог надёжности ;) -
Контроль напряжения на отдельном элементе батареи
ДЕЙЛ ответил Toni43 тема в Схемотехника
Почему бы не применить такую схему? Контроль за каждым аккумулятором можно выполнять всего одним микроконтроллером, у которого имеется 4 входа АЦП. Если мы знаем напряжение в точке А1, то легко можем пересчитать напряжение в точке 1, т.е. имеем информацию о разряде нижнего аккумулятора. Далее, мы знаем напряжение в точке А2, которое пересчитываем в напряжение точки 2, т.е. измеряем напряжение на последовательно соединённых нижних двух аккумуляторах, из этого напряжения вычтем чуть ранее высчитанное напряжение самого нижнего аккумулятора и отсюда будем знать напряжение на втором снизу, т.е. разницу между точками 1 и 2. И т.д. до самого верхнего. -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
конечная цель такая: имеется LPC1778, имеется скомпилированный файл proga.bin. Нужно сделать так, чтобы я мог по какому-нибудь интерфейсу с ПК этот файл побайтно отправить своей программой, а в контроллере эти байты встретит чуть ранее загруженный самопальный бутлоадер, который всё принятое разложит в памяти и запустит на выполнение. С написанием программы для ПК проблем не вижу, больше вопросов по принимающей стороне, т.е. с организацией записи прошивки в МК самопальным загрузчиком. Далее предполагаю передавать прошивку по радиоканалу и тем самым иметь возможность удалённо перепрошивать девайс. -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
А если у меня в проекте никакие библиотеки не подключены? Просто имеется такой код: void main (void) { while(1) { } } и ещё вопрос Если я участок памяти программы, начиная с нулевого адреса, полностью скопирую в ОЗУ по адресу ADRES, затем после процедуры копирования сделаю перескок ассемблерной инструкцией asm (" B ADRES ");, то это будет равносильно выполнению программы заново? Работать будет? Пока в матчасть вникаю, до железа руки не доходят. Вот ещё непонятность. в описании ядра CM3 есть такие слова: "Таблица векторов прерываний может быть перемещена по другому адресу в области кода или в области ОЗУ" и далее имеется описание регистра смещения таблицы векторов VTOR. Как выглядит участок программы, который перемещает эту таблицу векторов? Нужно просто в регистр смещения записать новый адрес? Какие-то дополнительные действия нужны? Хотелось бы посмотреть пример исходника. -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
С этим разобрался, для программного сброса перезапуска программы и соответственно для передачи управления по какому-либо адресу младший бит этого адреса должен быть всегда установлен, если используется Cortex-M3. Т.е. для программного перезапуска нужно написать: asm (" B 1 "); Для меня этот эксперимент принципиален для уяснения принципа передачи управления по конкретному адресу флеш, т.к. бутлоадер таким способом запускает программу, как я представляю. -
Стартовый загрузчик
ДЕЙЛ ответил ДЕЙЛ тема в Программирование
Есть ещё вопрос по безусловному переходу. если написать такой код: int i; void main (void) { for (i = 0; i<20; i++) { asm (" nop "); } asm (" B 0x???? "); } то по какому адресу нужно сделать безусловный переход, чтобы программа стала заново выполняться и возможно ли это? МК LPC1778, среда IAR.