Жесткая ошибка с макросом в операторе if или while на языке Си

#c #crash #embedded #stm32

Вопрос:

У меня есть следующий макрос, который я использую для чтения одного бита в регистре на моем STM32F091:

 #define GET_BIT(reg, pos)          (((reg)>>(pos))amp;0x00000001u)
 

Я должен использовать этот макрос с этими двумя параметрами:

 #define FLASH_KEYR                 (*((u32_t *)(0x40022004u)))
#define BSY_FLASH_SR_POS           (0u)
 

У меня нет никаких проблем с использованием этого макроса для оценки одной переменной, такой как:

 uint32_t value = GET_BIT(FLASH_SR, BSY_FLASH_SR_POS);
 

Но, используя этот макрос в условном операторе, подобном этому:

     while (GET_BIT(FLASH_SR, BSY_FLASH_SR_POS) == 1u);
 

Микропроцессор переходит в ISR для сбоя.

…Почему?

Комментарии:

1. Что такое FLASH_SR — т. е. показать определение (не объясняйте, что делает регистр SR). Waht-это АДРЕС РЕГИСТРАЦИИ

2. почему 0x00000001u вместо простого 1

3. @Toad __ — GET_BIT(((REGISTER_ADDRESS)>>(FIELD_POSITION))amp;0x00000001u) недопустимый вызов макроса с 2 аргументами GET_BIT(reg, pos) .

4. Вызов, о котором вы говорите, работает, не совпадает с тем, что вы говорите, прерывается, поэтому вполне вероятно, что это не имеет ничего общего с «если» или «пока», а скорее с параметрами. В любом случае это ужасная идея. Вместо того, чтобы использовать макрос положения бита, используйте макрос битовой маски (вероятно, уже определенный в заголовке чипа) и протестируйте бит напрямую или используйте адрес битовой полосы для прямого считывания бита.

5. Итак, вы хотели изменить адрес регистрации или значение регистра? Что вы на самом деле делаете и имеет ли это смысл семантически, будет зависеть от определения FLASH_SR. Макросы плохи, потому что они запутывают семантику кода. Чтобы отладить его, вы должны рассмотреть полное расширение и определить, является ли оно синтаксически и в данном случае семантически правильным.

Ответ №1:

Проблема в том, что вы заново изобретаете колесо, и оно вышло неправильно.

Вместо того, чтобы помочь вам заново изобрести еще одно новое колесо, вот существующее колесо, которое ST уже сделал для вас:

 #include "stm32f0xx.h"

...

while ((FLASH->SR amp; FLASH_SR_BSY) != 0);
 

Комментарии:

1. Нет, я не изобретаю колесо заново, потому что я не могу использовать библиотеку ST в этом критически важном для безопасности проекте

2. Я много работал над программным обеспечением IEC-62304 для медицинских устройств и проектами в области транспортных средств/военных. Любой аудитор с половиной клетки мозга доверял бы заголовкам определения регистра устройства от производителя оборудования, которые используются в тысячах проектов гораздо больше, чем все, что вы когда-либо могли написать. То же самое не относится к библиотекам STL или HAL, но вы, несомненно, должны использовать заголовки. Это подтверждается тем фактом, что вы не можете заставить его работать и просите случайных незнакомцев в Интернете о помощи в чем-то, что должно иметь решающее значение для безопасности.

3. Чтобы быть конкретным в отношении SMT32: эти заголовки определяют регистры как структуры, а ANSI-C не определяет объем памяти таких конструкций, лучше вообще их не использовать. В общем: я просто пишу некоторые периферийные драйверы, ничего сложного. Более того, вы можете забыть, что я нахожусь на STM32, этот вопрос является общим («почему этот код не работает»).

4. Вы не используете «какой-либо компилятор в целом». Вы используете компилятор, совместимый с ARM EABI, или должны им быть. Поместите ссылку на стандарт ARM EABI в пакет документации по проверке компилятора, а затем вы можете положиться на формальное определение упаковки структуры. Посмотрите на ISO14971 управление рисками для медицинских устройств (или эквивалент в вашей отрасли). Риск изобретения колеса всегда выше, чем делать это стандартным способом и предоставлять надлежащую документацию о том, почему действует стандартный способ.

Ответ №2:

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

Мой другой ответ по-прежнему является правильным профессиональным (особенно в критических условиях безопасности), но из комментариев следует, что это ответ, который вы предпочли бы принять.