ошибка в хедере IAR STM8

Случайно обнаружил ошибку в заголовочнике iostm8l152c6.h в IAR 1.20.1.
Не знаю обсуждалось уже или нет, во всяком случае я не видел, поэтому решил написать, может кому-то будет полезно.
Сижу, значит, ковыряю свою STM8L-Discovery. Светодиодами по священному обряду наморгался, аж до тошноты.
Пощупал стандартные библиотеки. Не особо впечатлился, честно говоря.
Понял, что прийдется либо править их, либо писать под себя. Пока склоняюсь ко второму.
Ну да суть не в этом.
Надумал для начала на той-же дискавери запустить часики, а заодно и при помощи встроенного драйвера с LCD-стекляхой поработать. Логично начать с индикатора, как мне кажется. Ну рассуждать тут не о чем особо, надо начинать.
Принялся за распихивание битов по регистрам. С регистрами работаю через определения в iostm8l152c6.h.

 //убираем делитель системной
 //частоты тактирования (F_CPU=16 MHz, HSI):
 CLK_CKDIVR_bit.CKM = 0;
 //Подаем тактирование на LCD, RTC:
 CLK_PCKENR2 |= (1<<3)|(1<<2);
 //Выбираем внешний кварц (LSE) для RTC:
 CLK_CRTCR_bit.RTCSEL3 = 1;
 CLK_CRTCR_bit.RTCSEL2 = 0;
 CLK_CRTCR_bit.RTCSEL1 = 0;
 CLK_CRTCR_bit.RTCSEL0 = 0;
 //Ожидание стабилизации внешнего кварца:
 while(CLK_ECKR_bit.LSERDY==0);
 
/*.............Настройка LCD.............*/
 //устанавливаем скважность:
 LCD_CR1_bit.DUTY1 = 1;/****фактически ****/
 LCD_CR1_bit.DUTY0 = 1;/*количество COM-ов*/
 //прескаллер n = 2 (коэфициэнт деления будет 2^n, F=(F_RTC/2)/2^n)
 LCD_FRQ_bit.PS3 = 0;/****После прескаллера (32786/2)/4=4096****/
 LCD_FRQ_bit.PS2 = 0;/**и дальше проходит через делитель на 16**/
 LCD_FRQ_bit.PS1 = 1;/******что и даст в результате 256 Гц******/
 LCD_FRQ_bit.PS0 = 0;/******частота кадра же равна 256/4 Гц*****/
 //установка контрасности:
 LCD_CR2_bit.CC2=1;
 LCD_CR2_bit.CC1=0;
 LCD_CR2_bit.CC0=1;
 //включение LCD:
 LCD_CR3_bit.LCDEN=1;
 


Сам только начал разбираться со всем этим делом (коменты в основном для себя же, чтоб было понятно потом, что я делаю). А для ускорения пользуюсь методикой параллельного покуривания документации с методом тыка.
Вобщем в качестве источника тактирования часовой кварц, который на плате уже установлен, чем я и решил воспользоваться.
Как видно на странице 87 референс мануала

система тактирования ЖКИ- завязана с тактированием RTC. Поэтому нам достаточно выбрать источник тактов для RTC при помощи RTCSEL (подробнее на странице 100 того же мануала), и, дождавшись стабильной работы генератора («while(CLK_ECKR_bit.LSERDY==0);»), переходить к настройке самого контроллера LCD.
В аппноте AN3114 об этом очень лаконично, но понятно написано на стр. 40.
Следующим шагом

//включим все ноги для управления сегментами:
  LCD_PM0_bit.SEG00 = 1;
  LCD_PM0_bit.SEG01 = 1;
  LCD_PM0_bit.SEG02 = 1;
  LCD_PM0_bit.SEG03 = 1;
  LCD_PM0_bit.SEG04 = 1;
  LCD_PM0_bit.SEG05 = 1;
  LCD_PM0_bit.SEG06 = 1;
  LCD_PM0_bit.SEG07 = 1;
  LCD_PM1_bit.SEG08 = 1;
  LCD_PM1_bit.SEG09 = 1;
  LCD_PM1_bit.SEG10 = 1;
  LCD_PM1_bit.SEG11 = 1;
  LCD_PM1_bit.SEG12 = 1;
  LCD_PM1_bit.SEG13 = 1;
  LCD_PM1_bit.SEG14 = 1;
  LCD_PM1_bit.SEG15 = 1;
  LCD_PM2_bit.SEG16 = 1;
  LCD_PM2_bit.SEG17 = 1;
  LCD_PM2_bit.SEG18 = 1;
  LCD_PM2_bit.SEG19 = 1;
  LCD_PM2_bit.SEG20 = 1;
  LCD_PM2_bit.SEG21 = 1;
  LCD_PM2_bit.SEG22 = 1;
  LCD_PM2_bit.SEG23 = 1;


«Короче, Склифасофский!»
Вроде всё готово, можно бы и проверить…
И тут меня спасла моя лень, в очередной раз. Перед тем, как писать определения для символов, и размещения их в LCD_RAM, я решил посмотреть а как оно вобще светится, заодно и проверить, мож чего упустил или настроил коряво.
Запиливаю во все регистры FF-ки:

  LCD_RAM0=0xff;
  LCD_RAM1=0xff;
  LCD_RAM2=0xff;
  LCD_RAM3=0xff;
  LCD_RAM4=0xff;
  LCD_RAM5=0xff;
  LCD_RAM6=0xff;
  LCD_RAM7=0xff;
  LCD_RAM8=0xff;
  LCD_RAM9=0xff;
  LCD_RAM10=0xff;
  LCD_RAM11=0xff;
  LCD_RAM12=0xff;
  LCD_RAM13=0xff;

посмотрев одним глазом уже думал решить, что всё гуд, но отрывая второй замечаю: часть сегментов в четвёртом знакоместе не светится.
начинаю смотреть в доку на дискавери, а в часности на экранчик. и вижу, что не светятся все сегменты, которые подключены к ноге SEG07.
странно. касаюсь пальцем к штырьку PD0, который как раз соответствует отвечающей за эту группу сегментов ноге STM8L152C6 и сегментики светятся. проверяю на обрыв — нет, всё чётко. Ага, думаю, забыл, видимо переключить эту ногу с I/O на ножку ЖКИ-контроллера, глянул — есть, но почему-то затесалась между SEG14 и SEG15. Да и не в том регистре, где должна быть. Ладно, пробую сменить на нужный регистр (глупо конечно, но по запарке и не такое сделаешь=)) — ИАР весело рапортует ошибку «отрекись, мол, еретик проклятый, ибо неведомо мне ничего про бит, рукою твоею вписанный в регистр LCD_PM0». Ага, стоп: копировал я все их из хидера, лезем туда и видим:

/* LCD Port mask register 0 */
#ifdef __IAR_SYSTEMS_ICC__
typedef struct
{
  unsigned char SEG00       : 1;
  unsigned char SEG01       : 1;
  unsigned char SEG02       : 1;
  unsigned char SEG03       : 1;
  unsigned char SEG04       : 1;
  unsigned char SEG05       : 1;
  unsigned char SEG06       : 1;
} __BITS_LCD_PM0;
#endif
__IO_REG8_BIT(LCD_PM0,     0x5404, __READ_WRITE, __BITS_LCD_PM0);

/* LCD Port mask register 1 */
#ifdef __IAR_SYSTEMS_ICC__
typedef struct
{
  unsigned char SEG08       : 1;
  unsigned char SEG09       : 1;
  unsigned char SEG10       : 1;
  unsigned char SEG11       : 1;
  unsigned char SEG12       : 1;
  unsigned char SEG13       : 1;
  unsigned char SEG14       : 1;
  unsigned char SEG07       : 1;
  unsigned char SEG15       : 1;
} __BITS_LCD_PM1;
#endif
__IO_REG8_BIT(LCD_PM1,     0x5405, __READ_WRITE, __BITS_LCD_PM1);

/* LCD Port mask register 2 */
#ifdef __IAR_SYSTEMS_ICC__
typedef struct
{
  unsigned char SEG16       : 1;
  unsigned char SEG17       : 1;
  unsigned char SEG18       : 1;
  unsigned char SEG19       : 1;
  unsigned char SEG20       : 1;
  unsigned char SEG21       : 1;
  unsigned char SEG22       : 1;
  unsigned char SEG23       : 1;
} __BITS_LCD_PM2;
#endif
__IO_REG8_BIT(LCD_PM2,     0x5406, __READ_WRITE, __BITS_LCD_PM2);

/* LCD Port mask register 3 */
#ifdef __IAR_SYSTEMS_ICC__
typedef struct
{
  unsigned char SEG24       : 1;
  unsigned char SEG25       : 1;
  unsigned char SEG26       : 1;
  unsigned char SEG27       : 1;
} __BITS_LCD_PM3;
#endif
__IO_REG8_BIT(LCD_PM3,     0x5407, __READ_WRITE, __BITS_LCD_PM3);

таки ж да: с какого-то перепугу в структуре для первого регистра обьвлено только 7 битов, во второй структуре — 9, вместе с нашим блудным сыном. Ставлю его на своё законное место, сохраняю. Поправляю имя регистра у себя:

...
  LCD_PM0_bit.SEG06 = 1;
  LCD_PM0_bit.SEG07 = 1;
  LCD_PM1_bit.SEG08 = 1;
...

компилится, всё светится. почти что счастье)))
ладно разговорился я что-то. пойду допиливать задуманное.
когда закончу — могу написать подробную статью по этому поводу («ручной», так сказать, запуск RTC и LCD на дискавери(: ), если, конечно, это хоть кому-то интересно будет.
  • +1
  • 13 ноября 2011, 04:59
  • DOOMSDAY

Комментарии (20)

RSS свернуть / развернуть
Интересно, пишите! Хм, если у вас последняя версия IAR наверное стоит накатать маляву разработчикам сиво творения.
0
да, наверное. только моего уровня владения английским тут будет недостаточно.
0
Да бросьте, там всего пару слов. Мол версия такая, файл такой, ошибка в строке такой-то такая-то, с уважением Пупкин.В
0
Похоже что во всех хэдерах где LCD описан.
0
Извиняюсь за grammar nazi, но уж если пишите не «заголовок» а «header» кириллицей, то пишите хЭдер или хЕдер. Голова все-таки хэд, а не хид.
0
ок, камрад )
0
Если уж быть совсем граммар-нази, то «э» обычно превращается в «е» при русификации. Так что «хедер».
0
письмо в саппорт было отправлено. жду ответа
0
Ответили:

«Please find attached the original iostm8l152c6.h that followed with the
EWSTM8 version 1.20.1 maybe the file you do have is corrupted

We can only offer prioritized technical support to customers with an active
Support and Update Agreement (SUA). Bug reports will of course be accepted
regardless of your current SUA status.

Regards, Roberto Catalan, Technical Support team»

Прикрепили к письму файл(как понятно по тексту письма) тот же самый. А дальше не совсем понятно что идёт по тексту, «Support and Update Agreement» — это что?
0
Не заплатившим за лицензию поддержка не полагается. Но баг-репорт примут в любом случае.
0
Кто объяснит эту строчку кода. __IO_REG8_BIT(LCD_PM3, 0x5407, __READ_WRITE, __BITS_LCD_PM3);
что такое __IO_REG8_BIT имя функции? Где она выполняется? или это аттрибут? LCD_PM3 это ясно это имя регистра, а 0x5407 это адрес этого регистра. Что такое __READ_WRITE, __BITS_LCD_PM3 не ясно для чего это и как работает? Кто гуру, кто может объяснить?
0
Это макроопределения, найдите их поиском где описаны и всё станет понятно.
0
так я искал в хедере и не нашел. Искал два раза. Ладно попробую в третий раз
0
Это где-то в файлах самого IAR, по-моему. Пробуйте cквозным поиском по каталогу установки IAR.
0
нашел только это находится в другом хедере
0
Разумеется в другом, приведенное тобой определение — явно из файла поддержки конкретного МК, а макрос не менее явно — общая заготовка для объявления бита в 8-битном регистре (причем «служебного пользования», на это намекает двойное подчеркивание в начале), глупо объявлять ее в каждом частном хедере отдельно.
Вообще, найти определение нужного символа без хорошей IDE может быть не столь уж простой задачей, хотя греп по "#define MACRO_NAME" обычно помогает.
P.S. По стандартным соглашениям именования в С макросы записываются заглавными буквами. Именно поэтому, видя название __IO_REG8_BIT ты понимаешь, что это макрос служебного пользования (либо автор мудак, срущий на соглашения).
0
Нашел вот этот макрос.
#define __IO_REG8_BIT(NAME, ADDRESS, ATTRIBUTE, BIT_STRUCT) \
__near __no_init volatile ATTRIBUTE union \
{ \
unsigned char NAME; \
BIT_STRUCT NAME ## _bit; \
} @ ADDRESS;
Но уровень моего понимания еще слаб для такой конструкции. Что такое __near __no_init? Volatile это понятно. BIT_STRUCT NAME это где то есть дефайн на это выражение. ## не помню что это где то читал когда то. @ADDRESS; такой знак @ используется в ассемблере. все это отдаленно похоже на структуру.
0
Что такое __near __no_init?
Атрибуты, compiler-specific, смотреть в документации на компилятор.
BIT_STRUCT NAME это где то есть дефайн на это выражение
Нет, это же параметры макроса:
#define __IO_REG8_BIT(<b>NAME</b>, ADDRESS, ATTRIBUTE, <b>BIT_STRUCT</b>)

## не помню что это где то читал когда то.
Оператор препроцессора «конкатенация». Почитай статью neiver 'а про препроцессор.
@ADDRESS; такой знак @ используется в ассемблере.
И что? Это С, смотри документацию на компилятор, потому что оператор нестандартный.
Ну и собственно, после подстановки параметров в макрос получаем:
__near __no_init volatile __READ_WRITE union
{
    unsigned char LCD_PM3;
    __BITS_LCD_PM3 LCD_PM3_bit;
} @ 0x5407;

Остаются нераскрытыми макросы __BITS_LCD_PM3 и __READ_WRITE, хотя смысл последнего и без того ясен.
0
P.S. По всей видимости это анонимный юнион, привязанный к конкретному адресу, хот я по прежнему недопонимаю, как оно работает — не объявлена ни переменная типа «анонимный юнион {...}», ни что-либо еще для доступа к его полям. Возможно, надо смотреть на окружение самого макроса.
0
Что-то по типу такого:

#define __IO_REG8_BIT(NAME, ADDRESS, ATTRIBUTE, BIT_STRUCT)\ 
                       volatile __no_init ATTRIBUTE union \ 
                        {                                 \ 
                          unsigned char NAME;             \ 
                          BIT_STRUCT NAME ## _bit;      \ 
                        } @ ADDRESS 
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.