#arm #embedded #microcontroller #keil #atmel
#arm #встроенный #Микроконтроллер #keil #atmel
Вопрос:
Я пытался прочитать уникальный идентификатор (UID) из микроконтроллера Atmel SAM3U, но это оказалось сложнее, чем нужно, чтобы это произошло. У кого-нибудь есть какие-либо примеры или может подсказать, как правильно его прочитать? Всякий раз, когда я это делаю, я жду в do while
цикле (как указано в документации), чтобы регистр состояния EEFC (Flash ROM) изменил состояния, но этого никогда не происходит, поэтому MCU затем застревает в цикле.
Вот код, который я использую
// must run this from SRAM
__attribute__((section(".ARM.__at_0x20080000"))) void Get_Unique_ID(unsigned int *pdwUniqueID)
{
Efc *p_efc;
unsigned int status;
// clear the array
pdwUniqueID[0] = 0;
pdwUniqueID[1] = 0;
pdwUniqueID[2] = 0;
pdwUniqueID[3] = 0;
// send the Start Read Unique Identifier command (STUI) by writing the Flash Command Register with the STUI command
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
// wait for the Flash Programming Status Register (EEFC_FSR) to fall
do { status = p_efc->EEFC_FSR; }
while ((status amp; EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
// the Unique Identifier is located in the first 128 bits of the Flash memory mapping
pdwUniqueID[0] = *(unsigned int *)IFLASH0_ADDR;
pdwUniqueID[1] = *(unsigned int *)(IFLASH0_ADDR 4);
pdwUniqueID[2] = *(unsigned int *)(IFLASH0_ADDR 8);
pdwUniqueID[3] = *(unsigned int *)(IFLASH0_ADDR 12);
// to stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
// command (SPUI) by writing the Flash Command Register with the SPUI command
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_SPUI;
// when the Stop Read Unique Unique Identifier command (SPUI) has been performed
// the FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises
do { status = p_efc->EEFC_FSR; }
while ((status amp; EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
}
Обратите внимание, что __attribute__((section(".ARM.__at_0x20080000")))
это не лучший способ динамически назначать эту функцию SRAM через компоновщик, и любые предложения о том, как сделать ее более динамичной, будут оценены.
РЕШАЕМАЯ проблема заключалась в том, что чипы, которые у меня были, были поддельными, поэтому SAM-BA возвращал все, что было в указанном адресе буфера SRAM. Это ошибка в SAM-BA, поскольку, если он получил 0x00000000, он должен выдать сообщение об ошибке или предупреждение, а затем прекратить чтение. Не покупайте поддельные чипы из Китая!
Спасибо.
Комментарии:
1. Есть ли причина, по которой вы не пишете циклы, как, например
while((p_efc->EEFC_FSR amp; EEFC_FSR_FRDY)==0){}
?2. Причина, по которой я спрашиваю, заключается в том, что части SAM, как правило, имеют таинственные недокументированные побочные эффекты в нескольких регистрах. Иногда приходится считывать весь регистр без маскирующих битовых полей, иначе возникнут недокументированные кремниевые загадки.
3. Я не думаю, что проблема не в коде цикла. Проблема в том, что MCU не запускает эти биты регистра Flash ROM (EEFC), поэтому он фактически застрял в этом цикле.
4. Вы отключили все прерывания («Отключение IRQ») перед вызовом функции?
5. Да, прерывания были отключены.
Ответ №1:
Я не верю p_efc
, что он правильно инициализирован. Вы создаете указатель на Efc
структуру данных, которая, таким образом, указывает на что-то.
Затем вы что-то записываете куда-то и ожидаете, что это сработает.
Efc *p_efc;
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
Я предполагаю, что вам нужно инициализировать его по правильному базовому адресу EEFC. В техническом описании указано следующее:
В SAM3U4 (внутренняя флэш-версия объемом 256 Кбайт) встроены два EEFC (EEFC0 для Flash0 и EEFC1 для Flash1), тогда как в SAM3U2 / 1 встроен один EEFC.
Поэтому, в зависимости от версии вашего MCU, вам нужно обратиться к EEFC0 или EEFC1. Я предполагаю, что вы используете libopencm3, но это будет работать для любой другой библиотеки. Найдите определение местоположения EEFC. Следуя определениям / файлам / ссылкам, которые мы получаем на этой странице, он сообщает нам указать наш Efc
указатель на EEFC0_BASE
или EEFC1_BASE
. Я бы посоветовал вам использовать EEFC0
и EEFC1
определяет, поскольку это делает ваш код более переносимым.
Таким образом, ваш код должен работать, если ваш Efc находится в EEFC0
, если вы делаете:
Efc *p_efc = EEFC0;
Комментарии:
1. Спасибо за предложение. Я изменил все это, чтобы удалить указатель на структуру данных и вместо этого использовать.
Efc
EEFC0
Кроме того, я создал оба файла (т.Е. ОСНОВНОЙ. C и UID. C, который содержит приведенный выше пример кода), компилируется в области SRAM. Теперь код работает и не зависает, но возвращаемые значения полностью отличаются от SAM-BA. Есть идеи, почему это происходит? Я могу загрузить весь свой простой пример проекта Keil, если вы хотите его проверить.2. Кроме того, я не использую libopencm3 . Я использую библиотеки Keil uVision и включает в себя для 3U1C. Этот вариант ARM MCU имеет только один EEFC, который фактически определяется как EFC0. С моим комментарием выше указатель теперь полностью удален, и, как указано, я использую определение напрямую (Т. Е.:
EFC0->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FCMD_STUI;
). Итак, чтобы уточнить, все ссылки наp_efc->
теперь простоEFC0->
. Однако я не получаю правильные биты обратно. Я получаю0x44203120
для первого адреса, используя приведенный выше код, где он должен быть на самом деле0x574A73F8
в соответствии с SAM-BA.