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

LPC4337. Init IAP. Status Code - случайная величина.

Добрый день, коллеги!

Несколько дней ищу баг. Функция Init IAP под документации должна возвращать только CMD_SUCCESS. И так происходит в проекте, который я делал несколько лет назад. Сейчас использую эту функцию в другом проекте, сначала получал 0, т.е. CMD_SUCCESS. А пару дней назад обнаружил, что возвращается 0x55. В списке статусов такого кода нет. Естественно - баг, подумал я. Если опустить кучу экспериментов, то я стал вызывать в конечном счёте Init IAP буквально сразу же после ResetHandler и настройки PLL на 204 МГц. И снова получил 0x55. Через пару часов я вспомнил, что инилициализурю в startup весь стек сигнатурой 0xaa55aa55. Поменял ради интереса на 0xaa77aa77. И Init IAP стала возвращать 0x77. Как так??? Возникает ощущение, что из-за того, что эта функция должна возвращать всегда CMD_SUCCESS, NXP как бы забыла добавить в код своего загрузчика возврат кода. В моём проекте сейчас - минимум. Вроде бы и ошибок уже негде наставить. Как проверить, это моя ошибка, или IAP Init не возвращает результат?

По условия трудового договора я обязан использовать стороний код для обращения к IAP. Вот эта функция:

 /* Initializes and prepares the flash for erase and write operations */
uint8_t Chip_IAP_Init(void)
{
	uint32_t command[5], result[4];

	command[0] = IAP_INIT_CMD;
	iap_entry(command, result);

	return result[0];
}

Всё остальное объявлено в заголовочнике так:

Spoiler
/* IAP command definitions */
#define IAP_INIT_CMD								49	/*!< Initializes and prepares the flash for erase and write operations */
#define IAP_PREWRRITE_CMD           50	/*!< Prepare sector for write operation command */
#define IAP_WRISECTOR_CMD           51	/*!< Write Sector command */
#define IAP_ERSSECTOR_CMD           52	/*!< Erase Sector command */
#define IAP_BLANK_CHECK_SECTOR_CMD  53	/*!< Blank check sector */
#define IAP_REPID_CMD               54	/*!< Read PartID command */
#define IAP_READ_BOOT_CODE_CMD      55	/*!< Read Boot code version */
#define IAP_COMPARE_CMD             56	/*!< Compare two RAM address locations */
#define IAP_REINVOKE_ISP_CMD        57	/*!< Reinvoke ISP */
#define IAP_READ_UID_CMD            58	/*!< Read UID */
#define IAP_ERASE_PAGE_CMD          59	/*!< Erase page */
#define IAP_SET_BOOT_FLASH          60	/*!< Set active boot flash bank */
#define IAP_EEPROM_WRITE            61	/*!< EEPROM Write command */
#define IAP_EEPROM_READ             62	/*!< EEPROM READ command */

/* IAP response definitions */
#define IAP_CMD_SUCCESS             0	/*!< Command is executed successfully */
#define IAP_INVALID_COMMAND         1	/*!< Invalid command */
#define IAP_SRC_ADDR_ERROR          2	/*!< Source address is not on word boundary */
#define IAP_DST_ADDR_ERROR          3	/*!< Destination address is not on a correct boundary */
#define IAP_SRC_ADDR_NOT_MAPPED     4	/*!< Source address is not mapped in the memory map */
#define IAP_DST_ADDR_NOT_MAPPED     5	/*!< Destination address is not mapped in the memory map */
#define IAP_COUNT_ERROR             6	/*!< Byte count is not multiple of 4 or is not a permitted value */
#define IAP_INVALID_SECTOR          7	/*!< Sector number is invalid or end sector number is greater than start sector number */
#define IAP_SECTOR_NOT_BLANK        8	/*!< Sector is not blank */
#define IAP_SECTOR_NOT_PREPARED     9	/*!< Command to prepare sector for write operation was not executed */
#define IAP_COMPARE_ERROR           10	/*!< Source and destination data not equal */
#define IAP_BUSY                    11	/*!< Flash programming hardware interface is busy */
#define IAP_PARAM_ERROR             12	/*!< nsufficient number of parameters or invalid parameter */
#define IAP_ADDR_ERROR              13	/*!< Address is not on word boundary */
#define IAP_ADDR_NOT_MAPPED         14	/*!< Address is not mapped in the memory map */
#define IAP_CMD_LOCKED              15	/*!< Command is locked */
#define IAP_INVALID_CODE            16	/*!< Unlock code is invalid */
#define IAP_INVALID_BAUD_RATE       17	/*!< Invalid baud rate setting */
#define IAP_INVALID_STOP_BIT        18	/*!< Invalid stop bit setting */
#define IAP_CRP_ENABLED             19	/*!< Code read protection enabled */

/* IAP_ENTRY API function type */
typedef void (*IAP_ENTRY_T)(unsigned int[5], unsigned int[4]);


/* Pointer to ROM IAP entry functions */
#define IAP_ENTRY_LOCATION        (*((volatile uint32_t *) 0x10400100))


#define IAP_FLASH_BANK_A                        0
#define IAP_FLASH_BANK_B                        1

#define IAP_FLASH_BANK_A_BASE                        0x1A000000
#define IAP_FLASH_BANK_B_BASE                        0x1B000000


static inline void iap_entry(unsigned int cmd_param[], unsigned int status_result[])
{
	((IAP_ENTRY_T) IAP_ENTRY_LOCATION)(cmd_param, status_result);
}

Может быть у меня глаз замылился, и я не вижу очевидного ляпа? Буду благодарен за любой пинок в нужном направлении)

P.S. Остальные нужные функции типа подготовки секторов, записи секторов работают отлично. Кстати, если опустить проверку возвращаемого значения Init IAP, то всё остальное всё равно работает нормально. И те функции возвращают надлежащие коды! Блин, я запутался....

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


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

Под отладчиком увидеть онлайн-дизасм области iap_entry() невозможно? Вернее, то место, на которое указывает IAP_ENTRY_LOCATION.

P.S. Быстрогугление показывает, что Chip_IAP_Init() у кого-то не возвращает ничего... Раз, два.

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


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

1 час назад, haker_fox сказал:

Как проверить, это моя ошибка, или IAP Init не возвращает результат?

По условия трудового договора я обязан использовать стороний код для обращения к IAP. Вот эта функция:

 /* Initializes and prepares the flash for erase and write operations */
uint8_t Chip_IAP_Init(void)
{
	uint32_t command[5], result[4];

	command[0] = IAP_INIT_CMD;
	iap_entry(command, result);

	return result[0];
}

Все ли условия вызова IAP выполнены правильно?

Например: вышеотквоченный код вызывается откуда - FLASH/RAM? Если 1-е, то не вижу запрета прерываний на время вызова. Или у вас все ISR в ОЗУ расположены? И таблица векторов прерываний - тоже в ОЗУ?

2-е: Выполнены ли все требования по используемой IAP ОЗУ? Эти требования есть в юзер-мануале.

Ваш код вызова IAP выглядит слишком примитивным. Вот как аналогичный вызов выглядит в одном из моих проектов:

struct IapData {
  u32 cmd;
  u32 in[4];
  u32 status;
  u32 out[4];
};
__no_init union {
  ...
  IapData volatile iap;
} static d0 @ ".dma";

//#pragma inline=never
static uint Iap(uint cmd)
{
  __no_init static u32 ivec[16] @ ".intvecRam";
  ASSERT_STATIC(ncell(NVIC.DIS) == ncell(NVIC.ENA));
  u32 nvicSav[ncell(NVIC.DIS)];
  d0.iap.cmd = cmd;
  int i = ncell(ivec) - 1;
  do ivec[i] = (u32)&IsrDummyRam;
  while (--i);
  ivec[15] = (u32)&IsrSysTick;
  i = ncell(NVIC.DIS) - 1;
  do {
    nvicSav[i] = NVIC.DIS[i];
    NVIC.DIS[i] = ~0;
  } while (--i >= 0);
  ivec[0] = NVIC.VTABLE;
  NVIC.VTABLE = (u32)&ivec[0];
  ptrIAP(&d0.iap.cmd, &d0.iap.status);
  NVIC.VTABLE = ivec[0];
  i = ncell(NVIC.DIS) - 1;
  do NVIC.ENA[i] = nvicSav[i];
  while (--i >= 0);
  return d0.iap.status;
}

extern "C" __ramfunc void IsrDummyRam() {}

extern "C" __ramfunc void IsrSysTick()
{
  sysTimer++;
  if (wdiSyst) WDI_TOGGLE();
}

Сравните. У меня на время вызова IAP должен оставаться активен один ISR - SysTick. Поэтому его ISR, как видно, расположен в ОЗУ, а все остальные прерывания - запрещаются.

Вот как выглядят требования резервирования ОЗУ для IAP в .icf:

define region RAM_regionA0    = mem:[from 0x10000020 to 0x10007EFF]; //main RAM - 32 байта вверху RAM для IAP
define region RAM_regionA1    = mem:[from 0x10007C00 to 0x10007CFF]; //ISR table in RAM
define region RAM_regionA2    = mem:[from 0x10007D00 to 0x10007FDF]; //code in RAM - 32 байта внизу RAM для IAP
define region RAM_regionB     = mem:[from 0x2007C020 size 0x7FC0]; //AHB RAM - по 32 байта на каждом конце RAM - для IAP
...

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


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

On 5/5/2023 at 2:22 PM, Arlleex said:

Под отладчиком увидеть онлайн-дизасм области iap_entry() невозможно?

Да. Но пока не хочется заниматься отладкой кода без исходников.

On 5/5/2023 at 2:22 PM, Arlleex said:

Chip_IAP_Init() у кого-то не возвращает ничего..

Аааа, понятно. Вы искали по названию этой функции. Я же искал по словам "iap init doesn't return status code" и т.п. вариациям слов.

On 5/5/2023 at 3:15 PM, jcxz said:

Например: вышеотквоченный код вызывается откуда - FLASH/RAM? Если 1-е, то не вижу запрета прерываний на время вызова. Или у вас все ISR в ОЗУ расположены? И таблица векторов прерываний - тоже в ОЗУ?

2-е: Выполнены ли все требования по используемой IAP ОЗУ? Эти требования есть в юзер-мануале.

Прерывания запрещены. 

Для резервирования области памяти, используемой IAP есть такое объявление массива:

__root static uint8_t s_reservedForIAP[16]@ 0x10089ff0;

Проверил по map, всё ОК.

On 5/5/2023 at 3:15 PM, jcxz said:

Вот как такой вызов выглядит в одном из моих проектов:

Поизучаю Ваш код! Спасибо!

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


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

17 минут назад, jcxz сказал:
uint32_t command[5], result[4];

У вас почему-то result[4]. Это правильно? Не смотрел как там в LPC43xx, но в LPC17xx (для которого мой код) должно быть больше. См. мой пример.

Открыл мануал LPC43xx. Вижу в нём:

Цитата

2. Define data structure or pointers to pass the IAP command table and result table to 
the IAP function:
unsigned int command_param[5];
unsigned int status_result[5];

У вас result[] на 1 меньше.

Кроме того - они у вас не объединены в структуру почему-то. Почему вы думаете, что компилятор расположит их в нужном вам порядке в памяти, а в не в обратном? Это всё равно что, кидая монетку быть уверенным, что всегда выпадет решка.

16 минут назад, haker_fox сказал:

Для резервирования области памяти, используемой IAP есть такое объявление массива:

__root static uint8_t s_reservedForIAP[16]@ 0x10089ff0;

Опять смотрим в мануал:

Цитата

IAP commands which result in a flash write/erase operation use 32 bytes of space in the top portion of the 
on-chip RAM for execution. The user program should not be using this space if IAP flash programming is permitted in the application.

Да, понятно, что IAP_INIT_CMD видимо не относится к командам "which result in a flash write/erase operation", но ведь у вас такая структура памяти применяется для вызова всех команд IAP? В том числе - и пишущих/стирающих флешь? Получается и это требование у вас не выполняется....

И почему Вы думаете, что 0x10089ff0 это: "top on-chip RAM"?

 

PS: Вы вообще мануал по IAP читали?  :unknw:

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


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

On 5/5/2023 at 3:20 PM, jcxz said:

У вас почему-то result[4]. Это правильно?

Неправильно. Должно быть 5 байт! Спасибо!

On 5/5/2023 at 3:20 PM, jcxz said:

Почему вы думаете, что компилятор расположит их в нужном вам порядке в памяти, а в не в обратном?

Поясните, пожалуйста. Почему компилятор должен разбить элементы массива в произвольном порядке? Это разве допустимо? Или он это может сделать, если увидит, что нет последовательного обращения к ячейкам массива, например в цикле? Или и в этом случае он волен наоптимизировать?))

Честно признаюсь, мне это и в голову не приходило. Правда. Не вру. С другой стороны, в UM они тоже не объединены в структуру. Почему? Или Вы что имеете в виду? Порядок элементов массива или сами массивы?

On 5/5/2023 at 3:20 PM, jcxz said:

Опять смотрим в мануал:

А о какой top on-chip RAM идёт речь? Так же несколько регионов? Как сделать правильные выводы?

On 5/5/2023 at 3:20 PM, jcxz said:

И почему Вы думаете, что 0x10089ff0 это: "top on-chip RAM"?

Это относится к этому:

image.thumb.png.75da9db55a661431044aabd32ba1907d.png

On 5/5/2023 at 3:20 PM, jcxz said:

PS: Вы вообще мануал по IAP читали?  

OFF: А это действительно нужно?😜 Никогда такой ерундой не занимался🙂

P.S. Прошу прощения за задержку с ответами. Вчера вспомнил неожиданно, что у меня дела. Пришлось срочно их выполнять.

On 5/5/2023 at 3:15 PM, jcxz said:

Вот как выглядят требования резервирования ОЗУ для IAP в .icf:

За таблицу отдельное спасибо! Но всё же из манула мне непонятно что нужно столько регионов резервировать. Там сказано всего лишь о двух.

Раз:

image.thumb.png.f1aa2db6b3a114ac8e68e568861cf942.png

Два:

image.thumb.png.e2cabf85cb944cd628d4e3c86c8f07df.png

И во втором случае мне непонятно, о каком регионе SRAM идёт речь...

 

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


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

39 минут назад, haker_fox сказал:

Неправильно. Должно быть 5 байт! Спасибо!

5 слов  :smile:

39 минут назад, haker_fox сказал:

Поясните, пожалуйста. Почему компилятор должен разбить элементы массива в произвольном порядке?

Я тут ошибся. Беру свои слова обратно. :smile:  В структуру объединять не обязательно.  

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

39 минут назад, haker_fox сказал:

А о какой top on-chip RAM идёт речь? Так же несколько регионов? Как сделать правильные выводы?

Два:

image.thumb.png.e2cabf85cb944cd628d4e3c86c8f07df.png

И во втором случае мне непонятно, о каком регионе SRAM идёт речь...

Вот об этом я и писал. 32 байта. И в мануале для LPC17xx (например) есть упоминание только об этих 32 байт, а о 16 байтах - нету. Если предположить, что код IAP во всех ARM LPC - одинаковый, то должны быть одинаковые требования для всех. Тем более что требования по передаче аргументов и возврату результатов для LPC17xx такие же, как в LPC43xx.

А о том, что такое "top of RAM" - я не знаю. Самые младшие адреса или самые старшие? Нигде это не указано. Также не указано - о каком регионе речь? На LPC17xx я пробовал поэкспериментировать и посмотреть - где же именно происходит порча. Но какие только команды IAP не вызывал - ни один из краёв ни одного из регионов ОЗУ не портился. Либо это требование излишнее, либо порча происходит только при определённых условиях, о которых ничего не известно и которые у меня не случились.

Поэтому в своём бутлоадере, использующем IAP, я просто зарезервировал по 32 байта с каждого конца каждого региона. На всякий случай. Тем более, что дефицита ОЗУ там нет.

 

PS: Сейчас пришло в голову ещё одно возможное объяснение ситуации с теми 32-ю байтами и почему я не увидел порчи: В мануале указано, что они используются для выполнения кода во время программирования/стирания флеша. Возможно IAP сохраняет их содержимое в стеке, копирует туда код, выполняет его и восстанавливает старое содержимое из стека.

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


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

Спасибо, коллеги! Кажется, ситуация выправилась. По крайней мере пока при ограниченном тестировании IAPInit возвращает 0.

Позволю себе задать ещё один вопрос. Во время работы IAP, как я заметил даже не во время программирования FLASH, если остановить отладчик, то IAR виснет. И в лог выдаёт это (прошу прощения за скрин, построчно долго копировать).

image.thumb.png.16ea948873f21d77aedbc484aa900e0d.png

Обычно потом отвисает и вываливается из отладки, либо приходится прибивать через диспетчер задач. Это только у меня, или явление нередкое и у других уважаемых коллег?

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


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

2 часа назад, haker_fox сказал:

Обычно потом отвивает и вываливается из отладки, либо приходится прибивать через диспетчер задач. Это только у меня, или явление нередкое и у других уважаемых коллег?

Где именно виснет? Внутри кода IAP (в ROM)? И при каком именно выполнении: обычном или пошаговом? И какой эмулятор? Какая версия IAR? WDT выключен? Какие права в MPU выставлены на область кода IAP (чтение/выполнение/...)?

 

Проверил у себя на IAR_7.80.4 + LPC1758 + JetLink SuperPro. Ни завис ни разу. Хоть при обычном выполнении кода IAP, хоть при пошаговом (протрассировал пошагово всю функцию чтения сер.номера (58)) начиная от её вызова до возврата в пользовательский код:

image.thumb.png.38c0c864272e01ebd813e23a269d4d50.png

image.thumb.png.9e278b66a6b961c35aba38e69a5bc75e.png

image.thumb.png.e23cad35a8e6e825c44d4abdaa9c63a3.png

везде шагает также как и по обычному коду. Всё ок.

 

PS: Может ваш эмулятор:

1) или не умеет аппаратные бряки?

2) или они запрещены?

3) или все израсходованы (превышено допустимое кол-во установленных в данный момент)?

А программные в ROM поставить невозможно. Потому и виснет при попытке поставить такой бряк.

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


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

26 minutes ago, jcxz said:

Внутри кода IAP (в ROM)?

Внутри.

26 minutes ago, jcxz said:

И при каком именно выполнении: обычном или пошаговом?

При обычном (F5).

26 minutes ago, jcxz said:

И какой эмулятор?

JetLink9.

27 minutes ago, jcxz said:

Какая версия IAR?

IAR 9.30.1.

27 minutes ago, jcxz said:

WDT выключен?

Выключен.

27 minutes ago, jcxz said:

Какие права в MPU выставлены на область кода IAP (чтение/выполнение/...)?

MPU не инициализирован.

28 minutes ago, jcxz said:

везде шагает также как и по обычному коду. Всё ок.

Спасибо, уже пища для раздумий.

28 minutes ago, jcxz said:

1) или не умеет аппаратные бряки?

Умеет.

29 minutes ago, jcxz said:

2) или они запрещены?

Простите, здесь не понял, где они могут быть запрещены?

29 minutes ago, jcxz said:

3) или все израсходованы (превышено допустимое кол-во установленных в данный момент)?

На момент зависания не более трёх BP установлено...

32 minutes ago, jcxz said:

Внутри кода IAP (в ROM)?

Внутри.

32 minutes ago, jcxz said:

И при каком именно выполнении: обычном или пошаговом?

При обычном (F5).

32 minutes ago, jcxz said:

И какой эмулятор?

JetLink9.

32 minutes ago, jcxz said:

Какая версия IAR?

IAR 9.30.1.

32 minutes ago, jcxz said:

WDT выключен?

Выключен.

32 minutes ago, jcxz said:

Какие права в MPU выставлены на область кода IAP (чтение/выполнение/...)?

MPU не инициализирован.

32 minutes ago, jcxz said:

везде шагает также как и по обычному коду. Всё ок.

Спасибо, уже пища для раздумий.

32 minutes ago, jcxz said:

1) или не умеет аппаратные бряки?

Умеет.

32 minutes ago, jcxz said:

2) или они запрещены?

Простите, здесь не понял, где они могут быть запрещены?

32 minutes ago, jcxz said:

3) или все израсходованы (превышено допустимое кол-во установленных в данный момент)?

На момент зависания не более трёх BP установлено...

Ну и что-то подобное стал замечать. Вроде все провода целые, комп перезагружал... Странно...

image.thumb.png.c51097b8673c5179da500e433d757128.png

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


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

1 час назад, haker_fox сказал:

Простите, здесь не понял, где они могут быть запрещены?

Я не пользуюсь IAR-ами старше 7.80.4, а у Вас - более новый. В новых может быть добавлена такая возможность. Предполагаю.

К тому же насколько знаю - лицензионные ключи в J-Link тоже могут ограничивать кол-во бряков.

1 час назад, haker_fox сказал:

Ну и что-то подобное стал замечать. Вроде все провода целые, комп перезагружал... Странно...

Тогда нужно разбираться в 1-ю очередь с этим. Или с проводами проблема или с питанием (может питание эмулятора недостаточное? точно есть 5V на входе?) или что-то вызывает сброс самого отлаживаемого девайса (или у него с питанием проблемы) или может частота для SWD выставлена слишком высокая. Вобщем - такого быть не должно.

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


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

19 hours ago, jcxz said:

Тогда нужно разбираться в 1-ю очередь с этим. Или с проводами проблема или с питанием

Сегодня утром настойчиво обратился к коллегам, разрабатывающим зарядное устройство. Выяснилось, что на приборе, выданном мне, барахлит система питания! Бррр... Подлатали, вроде пока полёт нормальный! Спасибо Вам!

 

Пользуясь случаем, ещё задам один вопрос по отладке. Все условия те же самые. Напомню, МК LPC4337 M4F. Если под отладчиком наступает условие сброса по переполнению WDT, отладка "виснет". Сам микроконтроллер непонятно в каком состоянии. Из-за висящего отладчика проверить не могу. Но без отладчика, WDT работает корректно, и сбрасывает МК. В UM не нашёл комментариев. Буду рад очередным подсказкам)

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


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

3 часа назад, haker_fox сказал:

Если под отладчиком наступает условие сброса по переполнению WDT, отладка "виснет".

Ну так это вроде как нормальное явление. Надо просто не допускать такого. Отключать WDT на время отладки или переводить его в режим генерации прерывания (если такое возможно в этом МК).

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


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

9 minutes ago, jcxz said:

Ну так это вроде как нормальное явление.

Недавно работал с GD32F450. Там при срабатывании WDT отладчик переходил на вектор сброса (там стояла точка останова). Так было приятно отлаживать всё это))) Вот я по привычке и захотел того же от LPC4337. Уже не помню, как раньше было с этим микроконтроллером, давно с ним работал.

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


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

В общем, почти неделю - полёт нормальный. Все функции работают как и положено! Просто супер-супер-супер спасибо уважаемому @jcxz за замечания и примеры кода!!!!:drinks::blum:

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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