zltigo 1 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Думаю, счетчик отправленных байт должен помочь. Драйвер будет вытаскивать из FIFO ровно то количество байт, которое он запихнул при записи. Вопрос ведь в том, КУДА ОН ИХ БУДЕТ ДЕВАТЬ после ВЫТАСКИВАНИЯ? Выбрасывать? Вы обещали научить меня писать драйвера .... так, что тупое опустошение не понадобится вовсе! Если под "умным" опустошением предполагается их, при их априори полной бесполезности тем не менее складывать куда-то дабы "когда свалимся в DABT, можно будет снять дамп и посмотреть", то что тогда назвать безумием :) :) :) будет чуть-чуть дольше, зато интуитивно понятно, что делается. И дольше и уж абсолютно интуитивно не понятна запись совершенно конкретного нуля, когда на самом деле может быть записано абсолютно произвольное значение :(. В общем это,конечно, мелочи... Но лучше владеть языком так, дабы не было и мелких огрехов, а не уповать на то, что "твоя моя и так понимай если твоя моя понимай однако нада будет". Дело привычки. Например как Вы поступите если есть некий шаблон колбека: typedef void (*putmsg_cb)(char *, int, int) и куча функций подпадающих под этот шаблон, но не использующих все параметры? Мне удобно поступать так: void xx_putmsg( char *msg, int size, int priority) { ignore( priority ); // <-- избавились от warning'a и сразу видно, что параметр priority нафиг не Будете смеяться, но мне - удобно АБСОЛЮТНО аналогично :). #define argsused(foo) (void)(foo) argsused( priority ); Только это совсем разные случаи, ибо в описываемый ранее SPSR; Абсолютно самодостаточен и не совершенно не нуждается, в отличии от priority, ни в каких мусорных обертках ignore( SPSR ); Если хотите сделать понятным для "танкистов", то напишите комментарий - "танкист" чуть-чуть выглянет из люка и узнает немного нового :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Вопрос ведь в том, КУДА ОН ИХ БУДЕТ ДЕВАТЬ после ВЫТАСКИВАНИЯ? Выбрасывать? Складывать в кольцевой буфер, и "семафорить - данные есть". Если эти данные хоть кому-то нужны, обрабатывающий процесс их заберет, если не нужны драйвер перетрет их нафиг по кольцу. Но взятки - гладки, свою работу - принять, нативно опустошить, просигналить - драйвер сделал. Вы обещали научить меня писать драйвера Это перебор. Я такого не обещал, к тому же Вы и так умеете их писать. А порассуждать как можно написать драйвер, чтобы избежать пустых чтений - это пожалуйста. :) Если под "умным" опустошением предполагается их, при их априори полной бесполезности тем не менее складывать куда-то дабы "когда свалимся в DABT, можно будет снять дамп и посмотреть", то что тогда назвать безумием :) :) :) Под "умным" опустошением понимаем - монотонную работу драйвера. Не ему решать что полезно, а что бесполезно. Принимать без разбора драйвер должен абсолютно все, что физически приходит, и отдавать upper layer'у на рассмотрение. Но лучше владеть языком так, дабы не было и мелких огрехов, а не уповать на то, что "твоя моя и так понимай если твоя моя понимай однако нада будет". Бесспорно. Но, даже при хорошем владении языком, лучше уходить от неоднозначностей там где можно, а там где нет неоднозначностей - подчеркивать логику работы кода: if (a || b && c) или if (a || (b && c) ) вроде одно и то же, но второе ведь наглядней. Будете смеяться, но мне - удобно АБСОЛЮТНО аналогично :). Смеяться не буду, - хорошо, что мы на одной волне в этом вопросе :) Только это совсем разные случаи, ибо в описываемый ранее SPSR; Абсолютно самодостаточен и не совершенно не нуждается, в отличии от priority Я бы не был так категоричен. Потому что SPSR - это не переменная, а макрос. Что там за ним спрятано - хз. Скажете, а UM на что, а если его нет под рукой у читателя кода? ни в каких мусорных обертках ignore( SPSR ); Если хотите сделать понятным для "танкистов", то напишите комментарий - "танкист" чуть-чуть выглянет из люка и узнает немного нового :) шутку понял :) Но все же argused() ignore() accessed() и т.п. делают код прозрачнее, и гибче при переносе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба if (a || b && c) или if (a || (b && c) ) вроде одно и то же, но второе ведь наглядней. Это далеко не одно и то же. Логические операции И и ИЛИ всегда выполняются слева направо. Даже компилятор не имеет права изменить этот порядок. Эквивалентным будет if (( a || b ) && c) и со скобками действительно нагляднее. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Это далеко не одно и то же. Логические операции И и ИЛИ всегда выполняются слева направо. Даже компилятор не имеет права изменить этот порядок. Эквивалентным будет if (( a || b ) && c) и со скобками действительно нагляднее. А приоритеты операций? Все-таки if (a || b && c) или if (a || (b && c) ) это одно и то же. Если есть время, просимулируйте вот этот тестик: void test(void) { int a = 1; int b = 0; int c = 0; if (a || b && c ) printf("1 || (0 && 0)"); else printf("(1 || 0) && 0"); } У меня результат этого теста - "1 || (0 && 0)". (RVDS 2.2 и 3.1). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 134 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба А приоритеты операций? Все-таки if (a || b && c) или if (a || (b && c) ) это одно и то же. Точно. Приоритеты подзабыл. Решил, что у них одинаковый приоритет. Посыпаю голову окурками. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
defunct 0 25 декабря, 2008 Опубликовано 25 декабря, 2008 · Жалоба Да все в порядке. Как раз хороший пример получился :beer: - лишний раз подчеркнуть логику работы кода - это только плюс. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ARV 1 27 декабря, 2008 Опубликовано 27 декабря, 2008 · Жалоба Да все в порядке. Как раз хороший пример получился :beer: - лишний раз подчеркнуть логику работы кода - это только плюс. как-то натолкнулся на высказывание "в Си скобки лишними не бывают" :) понравилось, следую этому правилу постоянно. голова болит меньше и проблем тоже меньше :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба Поскольку регистры uart безвариантно являются и прописаны как volatile, то несомнено второй вариант, ибо явные промежуточные переменные просто совсем не нужны. Что-то не получается обойтись без временной переменной. Вот код: void i2cStartRead(dword address) { ... //dword temp = I2C2->SR2; I2C2->SR2; } на что компилер (RV) ругается: i2c.cpp(71): warning: #174-D: expression has no effect Тот же самый код разложенный по "полочкам": typedef volatile unsigned short vu16; typedef unsigned short u16; typedef struct { vu16 CR1; u16 RESERVED0; vu16 CR2; u16 RESERVED1; vu16 OAR1; u16 RESERVED2; vu16 OAR2; u16 RESERVED3; vu16 DR; u16 RESERVED4; vu16 SR1; u16 RESERVED5; vu16 SR2; u16 RESERVED6; vu16 CCR; u16 RESERVED7; vu16 TRISE; u16 RESERVED8; } I2C_TypeDef; void i2cStartRead(dword address) { ... ((I2C_TypeDef *) (((u32)0x40000000) + 0x5800))->SR2; } Как убрать предупреждение компилятора, и обойтись без явной временной переменной? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба Как убрать предупреждение компилятора, и обойтись без явной временной переменной? Что-то я совсем не понял, что и как Вы собственно написали :(. А вообще так: typedef volatile struct { unsigned short SR2; ..... } I2C_TypeDef; I2C_TypeDef *I2C2 = (I2C_TypeDef *)(0x40000000 + 0x5800); void i2cStartRead(void) { .... I2C2->SR2; } P.S. И вместо мути в структуре ввиде 'reserved' используйте 32bit паковку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sonycman 0 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба Что-то я совсем не понял, что и как Вы собственно написали :(. А вообще так... P.S. И вместо мути в структуре ввиде 'reserved' используйте 32bit паковку. Так эта муть - библиотека ST для STM32. Я из неё использую только определения регистров. Ну её нафиг переделывать, и так пришлось править, чтобы хидеры из C++ компилировались... :) Попробовал, как Вы подсказали: typedef volatile struct { int a; int b; unsigned short SR2; } I2C_Type_Def; I2C_Type_Def * I2C2_1 = (I2C_Type_Def *)(0x40000000 + 0x5800); I2C2_1->SR2; но компилятор по-прежнему ругается: main.cpp(26): warning: #174-D: expression has no effect и выкидывает из кода эту строку... :07: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба чтобы хидеры из C++ компилировались... :) Так что, плюсовым компилируете!? Так тут уже по моему обсуждалось в начале топика - у плюсового свои странные понятия :(.... А такое, тогда он просто молча выкинет? (void)I2C2_1->SR2; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба Попробовал, как Вы подсказали: typedef volatile struct { int a; int b; unsigned short SR2; } I2C_Type_Def; I2C_Type_Def * I2C2_1 = (I2C_Type_Def *)(0x40000000 + 0x5800); I2C2_1->SR2; но компилятор по-прежнему ругается: main.cpp(26): warning: #174-D: expression has no effect и выкидывает из кода эту строку... :07: Впервые вижу волатильную структуру :) Может я ошибаюсь, но только переменная может иметь этот атрибут. Попробуйте объявить так: (volatile I2C_Type_Def *)(0x40000000 + 0x5800)->SR2; Потом проверьте есть ли в листинге чтение этого регистра. Я написал без временной переменной, но если она нужна или надо делать несколько чтений, то можно так: volatile I2C_Type_Def * I2C2_1 = (volatile I2C_Type_Def *)(0x40000000 + 0x5800); I2C2_1->SR2; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба но только переменная может иметь этот атрибут... С чего-бы это вдруг, тем более, что сами написали volatile I2C_Type_Def * I2C2_1 А если хотели I2C_Type_Def * volatile I2C2_1 так это совсем другое.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GetSmart 0 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба С чего-бы это вдруг, тем более, что сами написали volatile I2C_Type_Def * I2C2_1 А если хотели I2C_Type_Def * volatile I2C2_1 так это совсем другое.... Не, не. Я правильно выразил свою мысль в коде:) <<volatile I2C_Type_Def *>> говорит, что там, по адресу будет лежать волатильная структура/переменная. Переменная с адресом (I2C2_1) не должна/обязана быть волатильной. Разглядывая чужие хидеры, например из ИАРа, я ни разу не встречал волатил при объявлении структур, а вот при объявлении переменных - всегда. Поэтому и удивился. Если, теоретически, структуры могут иметь этот атрибут, то возможно проблема у sonycman-а в том, что компилятор не учитывает волатил из структуры, но будет учитывать при непосредственном объявлении в переменной. Проверить-то легко. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 4 января, 2009 Опубликовано 4 января, 2009 · Жалоба то возможно проблема у sonycman-а в том... Проблема в том, что компилятор плюсовый. <<volatile I2C_Type_Def *>> говорит, что там, по адресу будет лежать волатильная структура... Угу, только почему-то буквально строчкой выше Вы выражали сомнение в возможности описания таких структур :). О чем речь я и завел. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться