nanorobot 5 24 марта, 2022 Опубликовано 24 марта, 2022 (изменено) · Жалоба По известным причинам пытаюсь мигрировать 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\... то есть определение то компилятор видит, и в чем проблема, неясно. Все исходные файлы примера сохранены и пути к ним объявлены... Изменено 24 марта, 2022 пользователем nanorobot Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба 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; Это не макрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nanorobot 5 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба Ну пусть будет шаблон, или как его... Мое знакомство с С++ шапочное, и в данный момент обусловлено необходимостью использования scmRTOS. По сути вопроса что то можете сказать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 231 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба "По сути вопроса" - если не знаете шаблонов, то зачем пытаетесь ими пользоваться? На 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)) { ... } и т.д. Без всяких шаблонов. И без кучи магических чисел в исходниках и жёсткого прибивания гвоздями к номерам пинов всех исходников. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nanorobot 5 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба 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, могу конечно. Интересна именно тема почему не работают шаблоны, как таковые, когда, казалось бы, все условия для этого есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
heavyC1oud 0 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба можно попробовать объявить так typedef Pin<'С', 7, 0> LedG_t; extern LedG_t LedG; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
nanorobot 5 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба Just now, heavyC1oud said: можно попробовать объявить так typedef Pin<'С', 7, '0'> LedG_t; extern LedG_t LedG; объявление и использование происходит в одном файле. причем рбъявление выше по тексту. extern использовать излишне я считаю. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
heavyC1oud 0 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба как будет угодно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба 5 часов назад, nanorobot сказал: Компилятор ругается на использование макросов Pin: Error[Li005]: no definition for "Pin<(char)67, (int)7, (char)0>::GPIOx" [referenced from C:\Users\... Такое бывало, когда отключена оптимизация. Попробуйте включить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 15 24 марта, 2022 Опубликовано 24 марта, 2022 · Жалоба Добавлю. Там третий параметр - буква 'L' или 'H'. Это активный уровень (низкий/высокий). То есть, уровень, в который переводится ножка по On(). (На деле любое значение кроме 'L' означает высокий активный уровень). И ещё. Не знаю, как в варианте для STM8/IAR, но в моём варианте можно не объявлять экземпляр класса, можно сразу использовать тип: typedef Pin<'B', 12, 'L'> PB12; // PB12, активный уровень НИЗКИЙ PB12::On(); // перевод PB12 в НИЗКИЙ уровень Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться