Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как программно загнать STM32 в бутлоадер?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3
Salamander
Пока выяснил вот что - бутлодер от прошивки не портится. Но пишется во флеш совсем не то, что пишется, если программировать Keilом
Salamander
Мне кто-нибудь может пояснить, что за ерунда?
Test_project.hex - то, что генерирует keil
Зашиваем keilом - работает, скачиваем с помощью FlashLoader - получаем right.hex - он отличается.
Зашиваем бутлодером получаем wrong.hex

Как понять логику, если записываем, все записывается правильно, но когда этот правильный код скачиваем - получаем другое...
P.S. скачивал не все, у нажные сектора, начиная с 0x08003000
Salamander
У меня мысли кончились...
Кто-нибудь работал именно с AN2577 ?
Получается грузить только встроенным бутлодером или через Keil.
Предложенный в AN2577 бутлодер грузит во флеш фигню.
doom13
А сама запись/чтение данных в/из флэша нормально работает? Может начать с этого?

Вообще, на первый взгляд, данные в файлах TEST_Project.hex и right.hex одинаковы, отличие только в разном количестве байт в строке, т.е. "скачиваем с помощью FlashLoader" то, что и залили программатором.

А вот right.hex и wrong.hex отличаются. Ищите ошибку где-то в записи во флэш загрузчиком, возможно в приёме данных или отправке с хоста.
Salamander
Ваша правда, test и right одинаковы. Я просто сравнивал их средствами редактора, а в нем сравнение шло тупо побаитово, не вникая в суть записи.
Чуется мне, что собака где-то в привязке к железу зарыта, точнее к архитектуре памяти. В бутлодере полно дефайнов на разные случаи жизни, но возможео разработчики что-то и упустили. Бот кстати под сотую серию, у меня же 103ret6
doom13
Цитата(Salamander @ Mar 14 2015, 22:40) *
Чуется мне, что собака где-то в привязке к железу зарыта, точнее к архитектуре памяти. В бутлодере полно дефайнов на разные случаи жизни, но возможео разработчики что-то и упустили.

Ну если это прогеры-индийцы-студенты то возможно, в либах ТI частенько встречались баги.
Salamander
Скажите, а во Flаsh должна попадать только та часть строки, которая байты содержит? Длина строки, тип записи - это все обработчиком проглатывается?
doom13
Цитата(Salamander @ Mar 14 2015, 22:47) *
Скажите, а во Flаsh должна попадать только та часть строки, которая байты содержит? Длина строки, тип записи - это все обработчиком проглатывается?

Да.
Salamander
Цитата(doom13 @ Mar 14 2015, 22:46) *
Ну если это прогеры-индийцы-студенты то возможно, в либах ТI частенько встречались баги.


Ну знаете, я не склонен думать, что в программе HyperTerminаl закралась ошибка. Это широко применяемый продукт. А вот аппликуха, испытанная не на всех контроллерах вполне может содержать баг.
doom13
Цитата(Salamander @ Mar 14 2015, 22:51) *
Ну знаете, я не склонен думать, что в программе HyperTerminаl закралась ошибка. Это широко применяемый продукт. А вот аппликуха, испытанная не на всех контроллерах вполне может содержать баг.

Это про пример загрузчика было сказано.
Salamander
Есть вопрос, он конечно ближе к разделу начинающих, но я не буду плодить темы.
Вот функция приема данных
CODE
int32_t Ymodem_Receive (uint8_t *buf)
{
uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;

/* Initialize FlashDestination variable */
FlashDestination = ApplicationAddress;

for (session_done = 0, errors = 0, session_begin = 0; wink.gif
{
for (packets_received = 0, file_done = 0, buf_ptr = buf; wink.gif
{
switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT))
{
case 0:
errors = 0;
switch (packet_length)
{
/* Abort by sender */
case - 1:
Send_Byte(ACK);
return 0;
/* End of transmission */
case 0:
Send_Byte(ACK);
file_done = 1;
break;
/* Normal packet */
default:
if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
{
Send_Byte(NAK);
}
else
{
if (packets_received == 0)
{
/* Filename packet */
if (packet_data[PACKET_HEADER] != 0)
{
/* Filename packet has valid data */
for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH)wink.gif
{
file_name[i++] = *file_ptr++;
}
file_name[i++] = '\0';
for (i = 0, file_ptr ++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH)wink.gif
{
file_size[i++] = *file_ptr++;
}
file_size[i++] = '\0';
Str2Int(file_size, &size);

/* Test the size of the image to be sent */
/* Image size is greater than Flash size */
if (size > (FLASH_SIZE - 1))
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
return -1;
}

/* Erase the needed pages where the user application will be loaded */
/* Define the number of page to be erased */
NbrOfPage = FLASH_PagesMask(size);

/* Erase the FLASH pages */
for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(FlashDestination + (PageSize * EraseCounter));
}
Send_Byte(ACK);
Send_Byte(CRC16);
}
/* Filename packet is empty, end session */
else
{
Send_Byte(ACK);
file_done = 1;
session_done = 1;
break;
}
}
/* Data packet */
else
{
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
RamSource = (uint32_t)buf;
for (j = 0;(j < packet_length) && (FlashDestination < ApplicationAddress + size);j += 4)
{
/* Program the data received into STM32F10x Flash */
FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);

if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource)
{
/* End session */
Send_Byte(CA);
Send_Byte(CA);
return -2;
}
FlashDestination += 4;
RamSource += 4;
}
Send_Byte(ACK);
}
packets_received ++;
session_begin = 1;
}
}
break;
case 1:
Send_Byte(CA);
Send_Byte(CA);
return -3;
default:
if (session_begin > 0)
{
errors ++;
}
if (errors > MAX_ERRORS)
{
Send_Byte(CA);
Send_Byte(CA);
return 0;
}
Send_Byte(CRC16);
break;
}
if (file_done != 0)
{
break;
}
}
if (session_done != 0)
{
break;
}
}
return (int32_t)size;
}


Есть там такая строки
Код
memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
                  RamSource = (uint32_t)buf;
                  for (j = 0;(j < packet_length) && (FlashDestination <  ApplicationAddress + size);j += 4)
                  {
                    /* Program the data received into STM32F10x Flash */
                    FLASH_ProgramWord(FlashDestination, *(uint32_t*)RamSource);

                    if (*(uint32_t*)FlashDestination != *(uint32_t*)RamSource)
                    {
                      /* End session */
                      Send_Byte(CA);
                      Send_Byte(CA);
                      return -2;
                    }
                    FlashDestination += 4;
                    RamSource += 4;
                  }


Как мне данные из buf вытащить в окно watch, чтобы там был массивчик разворачивающийся? Я попробовал добавть - пишет cannot evaluate....
doom13
Цитата(Salamander @ Mar 14 2015, 23:50) *
Как мне данные из buf вытащить в окно watch, чтобы там был массивчик разворачивающийся? Я попробовал добавть - пишет cannot evaluate....

У Вас buf это указатель на uint8_t (uint8_t *buf). Чтобы просматривать значения, надо в watch вытащить buf[0], buf[1] и т.д., но это не удобно.
Создайте временный массив uint8_t temp_array[length], скопируйте в него содержимое buf нужной длины, в watch сможете просматривать все элементы temp_array (ещё смотрите, чтобы оптимизация была отключена, возможно проблема изначально в оптимизации, но не каждая среда может просмотреть массив через указатель на первый элемент).
Salamander
Я из интереса добавил парочку buf[0],buf[1] - пишет cannot evaluate. ПРинесет ли пользу заморачивание с временным массивом?

Если вытащить в watch (uint32_t)buf то отображается массив с одним элементом, имеющим одно и то же значение.
doom13
Цитата(Salamander @ Mar 15 2015, 01:19) *
Я из интереса добавил парочку buf[0],buf[1] - пишет cannot evaluate. ПРинесет ли пользу заморачивание с временным массивом?

Попробуйте, объявить массив нужной длины и добавить одну memcpy() - это ведь не сложно.

Цитата(Salamander @ Mar 15 2015, 01:19) *
Если вытащить в watch (uint32_t)buf то отображается массив с одним элементом, имеющим одно и то же значение.

Ну это Вы вытащили адрес памяти на которую ссылается buf (адрес первого элемента), а не сам элемент. Чтобы просмотреть значение надо тогда так:
*(uint32_t *)buf
Salamander
Код
uint8_t temp_array[1024];
memcpy(temp_array, packet_data + PACKET_HEADER, packet_length);

Работает.
ОБращает на себя внимание, что все символы, которые в исходном файле 0x31 в массиве оказываются 0x01
В остальном - пробежался по примерно 200 байт - вроде бы сходится.

Кстати, этот почти похожий код получается если передавать бинарный файл. Если подсунуть HEX, то как раз вылазит то, что появлялось в файле, который я выкладывал под именем wrong.hex

Код 0x31 - не несет ли он какого-то сакрального смысла в протоколе YModem?
doom13
Меня больше смущает соответствие hex 31 и char 1, но как-то связать это не получается.
Salamander
Поставил код "ловушку" для символа 0x31 - он принципиально не пролазит. Его просто нет в пакетах данных.
Что за шайтан?
A. Fig Lee
Цитата(doom13 @ Mar 14 2015, 18:07) *
Меня больше смущает соответствие hex 31 и char 1, но как-то связать это не получается.

Как "не получается"?
0х31 == '1'
Salamander
Все ближе подбираюсь к разгадке.
Как выяснилось - в бинарнике действительно на месте 0x31 был 0x01. И он почему-то не обновился. Перекомпилировал - получил правильный файл.
Как бы почти "ура" - прошивка не бьется. Но только почему-то перепрошивается через раз - беру новый бинарник (в нем светодиод мигает с другой частотой) прошиваю - вроде бы шьется, но диод моргает по прежнему. В общем, какие-то глюки, то ли с кейлом, то ли с бутлодером.
РАзберусь завтра...

у меня перестал писаться axf файл (из него собирался бинарник). Я его удалил - кейл не ругается и новый не создает
hex2bin - не работает, пишет *** Error: CreateProcess failed, Command: 'hex2bin ....

Есть какой-нибудь идеологически правильный способ получать бинарник на выходе?

.......................................................
Наконец-то!!!!
Все пишется!!
Завтра на свежую голову погоняю код туда-сюда..
doom13
Цитата(A. Fig Lee @ Mar 15 2015, 02:35) *
Как "не получается"?
0х31 == '1'

Если читать внимательно то
Цитата(doom13 @ Mar 15 2015, 02:07) *
Меня больше смущает соответствие hex 31 и char 1 ...

равно
Цитата(A. Fig Lee @ Mar 15 2015, 02:35) *
0х31 == '1'

scifi
Рановато вам с загрузчиком баловаться, имхо. В азах плаваете, мягко говоря.
Pilatus
Цитата(AVNN @ Mar 7 2015, 22:51) *
В заводской загрузчик на STM32F205 вхожу так:
Код
#define BOOTLOADER_ADDR 0x1FFF0000

typedef  void (*pFunction)(void);
pFunction Jump_To_Bootloader;
uint32_t JumpAddress;

JumpAddress = *(__IO uint32_t*) (BOOTLOADER_ADDR + 4);
Jump_To_Bootloader= (pFunction) JumpAddress;
/* Initialize Stack Pointer */
__set_MSP(*(__IO uint32_t*) BOOTLOADER_ADDR );
Jump_To_Bootloader();


На других STM-ках возможно что-то подобное можно сделать.



Что-то у меня не получается. Контроллер STM32F103RET6
Доходит до Jump_To_Bootloader() (брейкпоинтмами проверял) а дальше тишина. У меня бутлодер по адресу 0x08000000 (Я и этот адрес подставлял и тот что в предложенном коде) - бутлодер не запускается. Точнее не запускается все то, что он должен расшевеливать (у меня для отладки диод моргает). Если остановить программу (я отлаживаю в KEIL), то показывает адрес 0x08000182. Так значит он все-таки прыгает на начало флеша?
Пробовал даже таблицу векторов предварительно обратно переносить - не получается.
Как мне понять, что происходит?

Из будтлодера же прыгает в основную программу нормально

Код
    /* Test if user code is programmed starting from address "ApplicationAddress" */
    if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
    {
      /* Jump to user application */
      JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) ApplicationAddress);
      
      Jump_To_Application();

    }
Pilatus
Ну... практически разобрался.
Контроллер оказывается заходит в бутлодер, но виснет на первой же строчке RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
Путем проб и ошибок выяснилось, что зависание в бутлодере происходит в том случае, если в основной программе, откуда произошел прыжок в бутлодер, включено прерывание таймера 2 по переполнению (ну может быть еще какие возможные условия есть, но у меня причиной было это).
Если перед прыжком в бутлодер отключить прерывание, то все работает.

Но все же гложет меня вопрос - почему так? В бутлодере таймеры не используются, конфликтовать не с чем. Я поэкспериментировал и с самим прерыванием от таймера - удалил его содержимое, даже сделал так, чтобы он переполнялся как можно реже (секунда) - все равно проблемы.
x893
Таблица векторов меняется в бутлодере ?
После смены таблицы и разрешенном прерывании - куда будет совершен переход при прерывании ?
Pilatus
Цитата(x893 @ Jan 8 2017, 00:13) *
Таблица векторов меняется в бутлодере ?
После смены таблицы и разрешенном прерывании - куда будет совершен переход при прерывании ?


Об этом я подумал в первую очередь, не помогло.
Сейчас попробовал еще раз - тот же результат. Может я не так пробую?
В основной программе я переношу таблицу так
Код
        __set_PRIMASK(1);
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);  
__set_PRIMASK(0);


в бутлодере в самом начале main()
Код
        __set_PRIMASK(1);
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);  
__set_PRIMASK(0);


Что ему не так?
SSerge
Цитата(Pilatus @ Jan 8 2017, 12:40) *
Что ему не так?

Для нормального запуска нужно восстановить состояние которое было сразу после ресета.
Самый простой способ добиться этого - устроить ресет.
Сделать это Вам поможет функция void NVIC_SystemReset(void) из файла core_cm3.h.
Pilatus
Цитата(SSerge @ Jan 8 2017, 13:02) *
Для нормального запуска нужно восстановить состояние которое было сразу после ресета.
Самый простой способ добиться этого - устроить ресет.
Сделать это Вам поможет функция void NVIC_SystemReset(void) из файла core_cm3.h.

Спасибо! Самое то!
A.Lex
Подниму тему.
Пытаюсь сделать bootloader по примеру AN4657-STM32Cube_IAP_using_UART, но для STM32F100CB.
И не могу разобраться с Y-MODEMом. Терминалка Tera Term, не могу загрузить bin-файл.
В дебаге докопался, что status = HAL_UART_Receive(&huart1, &char1, 1, RX_TIMEOUT) при попытке загрузки все время HAL_BUSY.
Кто нибудь сталкивался с подобной проблемой?
A.Lex
Победить HAL не смог, сделал на SPL по AN2557
Lagman
Цитата(A.Lex @ Jul 12 2017, 11:04) *
Победить HAL не смог, сделал на SPL по AN2557

Хоть и другое семейство, я тонкостей семейств не знаю, но вот в этом сообщении https://electronix.ru/forum/index.php?showt...t&p=1412512 есть совет для stm32f0xx
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.