nanorobot 9 March 24, 2022 Posted March 24, 2022 (edited) · Report post По известным причинам пытаюсь мигрировать c STM32 на STM8 (32 битные использовали "с жиру", и из любопытства - Linux/GCC/ChibiOS). Взял пример 1-event-flag / STM8S / IAR. Чуть чуть допилил для STM8L - все работает как должно. Изменил структуру проекта под себя, мелкие попутные проблемы решил, кроме одной: Компилятор ругается на использование макросов Pin: Error[Li005]: no definition for "Pin<(char)67, (int)7, (char)0>::GPIOx" [referenced from C:\Users\... в моем случае он объявлен так Pin<'C', 7, 0> LedG; использование: LedG.Cpl(); пробовал намеренно внести ошибку в определение: Pin<'C', 7, 0, 1> LedG; сообщение об ошибке меняется: Error[Pe443]: too many arguments for class template "Pin" C:\Users\... то есть определение то компилятор видит, и в чем проблема, неясно. Все исходные файлы примера сохранены и пути к ним объявлены... Edited March 24, 2022 by nanorobot Quote Share this post Link to post Share on other sites More sharing options...
jcxz 361 March 24, 2022 Posted March 24, 2022 · Report post 2 часа назад, nanorobot сказал: Компилятор ругается на использование макросов Pin: Error[Li005]: no definition for "Pin<(char)67, (int)7, (char)0>::GPIOx" [referenced from C:\Users\... в моем случае он объявлен так Pin<'C', 7, 0> LedG; Это не макрос. Quote Share this post Link to post Share on other sites More sharing options...
nanorobot 9 March 24, 2022 Posted March 24, 2022 · Report post Ну пусть будет шаблон, или как его... Мое знакомство с С++ шапочное, и в данный момент обусловлено необходимостью использования scmRTOS. По сути вопроса что то можете сказать? Quote Share this post Link to post Share on other sites More sharing options...
jcxz 361 March 24, 2022 Posted March 24, 2022 · Report post "По сути вопроса" - если не знаете шаблонов, то зачем пытаетесь ими пользоваться? На STM8 использую данный набор макросов: #define Pdat2(port, pin) (PIO##port##.IN & 1U << (pin)) #define Pval2(port, pin) (PIO##port##.IN >> (pin) & 1) #define Pclr2(port, pin) (PIO##port##.OUT &= ~(1U << (pin))) #define Pset2(port, pin) (PIO##port##.OUT |= 1U << (pin)) #define Ptog2(port, pin) (PIO##port##.OUT ^= 1U << (pin)) #define Pout2(port, pin) (PIO##port##.DIR |= 1U << (pin)) #define Pin2(port, pin) (PIO##port##.DIR &= ~(1U << (pin))) #define PpullOn2(port, pin) (PIO##port##.REN |= 1U << (pin)) #define PpullOff2(port, pin) (PIO##port##.REN &= ~(1U << (pin))) #define PdatM2(port, mask) (PIO##port##.IN & (mask)) #define PclrM2(port, mask) (PIO##port##.OUT &= ~(mask)) #define PsetM2(port, mask) (PIO##port##.OUT |= (mask)) #define PoutM2(port, mask) (PIO##port##.DIR |= (mask)) #define PinM2(port, mask) (PIO##port##.DIR &= ~(mask)) #define PpullOnM2(port, mask) (PIO##port##.REN |= (mask)) #define PpullOffM2(port, mask) (PIO##port##.REN &= ~(mask)) #define Pdat(port_pin) Pdat2(port_pin) //false or true(не ноль) #define Pval(port_pin) Pval2(port_pin) //0 или 1 (строго) #define Pclr(port_pin) Pclr2(port_pin) //0 #define Pset(port_pin) Pset2(port_pin) //1 #define Ptog(port_pin) Ptog2(port_pin) //toggle #define Pout(port_pin) Pout2(port_pin) //на вывод #define Pin(port_pin) Pin2(port_pin) //на ввод #define PpullOn(port_pin) PpullOn2(port_pin) #define PpullOff(port_pin) PpullOff2(port_pin) #define PdatM(port, mask) PdatM2(port, mask) #define PclrM(port, mask) PclrM2(port, mask) #define PsetM(port, mask) PsetM2(port, mask) #define PoutM(port, mask) PoutM2(port, mask) #define PinM(port, mask) PinM2(port, mask) #define PpullOnM(port, mask) PpullOnM2(port, mask) #define PpullOffM(port, mask) PpullOffM2(port, mask) В файле описания периферии: Скрытый текст //IO pins (16bit) typedef struct { u16 IN; u16 OUT; u16 DIR; u16 REN; u16 unuse0[1]; u16 SEL0; u16 SEL1; u16 IV_L; u16 unuse1[3]; u16 SELC; u16 IES; u16 IE; u16 IFG; u16 IV_H; } HwRegsPIO16; //IO pins (8bit, odd ports) typedef struct { u8 IN; u8 unuse0[1]; u8 OUT; u8 unuse1[1]; u8 DIR; u8 unuse2[1]; u8 REN; u8 unuse3[3]; u8 SEL0; u8 unuse4[1]; u8 SEL1; u8 unuse5[1]; u16 IV; u8 unuse6[6]; u8 SELC; u8 unuse7[1]; u8 IES; u8 unuse8[1]; u8 IE; u8 unuse9[1]; u8 IFG; } HwRegsPIO8L; //IO pins (8bit, even ports) typedef struct { u8 unuse0[1]; u8 IN; u8 unuse1[1]; u8 OUT; u8 unuse2[1]; u8 DIR; u8 unuse3[1]; u8 REN; u8 unuse4[3]; u8 SEL0; u8 unuse5[1]; u8 SEL1; u8 unuse6[9]; u8 SELC; u8 unuse7[1]; u8 IES; u8 unuse8[1]; u8 IE; u8 unuse9[1]; u8 IFG; u16 IV; } HwRegsPIO8H; //IO pins (8bit, odd ports) typedef struct { u8 IN; u8 unuse0[1]; u8 OUT; u8 unuse1[1]; u8 DIR; u8 unuse2[1]; u8 REN; u8 unuse3[3]; u8 SEL0; u8 unuse4[1]; u8 SEL1; u8 unuse5[9]; u8 SELC; } HwRegsPIOJ; ... #ifdef IOPORT_EXTERN #define EXTERN __no_init __root volatile #else #define EXTERN extern volatile #endif EXTERN union { HwRegsPIO16 PIO12; HwRegsPIO8L PIO1; HwRegsPIO8H PIO2; } @ 0x0200; EXTERN union { HwRegsPIO16 PIO34; HwRegsPIO8L PIO3; HwRegsPIO8H PIO4; } @ 0x0220; EXTERN HwRegsPIOJ PIOJ @ 0x0320; В .h-файле определения пинов: #define PIN_USCIA1_CS 2, 3 //nRF24L01+: SPI chip select #define PIN_NRF_IRQ 2, 2 //nRF24L01+: Maskable interrupt pin. Active low #define PIN_NRF_CE 1, 0 //nRF24L01+: Chip Enable Activates RX or TX mode #define PIN_AOSONG 1, 3 //SDA-пин датчика AM2302 (DHT22) #define PIN_SCL 1, 7 #define PIN_SDA 1, 6 #define PIN_LED1 J, 0 #define PIN_LED2 J, 1 #define PIN_LED3 J, 2 #define PIN_LED4 J, 3 #define PIN_LED5 3, 4 #define PIN_LED6 3, 5 #define PIN_LED7 3, 6 #define PIN_LED8 3, 7 #define PIN_XIN J, 4 #define PIN_XOUT J, 5 В рабочем коде: Pclr(PIN_AOSONG); //установка в '0' Pout(PIN_AOSONG); //переключение на вывод ... Pset(PIN_LED_YELLOW); //установка в '1' ... if (!Pdat(PIN_UART_RX)) { ... } и т.д. Без всяких шаблонов. И без кучи магических чисел в исходниках и жёсткого прибивания гвоздями к номерам пинов всех исходников. Quote Share this post Link to post Share on other sites More sharing options...
nanorobot 9 March 24, 2022 Posted March 24, 2022 · Report post 9 minutes ago, jcxz said: "По сути вопроса" - если не знаете шаблонов, то зачем пытаетесь ими пользоваться? На STM8 использую данный набор макросов: #define Pdat2(port, pin) (PIO##port##.IN & 1U << (pin)) #define Pval2(port, pin) (PIO##port##.IN >> (pin) & 1) #define Pclr2(port, pin) (PIO##port##.OUT &= ~(1U << (pin))) #define Pset2(port, pin) (PIO##port##.OUT |= 1U << (pin)) #define Ptog2(port, pin) (PIO##port##.OUT ^= 1U << (pin)) #define Pout2(port, pin) (PIO##port##.DIR |= 1U << (pin)) #define Pin2(port, pin) (PIO##port##.DIR &= ~(1U << (pin))) #define PpullOn2(port, pin) (PIO##port##.REN |= 1U << (pin)) #define PpullOff2(port, pin) (PIO##port##.REN &= ~(1U << (pin))) #define PdatM2(port, mask) (PIO##port##.IN & (mask)) #define PclrM2(port, mask) (PIO##port##.OUT &= ~(mask)) #define PsetM2(port, mask) (PIO##port##.OUT |= (mask)) #define PoutM2(port, mask) (PIO##port##.DIR |= (mask)) #define PinM2(port, mask) (PIO##port##.DIR &= ~(mask)) #define PpullOnM2(port, mask) (PIO##port##.REN |= (mask)) #define PpullOffM2(port, mask) (PIO##port##.REN &= ~(mask)) #define Pdat(port_pin) Pdat2(port_pin) //false or true(не ноль) #define Pval(port_pin) Pval2(port_pin) //0 или 1 (строго) #define Pclr(port_pin) Pclr2(port_pin) //0 #define Pset(port_pin) Pset2(port_pin) //1 #define Ptog(port_pin) Ptog2(port_pin) //toggle #define Pout(port_pin) Pout2(port_pin) //на вывод #define Pin(port_pin) Pin2(port_pin) //на ввод #define PpullOn(port_pin) PpullOn2(port_pin) #define PpullOff(port_pin) PpullOff2(port_pin) #define PdatM(port, mask) PdatM2(port, mask) #define PclrM(port, mask) PclrM2(port, mask) #define PsetM(port, mask) PsetM2(port, mask) #define PoutM(port, mask) PoutM2(port, mask) #define PinM(port, mask) PinM2(port, mask) #define PpullOnM(port, mask) PpullOnM2(port, mask) #define PpullOffM(port, mask) PpullOffM2(port, mask) В файле описания периферии: Reveal hidden contents //IO pins (16bit) typedef struct { u16 IN; u16 OUT; u16 DIR; u16 REN; u16 unuse0[1]; u16 SEL0; u16 SEL1; u16 IV_L; u16 unuse1[3]; u16 SELC; u16 IES; u16 IE; u16 IFG; u16 IV_H; } HwRegsPIO16; //IO pins (8bit, odd ports) typedef struct { u8 IN; u8 unuse0[1]; u8 OUT; u8 unuse1[1]; u8 DIR; u8 unuse2[1]; u8 REN; u8 unuse3[3]; u8 SEL0; u8 unuse4[1]; u8 SEL1; u8 unuse5[1]; u16 IV; u8 unuse6[6]; u8 SELC; u8 unuse7[1]; u8 IES; u8 unuse8[1]; u8 IE; u8 unuse9[1]; u8 IFG; } HwRegsPIO8L; //IO pins (8bit, even ports) typedef struct { u8 unuse0[1]; u8 IN; u8 unuse1[1]; u8 OUT; u8 unuse2[1]; u8 DIR; u8 unuse3[1]; u8 REN; u8 unuse4[3]; u8 SEL0; u8 unuse5[1]; u8 SEL1; u8 unuse6[9]; u8 SELC; u8 unuse7[1]; u8 IES; u8 unuse8[1]; u8 IE; u8 unuse9[1]; u8 IFG; u16 IV; } HwRegsPIO8H; //IO pins (8bit, odd ports) typedef struct { u8 IN; u8 unuse0[1]; u8 OUT; u8 unuse1[1]; u8 DIR; u8 unuse2[1]; u8 REN; u8 unuse3[3]; u8 SEL0; u8 unuse4[1]; u8 SEL1; u8 unuse5[9]; u8 SELC; } HwRegsPIOJ; ... #ifdef IOPORT_EXTERN #define EXTERN __no_init __root volatile #else #define EXTERN extern volatile #endif EXTERN union { HwRegsPIO16 PIO12; HwRegsPIO8L PIO1; HwRegsPIO8H PIO2; } @ 0x0200; EXTERN union { HwRegsPIO16 PIO34; HwRegsPIO8L PIO3; HwRegsPIO8H PIO4; } @ 0x0220; EXTERN HwRegsPIOJ PIOJ @ 0x0320; В .h-файле определения пинов: #define PIN_USCIA1_CS 2, 3 //nRF24L01+: SPI chip select #define PIN_NRF_IRQ 2, 2 //nRF24L01+: Maskable interrupt pin. Active low #define PIN_NRF_CE 1, 0 //nRF24L01+: Chip Enable Activates RX or TX mode #define PIN_AOSONG 1, 3 //SDA-пин датчика AM2302 (DHT22) #define PIN_SCL 1, 7 #define PIN_SDA 1, 6 #define PIN_LED1 J, 0 #define PIN_LED2 J, 1 #define PIN_LED3 J, 2 #define PIN_LED4 J, 3 #define PIN_LED5 3, 4 #define PIN_LED6 3, 5 #define PIN_LED7 3, 6 #define PIN_LED8 3, 7 #define PIN_XIN J, 4 #define PIN_XOUT J, 5 В рабочем коде: Pclr(PIN_AOSONG); //установка в '0' Pout(PIN_AOSONG); //переключение на вывод ... Pset(PIN_LED_YELLOW); //установка в '1' ... if (!Pdat(PIN_UART_RX)) { ... } и т.д. Без всяких шаблонов. И без кучи магических чисел в исходниках и жёсткого прибивания гвоздями к номерам пинов всех исходников. Спасибо. Но проблема не в том, что я без шаблонов не могу управлять GPIO, могу конечно. Интересна именно тема почему не работают шаблоны, как таковые, когда, казалось бы, все условия для этого есть. Quote Share this post Link to post Share on other sites More sharing options...
heavyC1oud 0 March 24, 2022 Posted March 24, 2022 · Report post можно попробовать объявить так typedef Pin<'С', 7, 0> LedG_t; extern LedG_t LedG; Quote Share this post Link to post Share on other sites More sharing options...
nanorobot 9 March 24, 2022 Posted March 24, 2022 · Report post Just now, heavyC1oud said: можно попробовать объявить так typedef Pin<'С', 7, '0'> LedG_t; extern LedG_t LedG; объявление и использование происходит в одном файле. причем рбъявление выше по тексту. extern использовать излишне я считаю. Quote Share this post Link to post Share on other sites More sharing options...
heavyC1oud 0 March 24, 2022 Posted March 24, 2022 · Report post как будет угодно Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 March 24, 2022 Posted March 24, 2022 · Report post 5 часов назад, nanorobot сказал: Компилятор ругается на использование макросов Pin: Error[Li005]: no definition for "Pin<(char)67, (int)7, (char)0>::GPIOx" [referenced from C:\Users\... Такое бывало, когда отключена оптимизация. Попробуйте включить. Quote Share this post Link to post Share on other sites More sharing options...
AHTOXA 25 March 24, 2022 Posted March 24, 2022 · Report post Добавлю. Там третий параметр - буква 'L' или 'H'. Это активный уровень (низкий/высокий). То есть, уровень, в который переводится ножка по On(). (На деле любое значение кроме 'L' означает высокий активный уровень). И ещё. Не знаю, как в варианте для STM8/IAR, но в моём варианте можно не объявлять экземпляр класса, можно сразу использовать тип: typedef Pin<'B', 12, 'L'> PB12; // PB12, активный уровень НИЗКИЙ PB12::On(); // перевод PB12 в НИЗКИЙ уровень Quote Share this post Link to post Share on other sites More sharing options...