Arlleex 284 December 11, 2018 Posted December 11, 2018 (edited) · Report post Приветствую! Пишу тут описание регистров периферии для одного МК (STM8, STVD/Cosmic). Бывает так, что между двумя регистрами одной и той же периферии или блока находится пустое пространство (резерв). Так вот, в местах, где такие "дыры" по пару байт, я пользуюсь безымянными битовыми полями: typedef volatile struct { u8 CR1; u8 CR2; u8 NCR2; const u8 FPR; const u8 NFPR; u8 IAPSR; u16 : 16; u8 PUKR; u8 : 8; u8 DUKR; }TNVM; Но есть периферия, между регистрами которой очень много пространства (больше килобайта). Пытался сделать так: u8 : 95856; Однако, даже если писать более короткие размеры u8 : 16; компилятор кричит на невозможность создания такого битового поля: Цитата #error cpstm8 STM8S003.h:46(14) invalid bitfield size При этом открываю Dev-C++, копирую туда тот же самый код и компиляция проходит успешно (без ошибок, но с предупреждениями). Кто-нибудь знает наиболее красивый способ объявить безымянную пустышку в структуре в произвольное количество байт, чтобы при доступе к элементам с включенной функцией автозавершения кода это пустое место не светилось никакими "Reserved1" и т.д.? Либо что-то типа безымянного массива (правда, я о таких не слышал). Решение нужно кроссплатформенное стандартное P.S. Раньше так и делал - в нужном месте объявлял массив нужной размерности и давал ему имя Reservedx, x = 1, 2...N. Но сейчас ищу способ не захламлять список регистров при всплывающей подсказке. Edited December 11, 2018 by Arlleex Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 71 December 11, 2018 Posted December 11, 2018 · Report post ИМХО, лучше уж назвать их как-нибудь вроде "zReserved", чтобы сваливались в конец списка. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 284 December 11, 2018 Posted December 11, 2018 (edited) · Report post 16 минут назад, aaarrr сказал: ИМХО, лучше уж назвать их как-нибудь вроде "zReserved", чтобы сваливались в конец списка. Печально Не плодя тем, еще хотел бы осветить один момент. Пишу файл startup.c с константным массивом, определяющим таблицу векторов прерываний: typedef struct { #define INT_OPERATION_CODE 0x82 u8 INTOperationCode; void (*Handler)(void); }TISRVector; extern void ISR_ResetHandler(void); extern void ISR_TrapHandler(void); extern void ISR_TLIHandler(void); ... extern void ISR_NVMHandler(void); static const TISRVector ISRVectorTable[] = { {INT_OPERATION_CODE, ISR_ResetHandler}, {INT_OPERATION_CODE, ISR_TrapHandler}, {INT_OPERATION_CODE, ISR_TLIHandler}, {INT_OPERATION_CODE, ISR_AWUHandler}, {INT_OPERATION_CODE, ISR_ClockHandler}, {INT_OPERATION_CODE, ISR_EXTI0Handler}, {INT_OPERATION_CODE, ISR_EXTI1Handler}, {INT_OPERATION_CODE, ISR_EXTI2Handler}, {INT_OPERATION_CODE, ISR_EXTI3Handler}, {INT_OPERATION_CODE, ISR_EXTI4Handler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_SPIHandler}, {INT_OPERATION_CODE, ISR_TIM1FirstHandler}, {INT_OPERATION_CODE, ISR_TIM1SecondHandler}, {INT_OPERATION_CODE, ISR_TIM2FirstHandler}, {INT_OPERATION_CODE, ISR_TIM2SecondHandler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_USARTTxHandler}, {INT_OPERATION_CODE, ISR_USARTRxHandler}, {INT_OPERATION_CODE, ISR_I2CHandler}, {0, 0}, {0, 0}, {INT_OPERATION_CODE, ISR_ADCHandler}, {INT_OPERATION_CODE, ISR_TIM4Handler}, {INT_OPERATION_CODE, ISR_NVMHandler}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, }; Хочу теперь сделать хитрость. Чтобы в разных проектах заново не добавлять/удалять только нужные обработчики, я (как видно выше) определил для линкера все символы (имена обработчиков). Однако, как и следовало ожидать, при сборке проекта и отсутствии определенных обработчиков (их нет в таблице символов линкера), вылезли ошибки типа Цитата #error clnk debug\stm8s_fancontrol.lkf:1 symbol _ISR_TrapHandler not defined (Debug\start.o Debug\start.o ) Что бы я хотел: при отсутствии обработчика в проекте, считать, что он для текущего проекта и не используется, и подставить вместо этого имени значение 0 (хотя это и не так важно). В Keil для этого существовала опция [weak], которая, будучи определенной рядом с именем, указывала, что, если этот символ будет определен в проекте, то использоваться будет именно он. Если нет - то символ со спецификатором [weak]. Является ли стандартной фишкой компоновщика наличие команды, заставляющей обратить ненайденные символы в 0 или другое известное значение, или это бородатый вымысел и такого в принципе не предусматривается? Беглый взгляд на описание компоновщика под Cosmic прямого ответа не дает. Edited December 11, 2018 by Arlleex Quote Share this post Link to post Share on other sites More sharing options...
aaarrr 71 December 11, 2018 Posted December 11, 2018 · Report post weak в том или ином виде должен быть у всех. Ну а если хотите переносимо - делайте обертку. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 284 December 11, 2018 Posted December 11, 2018 · Report post Понял, благодарю! Quote Share this post Link to post Share on other sites More sharing options...
ViKo 1 December 12, 2018 Posted December 12, 2018 · Report post А зачем битовые поля? Задавайте байты, я называю Reserved_ и номер или адрес добавляю. А если нужно много байтов, тогда - массив. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 284 December 12, 2018 Posted December 12, 2018 · Report post 4 часа назад, ViKo сказал: А зачем битовые поля? Задавайте байты, я называю Reserved_ и номер или адрес добавляю. А если нужно много байтов, тогда - массив. Мой первый пост: Цитата Кто-нибудь знает наиболее красивый способ объявить безымянную пустышку в структуре в произвольное количество байт, чтобы при доступе к элементам с включенной функцией автозавершения кода это пустое место не светилось никакими "Reserved1" и т.д.? Либо что-то типа безымянного массива (правда, я о таких не слышал). Решение нужно кроссплатформенное стандартное P.S. Раньше так и делал - в нужном месте объявлял массив нужной размерности и давал ему имя Reservedx, x = 1, 2...N. Но сейчас ищу способ не захламлять список регистров при всплывающей подсказке. Quote Share this post Link to post Share on other sites More sharing options...
ViKo 1 December 12, 2018 Posted December 12, 2018 · Report post Вот так и делайте. Как все. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 284 December 14, 2018 Posted December 14, 2018 · Report post Итак, что в итоге. По поводу первого вопроса. Сделал через нижние подчеркивания, как бы намекая, что область системная и прямого манипулирования с этой областью не предусматривается. Поставил модификатор const, чтобы нельзя было туда записать в явном виде (как жаль, что нет модификатора запрета и чтения в Си): ... typedef volatile struct { u8 CR1; u8 CR2; u8 FREQR; u8 OARL; u8 OARH; const u8 __RESERVE__[1]; u8 DR; const u8 SR1; u8 SR2; const u8 SR3; u8 ITR; u8 CCRL; u8 CCRH; u8 TRISER; }TI2C; ... По поводу weak-символов. Получил официальный ответ от Cosmic. Оказывается, weak-символы поддерживаются в компиляторах Cosmic только в версиях, начиная с 4.4.7. Синтаксис следующий: void @weak function(void) {...} Текст официального ответа от Cosmic: Цитата Hello, The weak feature is experimentally supported in the STM8 compiler from version V4.4.7 and not currently described in the manual. The syntax uses the @weak modifier placed before a function name: void @weak func(void) Quote Share this post Link to post Share on other sites More sharing options...
ViKo 1 December 14, 2018 Posted December 14, 2018 · Report post Вряд ли вы сами в здравом уме будете записывать в переменную RESERVED, так что можно быть проще. Quote Share this post Link to post Share on other sites More sharing options...
jcxz 312 December 14, 2018 Posted December 14, 2018 · Report post 3 часа назад, Arlleex сказал: По поводу первого вопроса. Сделал через нижние подчеркивания, как бы намекая, что область системная и прямого манипулирования с этой областью не предусматривается. Вроде как имена окаймлённые двойным подчёркиванием обычно зарезервированы для нужд компилятора или идущих с ним стандартных хидеров. Поэтому такие имена лучше не использовать, во избежание конфликтов и недоразумений. Я такие поля обычно обзываю unuseXX. Визуально оно чётко отличается от действительных полей, так как те написаны большими буквами. Спойлер //GPIO typedef struct { u32 OUT; union { u32 OM; struct { u16 OMS; u16 OMR; }; }; u32 unuse0[2]; union { u32 IOCR[4]; u8 IOCR8[16]; }; u32 unuse1[1]; u32 IN; u32 unuse2[6]; u32 PDR[2]; u32 unuse3[6]; u32 PDISC; u32 unuse4[3]; u32 PPS; u32 HWSEL; u32 unuse5[34]; } HwRegsGPIO; Quote Share this post Link to post Share on other sites More sharing options...