2015-01-28 2 views
1

В внедренного C, я врезался в примере следующие (и многие другие похожи):Embedded C#define

#define GPIOA_AHB   ((GPIOA_AHB_Type   *) GPIOA_AHB_BASE) 

GPIOA_AHB_BASE является адресом, и это определено ранее. Что именно делает этот код? Я знаю, что определяет директиву для препроцессора, так что он заменяет все экземпляры значением, заданным в определении. Например,

#define GPIOA_AHB GPIOA_AHB_BASE 

заменит GPIOA_AHB с тем значением GPIOA_AHB_BASE было определено. Я не получаю, хотя то, что происходит в первом случае ...

+0

Вы можете получить предварительно обработанную форму своего исходного кода (например, используя что-то вроде 'gcc -C -E yoursource.c> yoursource.i') –

ответ

2

полной информации не может быть указан из информации в этом вопросе, но:

  1. Если исходный код содержит GPIOA_AHB как Идентификатор, он будет заменен на ((GPIOA_AHB_Type *)GPIOA_AHB_BASE) изначально.
  2. Что будет дальше, зависит от того, является ли либо GPIOA_AHB_Type, либо GPIOA_AHB_BASE сам по себе является макросом.
  3. Если есть #define GPIOA_AHB_BASE 0x10000, скажите, то это значение вставляется в заменяющий текст. Точно так же, если есть #define GPIOA_AHB_Type uint8_t, то значение вставляется в тексте замены, что приводит к коду, содержащий:

    ((uint8_t *)0x10000) 
    
  4. Это значение может быть разыменовываются и чтения памяти будет происходить, что на самом деле ссылается на шину и устройство GPIO ,

+0

Спасибо! До пункта 3. Сейчас я вижу, что происходит. Часть ((uint8_t *) 0x10000) все еще размывается ... Будет ли это возвращать значение, хранящееся по адресу 0x10000, отправленному на uint8_t? – Botond

+0

В гипотетическом расширении, которое я показал, у вас должно было бы быть выражение: 'uint8_t b = * GPIOA_AHB;' читать байты с этого адреса или '* GPIOA_AHB = 0x83;' писать байт на этот адрес. Общая концепция (адрес, который вы можете читать или писать) является точной; подробная механика зависит от определений. Если 'GPIOA_AHB_Type' является структурой вместо простого типа, то вы можете использовать' GPIOA_AHB-> member' для доступа к члену структуры. Главное, что он преобразует адрес памяти, продиктованный аппаратным обеспечением, в нечто, что может использовать программа C. Он неспособен, но эффективен. –

+1

Обычно такие макросы записываются как: '#define GPIOA_AHB (* (volatile uint8_t *) GPIOA_AHB_BASE)'. Таким образом, вам не нужно разыгрывать, но обращаться с регистром как с любой другой переменной. Кроме того, тип должен быть энергозависимым, поскольку он является ячейкой памяти. – Lundin

1

Из определения GPIOA_AHB можно сделать вывод, что он используется для ссылки на регистры GPIO/AHB устройства.

Обозначения для доступа к этим регистрам будут GPIOA_AHB->some_register.

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