Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions embedded_c.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,31 @@ if (cond1) {

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

Плохой пример:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Файлик называется embedded_c.en.md, а контент на русском.

```C
#define INPUT_1 { GPIOA, 10 }
#define INPUT_2 { GPIOA, 11 }

...

gpio_init(INPUT_1);
gpio_init(INPUT_2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем тут отступы? Думаю не нужны

```

В таком виде трудно вносить изменения, легко допустить ошибку, поправить одно и забыть другое.

Лушче написать так:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Лушче написать так:
Лучше написать так:

```C
#define INPUTS { { GPIOA, 10 }, { GPIOA, 11 } }

...

input_t input_list = INPUTS;
for (int i = 0; i < ARRAY_SIZE(input_list); i++) {
gpio_init(INPUTS[i]);
}
```

## Исправление ошибок в master

Ранее допущенные ошибки форматирования исправляются в отдельной ветке с PR согласно кодстайлу.
Expand Down Expand Up @@ -395,3 +420,61 @@ enum w1_protocol_transaction {
W1_PROTOCOL_TRANSACTION_RECEIVE
}
```

# Не плодите макросы конфигурации
Часто макросами в коде выбирается какая переферия используется в данном варианте, вариантов обычно не много, а переферии наоборот много. Вместо того чтобы прописывать макрос на каждый регистр или значение используйте структуры.

Вместо такого:
```C
#define MODBUS_HW_USART USART1
#define MODBUS_HW_USART_IRQn USART1_IRQn
#define MODBUS_HW_DMA_TX_CH DMA1_Channel2
```

Лучше написать так:
```C
struct modbus_hw {
USART_TypeDef *usart;
IRQn_Type irqn;
DMA_Channel_TypeDef *dma_tx_ch;
};

#define MODBUS_USART_HW { \
.usart = USART1, \
.irqn = USART1_IRQn, \
.dma_tx_ch = DMA1_Channel2 \
}
Comment on lines +442 to +446
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define MODBUS_USART_HW { \
.usart = USART1, \
.irqn = USART1_IRQn, \
.dma_tx_ch = DMA1_Channel2 \
}
#define MODBUS_USART_HW \
{ \
.usart = USART1, \
.irqn = USART1_IRQn, \
.dma_tx_ch = DMA1_Channel2 \
}

Вроде получше выглядит


```

# Переиспользование
Нужно использовать код повторно. Не нужно писать код если он уже написан. Если чтото существующее подходит не нужно делать чтото новое.
Чтобы не оставлять ошибки в дубликатах, экономить силы программиста и прочее. Читать подробнее в [Википедии](https://ru.wikipedia.org/wiki/Повторное_использование_кода).
Если есть 2 одинаковые строчки, подумайте, не оформить ли это в функцию, библиотеку или использовать в уже существующую.
Для использования кода с другого устройства - сделайте его библиотекой.

# Старайтесь не использовать поллинг
У любого кода есть причина выполнения, вот в обработке причины и нужно вызывать выполнение кода, или запланировать его выполнение.
Используйте инструменты организации кода - корутины и таймменеджер. В прерываниях планируйте задачу с обработкой в бэкграунде. Не используйте флаги.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну сам таймменеджер внутри флаги поллит же

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

# Не пишите лишний код, не выполняйте не нужные действия в коде
Пример: если файл с настройками не найден, прошивка использует дефолтные настройки. Не нужно сохранять файл с дефолтными настройками. Файл нужно записывать только если пользователь чтото поменял.
Чтение файла с дефолтными настройками ничем не отличается от отсутствия файла. Поэтому, можно избавиться от лишней операции записи, расхода места и износа флеш памяти, кода который эту запись делает.

# Не нужно делать в run time все что можно сделать в compile time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это точно всё заголовки первого уровня? Думаю надо подальше задвинуть

Все вычисления констант, генерацию макросов итд, то что не меняется в ходе работы программы нужно вычислять препроцессором на этапе сборки и записывать readonly константами: ресурсы ограничены, и их нужно экономить! Пусть мощный компьютер подготовит все необходимые данные.
По этой же причине следует выделять память статически и не использовать кучу.

# Не нужно делать в контексте прерывания все, что можно сделать в контексте background
Синхронизация асинхронных процессов это источник проблем. У нас есть разные инструменты для организации такой архитектуры. Тайм менеджер, корутины. Мы всегда должны знать что выполняется в прерываниях ВО ВСЕЙ ПРОШИВКЕ, чтобы быть уверенными что там нет ничего лишнего.
Например: в прерывании вызывать только планирование таски, а не само её выполнение.

# Не усложняйте код
Не нужно рассчитывать на тонкости стандартов языка. Не нужно заворачивать сложные конструкции. Код должен прочитать школьник который осилил только первую главу книжки по Си.
Подумайте можно ли сделать ваш код проще ? Часто можно выделить функции, чтото перегруппировать, распутать.
Помните про бритву Оккама.

# Делайте сразу хорошо если понимаете как
Не нужно писать TODO и FIXME. Если в код можно сделать компактнее, алгоритм быстрее, и вы знаете как, то сделайте сразу хорошо. Не надо лениться и аргументировать почему и так пойдет.
Плохо аргументировать фразами "жалко чтоли ? там не много". Такая аргументация не учитывает всю систему целиком, все возможные комбинации и многообразие кейсов применения.