Макросъемка, в которой используются контакты ввода/вывода

Я пишу прошивку для PIC32MX, используя HiTech PICC32. Одна из проблем, которые я хочу избежать, заключается в том, что, поскольку большинство контактов имеют несколько имен (например, AN0 = RB0 ​​= CN2 = PGED1), я или кто-то другой может случайно использовать RB0, не понимая, что AN0 уже используется. (Это может быть катастрофично, поскольку неправильная настройка аналогового/цифрового вывода может привести к чрезмерному потреблению тока и высвобождению необходимого дыма.)

Помимо всестороннего документирования каждого используемого булавка, мне было интересно, есть ли быстрый способ решить эту проблему на уровне кодирования. Я хочу макрос, который могут использовать люди (в основном я), например CLAIM_PIN(58), который выдает предупреждение или ошибку, если он выполняется дважды.

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

Я должен уточнить: код написан в нескольких единицах компиляции (по крайней мере, я думаю, что это то, что означает фраза). У меня есть файл .h/.c для моего кода A2D, аналогично для SPI, и аналогично для разных периферийных устройств, которые используют только определенные порты ввода-вывода. Пространство на самом деле не проблема, мой код оставляет много места на PIC32MX; также я могу использовать другой флаг __DEBUG для удаления кода проверки PIN-кода для окончательного использования.

Ответ 1

Хорошо, здесь. Нет времени выполнения.

#define CLAIM(n) struct busy##n {}

CLAIM(58);
CLAIM(58);

Если запустить дважды, он будет выходить из строя:

z.c:4: error: redefinition of ‘struct busy58’

Чтобы расширить проверку до нескольких единиц компиляции, вы захотите обернуть макрос в #if DEBUG, потому что мы будем использовать компоновщик для обнаружения столкновения и, следовательно, будем иметь промежуток времени выполнения.

#define CLAIM(n) char busy##n = 1;
#define CLAIM(n) void busy##n() {} // bdonlan

Ответ 2

#define CLAIM_PIN(n) char claimed_pin_##n;

Теперь, когда два фрагмента кода пытаются запросить вывод, символ будет дважды определен, и компилятор или компоновщик будут генерировать ошибку.

Изменить: Основываясь на комментариях, это может оказаться лучше:

#define CLAIM_PIN(n) void claimed_pin_#nn(void) {}

Ответ 3

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

С другой стороны, Марк Рэнсом обновил ответ, стоил +1.