2016-10-28 2 views
2

У меня есть программа (драйвер), которая читает/записывает некоторые регистры с отображением памяти. например:Лучший способ избежать приведения целых чисел в указатель при работе с доступом к памяти (MISRA 2008)

void foo_read(uint64_t reg_base, uint32_t *out_value) 
{ 
    *out = READREG(reg_base + FOO_REG_OFFSET); 
} 
  • reg_base является базовый адрес отображаемой памяти устройства (64-битный адрес)
  • FOO_REG_OFFSET является смещение регистра (#define FOO_REG_OFFSET 0x00000123). Регистрация «foo» - 32-разрядная «широкая».

READREG определяется следующим образом:

#define READREG(address) (*(uint32_t*)(address)) 

Как вы можете догадаться, MISRA 2008 не доволен отлитым из неподписанных долго долго указателя (5-2-7/5-2-8 является сообщались). Мой вопрос: какой лучший/подходящий способ получить доступ к памяти и избавиться от предупреждений MISRA? Я попытался применить к uintptr_t до каста к указателю, но This didn't help.

спасибо.

+2

Довольно очевидный вопрос: reg_base' на самом деле является указателем, почему бы не ввести его как 'uint8_t *'? – hidefromkgb

+1

@hidefromkgb: Или 'uint32_t *', Если 'reg_base' действительно должно быть целым числом, зачем использовать' uint64_t', а не 'uintptr_t'? (MISRA, вероятно, тоже этого не понравится, но 'intptr_t' или' uintptr_t' является наиболее логичным типом для целого числа, содержащего значение указателя.) –

+1

@KeithThompson, wouldn \ 't' uint32_t * 'умножать FOO_REG_OFFSET на 4, когда добавив в 'reg_base'? – hidefromkgb

ответ

1

ОК несколько вещей здесь - прежде всего, ваше определение READ_REG не хватает volatile - это должно быть что-то вроде

#define READREG(address) (*(uint32_t volatile *)(address)) 

Во-вторых - и это CPU конкретного курса - вообще говоря, чтение 32-битного значения из нечетного адреса (смещение 0x123) не будет работать - как минимум, он будет медленным (несколько циклов шины), а на многих архитектурах вы столкнетесь с исключением процессора. (Кстати, обратите внимание, что указатель арифметика не приходит в игру здесь, так как 2 значения добавляются перед тем, приведённый к указателю.)

Чтобы ответить на исходный вопрос:

что является лучшим/подходящий способ доступа к памяти и избавиться от MISRA предупреждения

Ну - вы являются нарушающих правил Мишра (вы должны в этом случае, мы все были там ...) поэтому вы получите предупреждение.

Так что вам нужно подавить предупреждение (ы) дисциплинированным, систематическим и легко узнаваемым способом. По моему мнению, нет лучшего примера и объяснения этого, чем в коде (QP), управляемом событиями, который является открытым исходным кодом. В частности:

  • ЗАКАНЧИВАТЬ QP's MISRA Compliance матрицы для примеров того, как это обрабатывается - например, просто поиск в PDF для Q_UINT2PTR_CAST макро
  • Отъезда фактического исходного кода QP - например, то macro that wraps/encapsulates such "int to ptr" casts (таким образом, они выполняются таким образом, который легко идентифицировать, и легко изменять/подавлять предупреждения в одном месте)
  • Наконец, проверьте конфигурационный файл PC-Lint qpc.lnt, где вы можете увидеть, как/где предупреждения подавляются в одном месте. Это объясняется в разделе this app note, раздел 6.3:

6,3 Правило 5-2-8 (REQ)

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

Приложения QP/C++ могут отклоняться от правила 5-2-8, когда им необходимо для прямого доступа к конкретным жестко закодированным аппаратным адресам. Структура QP/C++ инкапсулирует это отклонение в макрос Q_UINT2PTR_CAST(). Следующий фрагмент кода обеспечивает случай использования этого макроса: #define QK_ISR_EXIT() . . . \ *Q_UINT2PTR_CAST(uint32_t, 0xE000ED04U) = \

у меня нет времени, чтобы говорить о предупредительных suppresions MISRA, вопросы соблюдения и т.д., но выше дает вам все, что вам нужно.

P.S. Не знаете, какие рекомендации MISRA вы имеете в виду - для C есть руководящие принципы 2004 & 2012 года, а для C++ - рекомендации 2008 года (я знаю, это почти 2017 год!)

+0

#define FOO_REG_OFFSET 0x0000был всего лишь примером. Конечно, у меня нет странных смещений. – AndreiSS

+0

@AndreiSS - конечно, нет. У вас также нет принятого ответа на этот вопрос. – Dan

Смежные вопросы