Перейти к содержанию
    

Так уберите. Я понимаю, памяти вам не жалко. Но быстродействие-то вам наверняка не помешает? :)

Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так?

port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2));
port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2));

Компилятор видит, что MODER имеет квалификатор volatile, потому в каждой строке он читает из MODER и потом сохраняет полученное значение обратно. Объедини строки, сэкономишь две команды :)

port->MODER = port->MODER  & ~(((UNSIGNED32)0x03) << (pinIndex * 2)) | (((UNSIGNED32)0x01) << (pinIndex * 2));

Изменено пользователем Reflector

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так?....

Я так понимаю, оптимизация для многих тут - это как позавтракать: не поел с утра нормально, весь день на смарку ))

 

Объедини строки, сэкономишь две команды :)

Так сильно ухудшается читаемость, а для меня она гораздо важнее ничтожной экономии объема кода (уже повторяюсь).

 

 

Исходник я выложил, экспериментируйте, дерзайте, выкладывайте тут итоговые результаты.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чистый код - это прежде всего код, который хорошо понятен для того, кто его пишет и сопровождает.

Да. И не всегда его сопровождает тот, кто писал изначально.

Но, если удастся себя переучить под большинство, это будет только на пользу коду.

Да.

Убежден, что "общепринятый стандарт" придуман для тех, у кого нет своих правил и стандартов. У меня есть свой стандарт, долго его формировал из чужого кода и книжек.

Это не "общепринятый стандарт", это стандарт языка.

Мне ломает глаз эта uint32_t, мне лично удобнее U32

Понятно. То есть, вам не удалось "переучить себя под большинство". Чем же тут гордиться?

Буду рад если найдете баги или еще более лучшие решения, но придирки к оформлению и мелочам предлагаю все же оставить за кадром.

Это не мелочи. Вы же сами тут выше в теме много рассуждали о "чистом коде", учили всех, как надо. А когда привели пример - оказалось, что пример ваш - совсем не образчик чистого кода. Вот именно на этом я и хотел акцентировать внимание.

А так - конечно, он у вас работает, он вас устраивает, это всё нормально. Но это - не образец чистого кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. И не всегда его сопровождает тот, кто писал изначально.

Именно, поэтому я сопровождаю код, если его приходится отдавать на сторону, неким readme, где указано что и как именуется в моем коде (см. чуть ниже).

 

Это не "общепринятый стандарт", это стандарт языка.

Не путайте мух с котлетами: некие "стандарты" именования, принятые когда-то негласно в неких библиотеках и Стандарты Языка - абсолютно разные вещи!

 

Ничто не мешает использовать свои типы. Лишь бы все подчинялось некой единой принятой программистом идеологии, а не выглядело, как сборная солянка чужих и своих типов.

Именно поэтому для себя я принял четыре простых правила именования:

 

1) Типы, классы, структуры, перечисления - ColorIndex

2) Поля и методы классов/структур, экземпляры классов/структур, методы классов, локальные переменные функций и методов классов - colorIndex, getColorIndex()

3) Макросы, замены “магических” чисел, поля перечислений - STARTUP_DELAY_MS

4) Элементарные (платформозависимые) типы - UNSIGNED16, FLOAT32 - возможно, буду сокращать такие длинные имена, например: U16, F32 ... но пока это под вопросом.

 

 

Чем же тут гордиться?

Гордится? Это где ж я озвучивал подобные потребности?

 

Но это - не образец чистого кода.
Где я сказал, что этот кусок кода именно такой?

У меня код постоянно эволюционирует. Есть старые куски кода, которые внешне прекрасно выполняют свою функцию, но внутренне содержимое требует допила.

Например, код Pin, который я привел выше, именно такой - функционалом я пока что доволен, а внутренне содержание под сомнением. Как дойдут руки до него, допилю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне ломает глаз эта uint32_t

Хе-хе...

Forger, надо тебе букву 't' добавить. И забыть как о страшном сне! Вообще полное деление на нуль!

Изменено пользователем Эдди

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не путайте мух с котлетами: некие "стандарты" именования, принятые когда-то негласно в неких библиотеках и Стандарты Языка - абсолютно разные вещи!

Это не "некие стандарты, принятые в неких библиотеках", а стандартный (прописанный в стандарте языка) заголовок из стандартной (прописанной в стандарте языка) библиотеки. Типы из которого безо всяких дополнительных readme понятны всем программистам. То, что вы используете вместо этих стандартных типов какие-то свои - усложняет сопровождение. Вместо int вы тоже что-то используете? А то у него буковки маленькие, не вписывается в ваш способ наименования:)

Где я сказал, что этот кусок кода именно такой?

Ну, это подразумевалось. После стольких лекций про чистый код вы выкатили пример. Или это был "антипример", и я просто не понял идеи?

Например, код Pin, который я привел выше, именно такой - функционалом я пока что доволен, а внутренне содержание под сомнением.

Это слабо сказано - "под сомнением". Я бы сказал - так себе код. Очень неоптимальный, с какими-то самопальными типами, с нелогичной иерархией классов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вместо int вы тоже что-то используете?

Разумеется! Но причина не в буковках, а в том, что в разных платформах int имеет различную разрядность - в PIC/AVR/STM8 он 16-битный, во ARM - 32-битный

Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет.

float тоже может иметь различную разрядность на разных платформах, поэтому я явно указываю в платформозависимых типах разрядность типа числом, это оказалось очень полезным.

 

выдержка из википедии:

 

Реальный размер целочисленных типов зависит от реализации. Стандарт лишь оговаривает отношения в размерах между типами и минимальные рамки для каждого типа:

 

Так long long не должен быть меньше long, который в свою очередь не должен быть меньше int, который в свою очередь не должен быть меньше short. Так как char — наименьший из возможных адресуемых типов, другие типы не могут иметь размер меньше него.

 

Минимальный размер для char — 8 бит, для short и int — 16 бит, для long — 32 бита, для long long — 64 бита.

 

Желательно, чтобы тип int был таким целочисленным типом, с которым наиболее эффективно работает процессор. Это позволяет достигать высокой гибкости, например, все типы могут занимать 64 бита. Однако, есть популярные схемы, описывающие размеры целочисленных типов.[7]

 

На практике это означает, что char занимает 8 бит, иshort 16 бит (также, как и их беззнаковые аналоги). int на большинстве современных платформ занимает 32 бита, а long long 64 бита. Длина long варьируется: для Windows это 32 бита, для UNIX-подобных систем — 64 бита.

 

Это слабо сказано - "под сомнением". Я бы сказал - так себе код. Очень неоптимальный, с какими-то самопальными типами, с нелогичной иерархией классов.

Я не буду спрашивать, что вы понимаете под "нелогичной иерархией классов", уже неинтересно, поэтому отвечу проще - не нравится мой код, пишите по-своему.

Мне приходилось пробовать разные решения, и похожее как у вас, но оказалось - не моё.

 

Вам не годится мой подход, мне - ваш.

Врядли дальнейшая наша болтовня полемика это как-то изменит ;)

Поэтому предлагаю переключить внимание на что-то другое ....

 

 

Вот до кучи мои типы данных (платформа ARM Cortex-M)

 

typedef unsigned            UNSIGNED1;
typedef unsigned char        UNSIGNED8;
typedef unsigned short        UNSIGNED16;
typedef unsigned int            UNSIGNED32;
typedef unsigned long long         UNSIGNED64;
typedef signed char            SIGNED8;
typedef signed short            SIGNED16;
typedef signed int            SIGNED32;
typedef signed long long         SIGNED64;
typedef float                FLOAT32;
typedef double                FLOAT64;

 

Вот эти макросы считаю очень полезными (макросы применяю крайне редко, вообще, стараюсь их заменять функциями, если это возможно):

#define MAKE_UNSIGNED32(high,low)        ((((UNSIGNED32)high) << 16) + low)
#define LOW_UNSIGNED16(unsigned32)        ((UNSIGNED16)((UNSIGNED32)(unsigned32) & 0x0000FFFF))
#define HIGH_UNSIGNED16(unsigned32)        ((UNSIGNED16)((UNSIGNED32)(unsigned32) >> 16))

#define MAKE_UNSIGNED16(high,low)        ((((UNSIGNED16)high) << 8) + low)
#define MAKE_SIGNED16(high,low)            ((SIGNED16)MAKE_UNSIGNED16(high,low))
#define LOW_UNSIGNED8(unsigned16)        ((UNSIGNED8)((UNSIGNED16)(unsigned16) & 0x00FF))
#define HIGH_UNSIGNED8(unsigned16)        ((UNSIGNED8)((UNSIGNED16)(unsigned16) >> 8))

 

Еще раз на всякий случай повторюсь для потомственных "танкистов": не нравится моя реализация, не пользуйтесь, обещаю, что настаивать не буду :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насчёт быстрее - вряд ли, скорее будет паритет. Насчёт удобнее - всяко. Сравните:

 

#define csOn() (GPIOA->BSRR = (1<<4))
#define csOff() (GPIOA->BSRR = (1<< (4 + 16)))
#define csCpl() (GPIOA->ODR ^ (1<<4))

vs

using CS = Pin<'A', 4>;
CS::On();
CS::Off();
CS::Cpl();

АНТОХА... не путайте мухи с котлетами.... вы сравниваете определение vs использование.

Вот использование vs использование

csOn();

csOff();

//или

CS::On();

CS::Off();

при использовании с дефайнами даже объявление не нужно, т.е. нет строки using CS = Pin<'A', 4>;

 

давайте сравним опеределение vs определение

#define csOn() (GPIOA->BSRR = GPIOA_BSRR_BR4)

#define csOff() (GPIOA->BSRR = GPIOA_BSRR_BS4)

//или

.....

 

2Forger

Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет.
пруфлинк? Стандарт строго оговаривает, что int - знаковый.

float тоже может иметь различную разрядность на разных платформах
пруф? Стандарт оговаривает 4 байта в формате IEEE754

 

typedef unsigned            UNSIGNED1;

wtf? Это bool чтоли?

signed int SIGNED32;
я высказывался за свой вкус про всякие SIGNED32, U32.... тут даже не вкус. почему мне не нравиться: если скописастить кусок кода из другово проекта, то не соберётся, нужно тащить до кучи мои типы данных. Это напрегает. в коде могут быть заимствования из 3-х 4-х проектов. получается для каждого стиля до кучи нужно тащить типы данных. В одном проекте можно увидеть весь зоопарк определений.

во вторых.... Forger я понял, что для вас литералы - это магические цыфры.... 0x10 или 0b1010110- это что-то плохое, что мешает чтению кода. есть стандартный uint32_t. А использование своих типов взамен стандартных - вы считаете это тру стиль?

 

в третих.... ну даже если там глаз режет uint32_t. вам милее U32. Дело вкуса. Но, у вас в тайпдефе мина. например

typedef signed int SIGNED32;

вы пишете какойнибудь код.... допусим расчет CRC на ARM. Один раз написал и забыл. Но встала задача посчитать CRC на Atmega. там int не 32. Вы/коллега/ученик перенёс на АВР ваш код... и упс!!!

почему бы не определить так?

typedef int32_t SIGNED32;

 

Здорово, но раз есть csOn(), то как минимум должен быть и csOff()
естественно.... так же как и в шаблонах/классах

 

потом захочется записать битик и дополнительно придется делать проверки...
чего?

 

А инициализация, она ведь тоже нужна? Итого сколько всего будет таких макросов для одного пина?
я затронул только переключение бита. инит нужен. его можно и функцией, и макросом, можно классом...можно сразу хором весь порт GPIOA проинитить.... это как вам угодно. Я просто хочу сказать, что не нужно думать бинарно.... у вас либо 0, либо 1. Либо С++ с ООП в полный рост безоговорочно.... с оверинженерингом, либо если один макрос или литерал воткнут - то это непрофессионализм. Использование стандартного литерала х и b - это фу фу фу, магическая цифра.... зато SIGNED32 (при чем с миной) - это круть!!!!

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Либо С++ с ООП в полный рост безоговорочно.... с оверинженерингом, либо если один макрос или литерал воткнут - то это непрофессионализм. Использование стандартного литерала х и b - это фу фу фу, магическая цифра.... зато SIGNED32 (при чем с миной) - это круть!!!!

+1

еще я улыбнулся над миной

class PinBase
{
public:
....
    inline void toggle(void) { port->ODR ^= pinMask; }

C++ это круто, но про многопоточность мы не слышали.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, касательно volatile... Forger, как думаешь что происходит, когда ты в своем классе делаешь так?

port->MODER &= ~(((UNSIGNED32)0x03) << (pinIndex * 2));
port->MODER |= (((UNSIGNED32)0x01) << (pinIndex * 2));

Компилятор видит, что MODER имеет квалификатор volatile, потому в каждой строке он читает из MODER и потом сохраняет полученное значение обратно. Объедини строки, сэкономишь две команды :)

port->MODER = port->MODER  & ~(((UNSIGNED32)0x03) << (pinIndex * 2)) | (((UNSIGNED32)0x01) << (pinIndex * 2));

Независимо от читабельности и эффективности первый вариант крайне не рекомендуется к использованию, так как он порождает промежуточные состояния аппаратуры, каждое из которых должно быть тщательно проверено на отсутствие побочных эффектов.

В процитированном примере возможен следующий сценарий: некий пин переключается между режимами output и alternate. Первый вариант на некоторое время поставит пин в input mode. Если между двумя записями в MODER произойдёт прерывание, то пин зависнет в input mode надолго, и подтяжка может переключить его в неожиданное для разработчика состояние - здравствуй, трудноуловимый глюк!

Кстати, в стандартном HAL такого ляпа с MODER нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Более того, в различных компиляторах по-умолчанию int - знаковый, а в некоторых - нет.

...

typedef unsigned UNSIGNED1;

Ну это всё, приплыли.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

+1

еще я улыбнулся над миной

class PinBase
{
public:
....
    inline void toggle(void) { port->ODR ^= pinMask; }

C++ это круто, но про многопоточность мы не слышали.

А вот я слышал и не по наслышке, т. к. практически везде, где используется с++, у меня стоит rtos.

Что по-вашему в этом куске кода не так?

 

Ну это всё, приплыли.

Это было сделано для обозначения битовых полей различной ширины в структурах, осталось в наследство, в настоящее время практически не используется.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

давайте сравним опеределение vs определение

 

Вот определение vs определение:

#define csOn() (GPIOA->BSRR = (1<<4))
#define csOff() (GPIOA->BSRR = (1<< (4 + 16)))
// или 
using CS = Pin<'A', 4>;

 

Вот использование vs использование:

csOn();
csOff();
//или
CS::On();
CS::Off();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

пруфлинк?
Все было указано выше. Читайте внимательнее.

 

Стандарт строго оговаривает, что int - знаковый.

пруф? Стандарт оговаривает 4 байта в формате IEEE754

По факту все иначе, читайте внимательнее.

 

wtf? Это bool чтоли?

НЕТ, читайте стандарт.

 

почему бы не определить так?

typedef int32_t SIGNED32;

Потому что в самом голом компиляторе нет такого типа, он создан в виде одного из typedef в одном из библиотечных инклклудов.

Т.е. нужно еще и подключать некий библиотечный файл, где этот тип описан.

В целом это все придирки.

 

 

 

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот определение vs определение:

#define csOn() (GPIOA->BSRR = (1<<4))
#define csOff() (GPIOA->BSRR = (1<< (4 + 16)))
// или 
using CS = Pin<'A', 4>;

где определение шаблона Pin<>? ещё 100500 строк!!!

 

Что по-вашему в этом куске кода не так?
ну вы не видите, что ваш тогл, при "одновременном" переключении разных бит, в одном порте из разных потоков не будет работать?

 

Потому что в самом голом компиляторе нет такого типа, он создан в виде одного из typedef в одном из библиотечных инклклудов.

Т.е. нужно еще и подключать некий библиотечный файл, где этот тип описан.

В целом это все придирки.

Т.е. вы не оспариваете что у вас мина в коде, вам предлагают её разминировать, на что ответ - это придирки. ))) Профессиональный подход, чистый код, легкочитаемый и переносимый .... ну ну .. )))

 

 

читайте внимательнее.
225 постов.... не увидел где была ссылка или упоминание на стандарт, в котором int беззнаковый. Не могли бы вы меня ткнуть носом, плииз.... приходится унижаться, чтоб получить знания, ДОЖИЛИ!!!

И о каком стандарте вы говорите, в котором всё иначе? может мы на разных языках пишем? Я думал мы тут делимся опытом, а не писками меримся. Просто отказ подкрепить свои слова пруфлинком выглядит как пустые слова... у меня длиньше, но я не покажу

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...