Самопрограммирование (STM32)

Иногда находятся нестандартные решения ...


Представим, что имеется большая интерфейсная линия, на которой размещено несколько десятков устройств. Управляет ими один мастер.
И вдруг, понадобилось обновить прошивку.
Ситуация не радостная. Мало того, что они удалены друг от друга, так еще и программатор с ноутбуком подключать к каждому персонально…
Вот и придумали для похожих задач самопрограммирование.

Идея такова:
Программа состоит из двух частей. Загрузчика и программы основной.
Загрузчик проверяет команду от Мастера для входа в режим программирования.
Если ничего нет — передает управление основной программе.
Основная программа кроме своих задач, должна следить за появлением все той же команды начала программирования.
И если такая появится, произвести Сброс. После чего управление вновь окажется у загрузчика.
Он примет байты данных, проверит контрольную сумму чтобы не накосячить, и запишет все по порядку во FLASH.

Загрузчик обязательно должен начинаться с 0x80000000 адреса, иначе старта не будет.

Основная программа может начинаться с любого адреса, в пределах 0x80000000-0x8001FFFF.
А чтобы она случайно не пересеклась с загрузчиком, для нее нужно выбрать место.
Проще это сделать, задав соответствующие значения в Keil-е или Coocox.

Адреса прекрасно отображаются в отладчике.
Но нельзя просто перейти на первый попавший.
Заглянем с файл .map.
Там будет строка примерно такого содержания — «Reset_Handler 0x08001421 Thumb Code»
Значит переходить нужно на 0x08001421.
Адрес Reset_handler — остается неизменным.
И не забыть переопределить вектора прерываний.
(NOP-ы здесь только для демонстрации, они не нужны вовсе как и функция Work)


SCB->VTOR = (((uint32_t)0x08000800)); // Переопределить вектора
.................................

typedef  void (*pFunction)(void); // Объявляем функцию перехода
...........................................

((pFunction) 0x08001421)(); // Переход на 0x08001421
.......................................

void work(void){ // Функция с пустыми NOP-ами
 __ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");__ASM("NOP");


HEX файл передается построчно:
:101800009008002001190008091900080B190008A8
где ":«начало строки.
»10" — длина данных (16).
"1800" адрес куда записывать первый байт данных из строки (последующие байты записываются на +1).
"00" запись.
"9008002001190008091900080B190008" — 16 байт данных.
"A8" Оканчивается каждая строка байтом контрольной суммы.
Считается легко. Если просуммировать все байты (контрольной суммы тоже), результат по модулю будет равен 00.

В моем проекте проверка КС происходит сразу после приема, в буфере uint8_t baits[21],
потом данные перебрасываются в uint8_t BUFFER_data[315][21].



Примеры.

read:   
     while(Rec_Flag==0){}; // Ждем данных
       Receive_UDR(); // Прием
	 Rec_Flag=0; 
      if (Receive_DATA[0]==':')
														 
      temp = check_sum(Konvert_ascii_leng()); // Проверка КС
    
      if(temp==0)
       {	                         
          Bait_to_FLASH_data(couBaits_toFLASH); Переброс в BUFFER_data[315][21];
          couBaits_toFLASH++; // Общий счетчик принятых строк
															
          temp = Konvert_ascii_leng(); // Определяем длину данных
          temp2 = konver_ascii_address(); // Адрес
																																		                   
          Receive_dat_clear();																	 
          Rec_Flag=0;	
																																	 
          Transmit_UDR("Ok", 20); // Отчитатся о удачно принятой строке																		
          goto read; // Снова, пока не поступит команда окончания
    } 
  else (если начало не ":" проверяем на условие, переходим в записи)
    

uint8_t check_sum (uint8_t leng){
        uint8_t temp3 = 0;
	uint8_t cou = 0;
	uint8_t temp4 = 0;
	uint16_t sym = 0;
	uint8_t count = 0;
	temp4 = leng ;
	leng = leng *2;
	leng = leng + 10;
	
	for(cou=0;cou<leng; cou=cou+2)
		{	
		 temp3 = Konvert_all(cou);
			baits[count] = temp3;
			sym=sym+temp3;
			count++;
    }	
	  leng = temp4;
	  leng = leng +6;
	     for(temp4=temp4; temp4<15; temp4++)
                {
		 baits[leng++]=0xFF;
                }
return sym;		
}

uint8_t Konvert_ascii_leng(){
     uint8_t template2;
     uint8_t templat;
	
    for(temp=0; temp<2; temp++)
	{		
	 switch(Receive_DATA[temp+1])
	 {
         case 'F': templat= 0x0F; break;
	 case 'E': templat= 0x0E; break;
	 case 'D': templat= 0x0D; break;
	 case 'C': templat= 0x0C; break;
	 case 'B': templat= 0x0B; break;
	 case 'A': templat= 0x0A; break;
	 case '9': templat= 0x09; break;
	 case '8': templat= 0x08; break;
	 case '7': templat= 0x07; break;
	 case '6': templat= 0x06; break;
	 case '5': templat= 0x05; break;
	 case '4': templat= 0x04; break;
	 case '3': templat= 0x03; break;
	 case '2': templat= 0x02; break;
	 case '1': templat= 0x01; break;
	 case '0': templat= 0x00; break;
	 default : templat= 0x0F; break;
    }	 template2 = template2 <<4;
	 template2 |= templat;
	}
	return template2;
}

Стирание FLASH
void FLASH_errase_Page(uint32_t address_start)
{
	flash_unlock();
	FLASH->CR = FLASH_CR_PER;
  FLASH->AR = address_start;
  FLASH->CR|= FLASH_CR_STRT;
  while ((FLASH->SR & FLASH_SR_BSY) != 0 );
	FLASH->CR = FLASH_CR_LOCK;	
}

void flash_unlock(void) {
  FLASH->KEYR = FLASH_KEY1;
  FLASH->KEYR = FLASH_KEY2;
}


И сама запись
void Write_FLASH(){
      uint32_t address =0;
      uint32_t address2 =0;
      int long numstring = 0;
      uint8_t temp3 = 0; 
      uint8_t temp4 = 0;
      uint32_t data = 0;
      int long line =0;
      uint8_t temp5 = 0;
      uint32_t temp6;
	
      FLASH_errase();
	
  for(temp3=0; temp3<couBaits_toFLASH; temp3++)
       {
	flash_unlock();
		
	FLASH->CR |= FLASH_CR_PG; //Разрешаем программирование флеша
		
	address=0;
	temp6=0;
		
	address = BUFFER_data[line][1];
        temp6 = address;		
	address = BUFFER_data[line][2];
	temp6 = temp6 << 8;
	address |=  temp6 ;
	
	temp6 = 0x8001800;
	temp6&=~0x00FFFFF;
	address |= temp6;
		
	for(temp4=0;temp4<16; temp4=temp4+4)
	  {
	   data = 0;
	   data |= (BUFFER_data[line][temp4+7]) ;   data = data <<8;
	   data |= (BUFFER_data[line][temp4+6] );   data = data <<8;	
           data |= (BUFFER_data[line][temp4+5] );   data = data <<8;
	   data |= (BUFFER_data[line][temp4 + 4] );
			
	   while ((FLASH->SR & FLASH_SR_BSY) != 0 );
      *(__IO uint16_t*)address = (uint16_t)data; //младшие 2 байта
          while ((FLASH->SR & FLASH_SR_BSY) != 0 );
			
          address+=2;
          data>>=16;
       *(__IO uint16_t*)address = (uint16_t)data; //старшие 2 байта
          while ((FLASH->SR & FLASH_SR_BSY) != 0 );
	  address+=2;
	 }
	  data = 0;
          FLASH->CR &= ~(FLASH_CR_PG); //Запрет программирования
	  line++;
   }	
}

Затем написал простенькую программу, которая просто отсылает HEX по строкам и следит за ответами.



Единственное неудобство в том, что проектов должно быть двое…
  • +6
  • 06 июля 2013, 11:23
  • khomin
  • 1
Файлы в топике: boot.zip

Комментарии (60)

RSS свернуть / развернуть
Простите за объявление.
0
Маленькая рекомендация. Что бы на такое объявление среагировал кто-то кроме ниираспила следует код оформлять чуть более качественно. гуглтранслейт забанен только в ниираспил, остальные компании могут его себе позволить. А наблюдать в одном коде konver_ascii_addres и address тем более странно. Помните — объявление/резюме — это ваше лицо. К ним надо подходить серьезно. Оформите «коекак» и получите «коекак».
P.S.: А я вот постоянно по-русски пишу «буффер» :)
+5
Конвертация ASCII-HEX в байт тоже забавная. Но это уже к самому коду, а не оформлению.
Baits тоже забавно. Русское слово в транслите с английским окончанием множественного числа)
+2
наблюдать в одном коде konver_ascii_addres и address тем более странно
а FLASH_errase, templat, sym, leng, cou. за такое вполне вменяемо 35к в москоу просить.
0
for(temp=0; temp<2; temp++)
тоже прикольно — как известно i,j,k перекочевали в Си из бейсика, в который они попали видимо из фортрана, в который они попали видимо из классических математических формул с Σ.

Видел как-то давно такой юмор:
int foo(ping) {

return pong;
}
0
в который они попали видимо из фортрана
Не «видимо», а именно из него. В фортране существует некоторый набор переменных, которые «уже объявлены» с предопределенным типами. Конкретно i,j,k и, если память не изменяет, l и m — целые.
0
Совершенно очевидно, что i,j,k перекочевали из алфавита.
0
35 т.р. в Москве? Не малоли?
В Чебоксарах (Чувашляндия) средняя З.П. 15 т.р. — которая ни на чё не хватает.
+2
Очевидно человек уже работает в обороннии, там з/п у сотрудников ниже рыночных в разы. Человек просто не знает, что можно зарабатывать больше, правда следовало бы немного подучится. будучи ещё в том нии.
+1
А что такого — 35 тыр. для москвы это нищенская з/п. Челу как я понял 23 года, и видимо вышки нет, электронику/MCU за год/полтора изучил по EE и инету — вполне скромно себя ведет, начиная с 35 тыр. Только вот как раз в профильной оборонке/нии старой формации ему как раз и не помешало бы подучиться годика 2-3. У барыг/ИП, где такие же самоучки или бывшие студенты — его уже ничему не научат.
0
Знали бы вы его текущую зарплату, сказали бы: «биги оттуда срочно!»
В этих нии нельзя задерживаться на долго — сгниёшь и никуда больше не уйдешь. Так что ни о каких 2-х годах, а тем более трех не может быть и речи. У тех же барыг он будет получать отдачу гораздо быстрее, что будет способствовать обучению. В ниишке ему надо только освоить всякие госты и организацию работы (отчеты, служебки,...), самому же разработку там не освоить — нечего и задерживаться.
0
Я же не знаю про какое нии там идет речь, в нии можно и сисадмином и техником паялой работать, но можно и аспирантом быть на нищенской з/п, но с интересной темой и с неплохой техн.базой, которой у барыг просто нет или она им не нужна.
0
Сам постоянно себя убеждаю в том, что надо бежать из НИИ, но куда? К дяде? Может тогда лучше свое дело организовать?
0
надо бежать из НИИ, но куда?
Куда, куда — естественно в Тексас Инструментс! Там такая же тупая работа инженеришкой с 8-00 до 17-00, но оклады больше.

Я вот более приземленными проблемами занят — как научиться/стать гениальным(ну хотя бы талантливым) инженером или хотя бы искусным и сверхпродуктивным мегаговнокодером (типа Линуса — вот счастливый человек, как начал с 20 лет говнокодить и портировать ОДНУ программку — так с нее и питается до сих пор). Как видите, Я выбрал что попроще, т.к. гениального математика или натурального философа из меня уже не получится — загубили талант «дерьмократы». Ввиду уникальной конфигурации мозга, я мог бы принести огромную пользу Родине, да и вообще всему человечеству, ну и естественно такой уникальный труд надо было бы соответственно оплачивать. Я мог бы продвинуть вперед такие перспективные отрасли науки и технологии, как квантовые компьютеры, искусственный интеллект, строение материи на микроуровне и т.п. Почему меня не определили в соответствующие структуры, не поддержали материально и не дали соответствующую материально-техническую базу?
-1
я бы и рад в тексас, но это же не так просто…
0
я бы и рад в тексас, но это же не так просто…
Вот что говорит Джо Фрейзер — он не разбогател в итоге, как некоторые, но был и остался настоящим простым мужиком(солью земли).
0
Попасть в большую контору вполне реально. В конце-концов, там уже работает много народу, как-то же они туда попали, верну? :) Вопрос больше в желании туда попасть. Вблизи (а тем более изнутри) большие конторы зачастую куда как менее привлекательны, чем издалека.
0
так с нее и питается до сих пор
Линукс, насколько мне известно, программа бесплатная, с чего ему питаться?
0
Линус конечно лох в этом смысле — ему очень далеко до Билла или Стива, но ему и ничего больше и не надо видимо: домик, пара мерсов есть и 10-15 тыр баксов ежемесячно с конца 90-х. Точно не знаю механизмов, но западное об-во его как-то гуманитарно содержит — это же не россия.
0
Линус конечно лох в этом смысле — ему очень далеко до Билла или Стива,
Или наоборот, он гораздо прозорливее их обоих и позаботился о карме смолоду.
+1
10-15 тыр баксов ежемесячно
Это, кстати, не так уж много, для людей такого калибра. Я не сильно удивлюсь, если окажется сумма раза в два-два с половиной больше.
0
Это, кстати, не так уж много, для людей такого калибра. Я не сильно удивлюсь, если окажется сумма раза в два-два с половиной больше.
Ну я тоже так и думал, просто указал сумму по минимуму, учитывая, что он вроде не помешанный на бабках чел, и 10-15 тыр.я думаю с лихвою хватает его семье для нормального существования. Кстати в док.фильме 2001 года «The Code (Linux)» он уже гоняет на BMW, которую в штатах может себе позволить любой, кто имеет >=5 тыр.$ в месяц.
0
Ну я тоже так и думал, просто указал сумму по минимуму, учитывая, что он вроде не помешанный на бабках чел, и 10-15 тыр.я думаю с лихвою хватает его семье для нормального существования
Дело не в стремлении заполучить много бабок, просто стоимость жизни сильно зависит от местности.
0
То, что софт раздается бесплатно вовсе не значит, что за его разработку не платят. Один из вариантов — допиливание имеющейся софтины для решения конкретных задач. Раз заказчику это нужно, он и платит за разработку. А поскольку это опенсорс, то результатом потом пользуются все. Другой вариант — какая-нибудь контора для решения своих задач пишет софтину, а поскольку продажа софта не ее бизнес, то готовую софтину выкладывает в виде опенсорс. Самой конторе это выгодно, поскольку сильно снижает затраты на дальнейшее сопровождение и развитие софтины. Ну и имидж, естественно. А имидж это новые клиенты и бабло от основного бизнеса.
0
Да, кстати, забыл еще о таком замечательном варианте, как борьба с конкурентами с помощью открытых технологий. Например андроид. Да и линукс в этом качестве тоже использовался. В обоих случаях удалось выпинать с рынков, где, казалось, они давно и прочно окопались. Естественно, что это не могло произойти без вложения бабла в разработку, причем изрядного.
0
Линукс, насколько мне известно, программа бесплатная, с чего ему питаться?

Linux — как раз хороший пример, что на open source можно зарабатывать. Посмотрите например на Linux Foundation (там есть информация о членах и ежегодных взносах). И это только один из источников дохода, evsi привел множество других. Помимо этого, корпорации спонсируют ядро не только деньгами, но и кодом, отдавая свои наработки сообществу.
0
Такие люди как Линус для меня просто загадочный пример уникальных возможностей человеческого мозга в сфере кодинга, но еще больше трудолюбия. Для меня ясно, что он бывший студент, т.е. был типичным говнокодером года 2-3, т.е. говнокодером тактическим(на уровне самого кода). Потом еще года 2-3 он уже побыл говнокодером стратегическим, т.е. уже на уровне самого проекта и его структуры. И наконец стал гуру.

Великий RMS, как говорят, был когда-то заурядным паскалюгой и не смог пройти собеседование в Microsoft. И он явно перемудрил со своей ОС GNU и сам в итоге запутался в ней(горе от ума), хотя возможно что очень много усилий он направил на GCC и другие программы для GNU, но студент Линус в это время неутомимо, обильно и монолитно говнокодил свой Linux и к большому удивлению даже для себя — его проект достиг известности и был успешен почти с самого начала.

В связи с этим очень интересны особенности мозга, характера и главное воспитания Линуса. Просто уникальные возможности в подъеме в одиночку кода, просто фантастического по своей массе(вначале десятки, а потом сотни тысяч строк), и доведения его до какого-то окончательного и вполне надежно работающего состояния, что просто не посильно огромному большинству других кодеров и говнокодеров. Здесь надо еще учесть такой человеческий феномен, что чем более опытным становится кодер — тем меньше он обычно пишет, т.е. ему просто становится лень, он наглеет/толстеет/буреет с точки зрения радотодателя или становится не пишущим гуру.
+1
… чем более опытным становится кодер — тем меньше он обычно пишет <...> становится не пишущим гуру.
Такой уровень называется system architect — системный архитектор, нечто вроде генерального конструктора. И дело здесь не в лени, такая должность неизбежно появляется в больших проектах.
Другие аналогии — это режиссёр, или дирижёр, или спортивный тренер. Они не играют сами, но знают, как должны играть другие. Впрочем, Торвальдс — играющий тренер.
+3
Само ядро Windows NT тоже практически в одиночку написано вот этим мега-челом. Возможно потому, что период говнокодера он прошел еще в 70-х, тем более ему было у кого учиться — он работал в DEC.

Есть мнение, что system architect — это просто обычный паразит и даже вредитель. Каких я видел в россии — это или говнокодер, быстро пролезжий по карьерной лестнице; бывший студент начитавшийся умных книжек — псевдо-гуру, но весьма активный и с хорошо подвешенным языком или просто идиот со связями/блатом/родственниками. Т.е. типичный нач.отдела, зам или директор в любой отрасли народного барыжного/бюрократического хоз-ва россии.
0
Есть мнение, что system architect — это просто обычный паразит и даже вредитель.
Тогда это не системный архитектор, а паразит и вредитель, занимающий должность системного архитектора.
+2
Есть мнение, что system architect — это просто обычный паразит и даже вредитель.
В любой работе есть люди делающие ее хорошо и есть люди делающие ее плохо.

P.S. меня чуть ли не силком выпихнули на позицию системного архитектора с позиции обычного синьора (даже не тимлида). просто я оказался самым опытным и единственным способным тянуть эту работу. и да, периодически я все еще пишу код сам, когда у меня остается на это время, учитывая, что на мне висят несколько проектов.
0
Военно-историческая новелла на близкую тему:
«Трассировка и раскладка кабелей на компьютере».
0
Просто уникальные возможности в подъеме в одиночку кода
Нет, не уникальные. Да и вообще это больше вопрос самодисциплины и правильной организации процесса. Что, следует отметить, тоже произошло далеко не сразу и именно самостоятельное тягание длилось не так долго.
0
И он явно перемудрил со своей ОС GNU и сам в итоге запутался в ней(горе от ума)
Стоит заметить, что ОС он таки и сделал. Линукс — это только ядро, солидная часть, но не вся ОС.
0
Интересно, что в 1992 г. в споре с Линусом сторонник микроядра проф. Таненбаум говорит что:
через 5 лет все будут пользоваться свободной GNU на компьютерах SPARCstation-5 мощностью 200 MIPS с памятью 64 мегабайт
вместо «тупиковой» Linux, жестко привязанной тогда к i386, т.е. он реально расчитывал на портируемое микроядро ОС GNU от Столмена.
0
Неудивительно, Таненбаум вообще сторонник микроядерной архитектуры. Впрочем, как показало время, свое микроядро он до юзабельного состояния допилил раньше, чем GNU.
0
Сложно что-то конкретное процетировать или предложить, по этому ограничусь следующим.
Проще это сделать, если создать функцию с пустыми командами.
Проче и недопустимее. Посмотрите аппноуты от производителя как создавать загрузчики и прошивки прогграмм ориентированные на работу с загрузчиком. Для этих целей применяется линкер (для стм8 я описывал как делать, и загрузчик в том числе). С его помощью можно настроить адреса (области для загрузчика и для кода), и тогда у вас будет возможность применить ещё и предусмотренный в МК механизм защиты загрузчика.
+2
Там еще такое есть:
Там будет строка примерно такого содержания — «Reset_Handler 0x08001421 Thumb Code»
Значит переходить нужно на 0x08001421.
Тоже безобразие.
+1
Именно к этой фразе относится высказывание про адреса, но я не вижу смысла цитировать весь пост.
0
То адреса секций, точка и метод передачи управления — несколько отдельный вопрос.
0
Да уж, сегменты не просто так придумывали.з.
0
Не жирно ли хекс передавать их хранить? Оперативка не бесконечная =) *тем более 300 строк — ни о чём*
А ещё не проверяется couBaits_toFLASH (с ответом мастеру), переполнение буфера можно ждать, если прошивка будет иметь более 315 строк.

И я вижу нехороший косяк — если хоть одна строка хекса не дойдёт, а команда на прошивку «Wr_to_F_end» придёт, основную прошивку вы убьёте. И дальше я вижу кусок металлолома вместо прибора. А не дойти оно может запросто, это ж Ethernet и UDP. Контрольную сумму нужно проверять и дополнительно после приёма всех кусков прошивки, от целого файла, вне зависимости от того, какие команды идут от мастера! Если кто-то по дурости или случайно пришлёт эту команду и если прошивки готовой нет в буфере, надо слать нафиг мастера.

И по поводу архивов — лучше, если все генерируемые компилятором файлы будут удалены, может, кроме прошивки =) Ну и валятся в отдельную папочку, а не к исходникам…

s019.radikal.ru/i614/1307/7e/2ffb421ee9c3.png — код и должен так гулять?=)
+2
goto? В С++? Нехорошо.
0
Ну я так понимаю, там это можно заменить на while() по ходу дела. Но это видимо, из-за того, то ассемблер был исходным языком, а си уже вторым…
+1
Друзья-товарищи :)
Касательно-названий адресов, уж простите меня :)
Только вот вот отучился от транслита в названиях.
Учту и в следующий раз буду пользовать GoogleTranslate.
Вышка есть, но совсем не московская. С преподами далекими от своих специализаций.
Любую критику приветствую.
35 т.р. потому, что Москве совсем недавно…
0
ищите на хедхантере тыщ от 70 хотя бы.
+1
Иди к барыгам в ремонтники, они тебя научат не бояться тонких электронных технологий. Можно зашибать хорошие деньги.
-1
хочу пока сделать так: стартую в бутлоадер (в нем ничего не делаю ) дале просто переключаюсь в основную программу.
бутлоадер
в линкере ROM star: 0x08000000.
int main(void) 
{   .....
    #define ApplicationAddress  0x0800f5f1 //адрес Reset_Handler смотрю в .map основной  программы                               
    typedef  void (*pFunction)(void);
    pFunction Jump_To_Application;
    uint32_t JumpAddress;

    if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)    
    { 
      JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);                 
      Jump_To_Application = (pFunction) JumpAddress;                            
      __set_MSP(*(__IO uint32_t*) ApplicationAddress);                          
      Jump_To_Application();                                                    
    }
    while (1) 
    {
        GPIO_SetBits(GPIOC, GPIO_Pin_8);
        Delay(0x7FFFF);
        GPIO_ResetBits(GPIOC, GPIO_Pin_8);
        Delay(0x7FFFF);
    }
}
основная программа:
в линкере ROM star: 0x0800F000
int main(void) 
{
    __disable_interrupt();                                                      
    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0xf5f1);                            
    .....
    while (1) 
    {
        GPIO_SetBits(GPIOC, GPIO_Pin_9);
        Delay(0x7FFFF);
        GPIO_ResetBits(GPIOC, GPIO_Pin_9);
        Delay(0x7FFFF);
    }
}

В итоге if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000) попадаю в while ( Помогите разобраться
0
  • avatar
  • VIC
  • 07 июля 2013, 13:18
А чего ты еще ожидал? Сам посмотри, что получается при операции 0x0800f5f1 & 0x2FFE0000.
Ну и опять же, подставлять в бутлоадер адрес из линкера — не лучшая идея. Потом ты обновишь основную прошивку, в ней новый адрес точки входа… А в бутлоадере забит хардкодом старый, и что делать?
Обычно задача решается расположением в фиксированном месте основной прошивки таблицы векторов, из которой бутлоадером вызывается нужный вектор (в простейшем случае только один — точка входа, но при желании их может быть и больше).
0
Спасибо.
Я же не так делаю 0x0800f5f1 & 0x2FFE0000, а беру значание по адресу ApplicationAddress & 0x2FFE0000
Проверяем, есть ли что-нибудь по адресу там должно лежать значение SP для приложения, его кладет линкер.
bootloader project.rar
0
Я же не так делаю 0x0800f5f1 & 0x2FFE0000, а беру значание по адресу ApplicationAddress & 0x2FFE0000
Тьфу ты, действительно. Запутался в обилии скобок и звездочек.
0
Не подскажете в чем проблема?
0
А таблица векторов и Reset_Handler располагаются в разных адресах, вы же адрес стека пытаетесь найти этим хитрым способом?

*я не очень въехал в эти конструкции*
0
Я бы не полагался на адреса из линкера. Лучше поместить таблицу векторов, вызываемых бутлоадером, по фиксированному адресу и проверять ее наличие (можно по magic-полю). Можно в качестве оной использовать таблицу векторов прерываний, опять же разместив ее по фиксированному адресу — проверять ее наличие и прыгать на RESET, а дальше прошивка сама переключит прерывания на эту таблицу.
0
Как это можно сделать в Keil?
0
Понятия не имею. Можно посмотреть, как сделано у других, в стартап-файлах (собсна, именно их скорее всего и потребуется править) и примерах самого кейла, а также покурить документацию. Для задания абсолютного адреса объекта обычно используется директива с названием в духе origin (бывают и сокращения вроде org, в Delphi аналогичная директива называется absolute).
Ну а вся программа в сборе размещается по адресам выше секции бутлоадера с помощью настроек линкера.
А вообще желательно посмотреть готовые примеры для конкретной среды и чипа — в примерах от среды, от производителя чипа, а также в аппнотах.
0
запустил ) Вот что нужно подправить в основной программе:
в линкере
intvec_start:  0x0800f5f1
ROM star: 0x0800f5f1
0
В Кейле можно определить регионы памяти в свойствах проекта или в спец.файле, и в свойствах каждого файла выбирать, в коем регионе код будет располагаться (так и в оперативку код запихать можно, просто указав, что пихаем его в IRAM).
0
спасибо
0
Спасибо. Немного подправил.
Хочется заметить, что такое решение бутлоадера коммерчески малопригодно.
Прошивка передается в открытую (хоть без бутлоадера она ничто, но все же).
Передавать все в ASCII тоже не самая лучшая идея, но зато так более чем наглядно )
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.