реклама на сайте
подробности

 
 
12 страниц V  « < 9 10 11 12 >  
Reply to this topicStart new topic
> Как ПРАВИЛЬНО программировать на С++, Вопросы по программированию на С++ для микроконтроллеров.
halfdoom
сообщение Sep 27 2010, 13:56
Сообщение #151


Профессионал
*****

Группа: Свой
Сообщений: 1 003
Регистрация: 20-01-05
Пользователь №: 2 072



Цитата(neiver @ Sep 27 2010, 12:00) *
Это можно реализовать. Но я не уверен, что нужно. Это оптимизация под один частный случай использования под определенной семейство МК. В этой библиотеке есть более важные варианты использования, которые надо оптимизировать.

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

Что касается атомарности, то это забота не этого класса.

А снабженец закупивший MSP вместо AVR однозначно будет уволен.
Go to the top of the page
 
+Quote Post
neiver
сообщение Sep 27 2010, 14:48
Сообщение #152


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Кстати, списки линий поддерживают и манипуляцию отделными битами из списка.
Переводя на пример, который запросил Quasy это будет выглядеть так:

Код
#include <avr/io.h>
#include "iopins.h"
#include "pinlist.h"

using namespace IO;

typedef PinList<Pa0, Pb0, Pd3, Pd4>  Pins;

int main()
{
              Pins::Pin<0>::Clear();
    Pins::Pin<1>::Set();
    Pins::Pin<2>::Clear();
    Pins::Pin<3>::Set();
}

Асм листинг:
Код
cbi    0x1b, 0; 27
sbi    0x18, 0; 24
cbi    0x12, 3; 18
sbi    0x12, 4; 18


Quasy, вы это хотели увидеть?
Go to the top of the page
 
+Quote Post
segment
сообщение Sep 27 2010, 15:58
Сообщение #153


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



2 Andy Mozzhevilov
Я говорил про то, что управление конкретными линиями GPIO должно быть только в одном потоке. Иначе вообще странная ситуация складывается - мы пытаемся двумя разными потоками управлять одним и тем же, при этом боимся где-то пересечься. Просто программист, который будет потом разбираться в коде, должен быть в курсе того, что есть такое пересечение потоков.
Кстати, Вы сказали про "приходится настройку портов оборачивать в критические секции", но если это задается вначале программы, то зачем оборачивать в критическую секцию, когда прерывания от периферии еще не разрешены?
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Sep 27 2010, 16:13
Сообщение #154


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Сега @ Sep 27 2010, 22:58) *
2 Andy Mozzhevilov
Я говорил про то, что управление конкретными линиями GPIO должно быть только в одном потоке. Иначе вообще странная ситуация складывается - мы пытаемся двумя разными потоками управлять одним и тем же, при этом боимся где-то пересечься.

Согласен. ИМХО если есть какой-то разделяемый ресур ввода/вывода, то правильно будет ввести сущность "драйвер/менеджер" устройства, и все операции вести через него. Соответственно, вся забота о разделении доступа ложится на этот драйвер
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Sep 27 2010, 21:04
Сообщение #155


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Dima_G @ Sep 27 2010, 20:13) *
ввести сущность "драйвер/менеджер" устройства, и все операции вести через него. Соответственно, вся забота о разделении доступа ложится на этот драйвер

Дык это - для синхронного вывода. Релюхами клацать smile.gif А если у нас(Вас) случилась такая беда: используется 7 бит для LCD, и надо ж такому случиться - 1wire на последней ноге торчит... Что делать? ванварь-то требует довольно точных временных интервалов...
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Sep 28 2010, 04:42
Сообщение #156


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



Цитата(Сега @ Sep 27 2010, 19:58) *
2 Andy Mozzhevilov
Я говорил про то, что управление конкретными линиями GPIO должно быть только в одном потоке. Иначе вообще странная ситуация складывается - мы пытаемся двумя разными потоками управлять одним и тем же, при этом боимся где-то пересечься.

Значит вы не поняли суть проблемы. Она в том, что для для модификации значения одного бита порта используется команда чтения значения всего порта (8 бит для avr), модификация нужного бита в регистре, и запись 8 бит обратно в порт. То есть модификация 1 бита фактически - это модификация всего порта. Следовательно, если на этом порту есть 2 разных линии, каждая из которых управляется из разных потоков, возможны трудноуловимые баги, обусловленный неатомарными операциями с 8-битным портом. В предыдущем сообщении я написал, как это решается в ARM NXP. Для avr предлагается использовать команды манипуляции отдельными битами (насколько я понял из их мненоники и описания).
А то что вы писали - это управление одной линией из разных потоков (или прерываний и фона) - это другая тема. И такое тоже имеет место быть при необходимости - не надо кричать, что это бред. Например, в фоне выставляется запрос внешнему устройству на каком-то пине, ответ от устройства обрабатывается по прерыванию, в котором в том числе и запрос снимается. Только в этом случае автомат состояния делается общий для такого управления, и там где нужно, изменения состояния автомата оборачиваются в критические секции.

Цитата
Кстати, Вы сказали про "приходится настройку портов оборачивать в критические секции", но если это задается вначале программы, то зачем оборачивать в критическую секцию, когда прерывания от периферии еще не разрешены?

Если это касается main - то не нужно.
На я использую драйвера периферии на С++, где в конструкторе производится инициализация и настройка альтернативных режимов пинов. Все конструкторы закрыты в критические секции, поскольку объекты могут быть созданы не только глобально (конструкторы их будут вызваны до main), но и локально в функции (задаче). В этом случае конструктор будет вызван в месте создания, когда прерывания уже во всю имеют место быть.


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
DL36
сообщение Sep 28 2010, 05:57
Сообщение #157


Местный
***

Группа: Свой
Сообщений: 460
Регистрация: 5-10-06
Из: Херсон
Пользователь №: 21 006



Цитата(neiver @ Sep 27 2010, 14:29) *
xor.w TRISB // TRISB = 0x0022 --> один бит потеряли, должно быть 0x002A

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

Дело не в подводных камнях просто пример совершенно не корректный, скажу более он в принципе не имеет решения.

С нашим устройством связаны биты о маска 0х000F и они должны меняться из одного места. Меняйте любые другие и все будет работать.

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

Макросы прекрасно работают в реальных проектах под TNKernel и позволяют отказаться во многих местах от использования критических секций.
Go to the top of the page
 
+Quote Post
segment
сообщение Sep 28 2010, 06:03
Сообщение #158


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Цитата(Andy Mozzhevilov @ Sep 28 2010, 08:42) *
Если это касается main - то не нужно.
На я использую драйвера периферии на С++, где в конструкторе производится инициализация и настройка альтернативных режимов пинов. Все конструкторы закрыты в критические секции, поскольку объекты могут быть созданы не только глобально (конструкторы их будут вызваны до main), но и локально в функции (задаче). В этом случае конструктор будет вызван в месте создания, когда прерывания уже во всю имеют место быть.

Хорошо, ну а какой смысл вообще оборачивать конструкторы в критические секции? Ну сработало прерывание (не касающееся этой периферии, так как инициализация еще не завершилась), отработали его, вернулись к инициализации и поползли дальше по конструктору, что должно сломаться?
ЗЫ: я не спорю, мне просто интересно
Go to the top of the page
 
+Quote Post
Andy Mozzhevilov
сообщение Sep 28 2010, 06:51
Сообщение #159


Знающий
****

Группа: Свой
Сообщений: 877
Регистрация: 26-01-05
Из: Екатеринбург
Пользователь №: 2 206



Цитата(Сега @ Sep 28 2010, 10:03) *
Хорошо, ну а какой смысл вообще оборачивать конструкторы в критические секции? Ну сработало прерывание (не касающееся этой периферии, так как инициализация еще не завершилась), отработали его, вернулись к инициализации и поползли дальше по конструктору, что должно сломаться?
ЗЫ: я не спорю, мне просто интересно

Так смысл абсолютно тот же, что и обсуждается сейчас здесь про неатомарные команды модификации битов порта.
Поясню на примере с ARM NXP.
Eсть регистр ввода-вывода (32 битный). В этом регистре настраиваются 16 линий порта на некоторые альтернативные функции, по 2 бита на пин. То есть, чтобы перенастроить некоторую линию (или группу линий) на другую функцию - нужно:
1. Считать значение IO регистра
2. Модифицировать значение нужным образом.
3. Записать новое значение в IO регистр.
При этом в конкретном драйвере мне нужно (предположим) перенастроить только 2 IO линии из 16-ти, за которые отвечает этот регистр.

Теперь - у меня RTOS с вытеснением (аналогичные рассуждения для прерываний).
В другой задаче у меня так же есть код, который оперирует настройкой линий IO в пределах тех же 16-ти линий того же порта.
Проследите, что будет, если где-то между 1. и 3. произойдет переключение контекста на другую задачу, которая решит также перенастроить линии порта (другие линии, но находящиеся в пределах этих 16-ти).

1a. Считать значение IO регистра
--- контекст a->b
1б. Считать значение IO регистра
2б. Модифицировать значение нужным образом.
3б. Записать новое значение в IO регистр.
--- контекст b->a
2a. Модифицировать значение нужным образом.
3a. Записать новое значение в IO регистр.

В результате операции, выполненные в 1б, 2б, 3б - будут похерены.

ЗЫ: Проблема в том, что подобные баги - трудноуловимы. Их проявление - стечение обстоятельств. То есть как правило - это нечто вроде: "У меня софт прекрасно работает месяц, но потом иногда затыкается обмен данными".
Или: "У меня 1 раз из 100 устройство не включается, но после включения все 99 раз все дальше работает без сбоев".


--------------------
Пасу котов...
Go to the top of the page
 
+Quote Post
Quasy
сообщение Sep 28 2010, 09:13
Сообщение #160


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-09-10
Пользователь №: 59 665



Цитата(neiver @ Sep 27 2010, 18:48) *
Асм листинг:
Код
cbi    0x1b, 0; 27
sbi    0x18, 0; 24
cbi    0x12, 3; 18
sbi    0x12, 4; 18


Quasy, вы это хотели увидеть?

Для данной конфигурации - да. Остался, кажется, один шаг - заставить Вашу библиотечку разбирать: когда выводить побитно, а когда организовать критическую секцию с "Чтением-Модификацией-Записью". Это, кстати, нужно только для эффективного вывода констант (для переменных вывод побитный, там групповой вывод не работает).
Если интересно, то скажу, что в моем тупом варианте это делается весьма легко: в препроцессоре макрос считает для константы биты на каждом порту, и препроцессор же делает выбор.
Цитата
#if (GROUP_0_COUNT_BITS_OF_PORTA < 4) && (PORTA_HAVE_BITS_ACCESS)
Вот тут побитно SBI/CBI для порта А
#else
ENTER_ATOMIC Ну, для XMEGA критическая секция не нужна
RMW PORTA
RELEASE_ATONIC
#endif


... и так для всех портов.

Что для этого потребовалось? Ну, где-то сказать, что ПортА на битовом пространстве, ПортG - нет.
(для ХМЕГИ это означает - сказать на какой виртуальный порт отображен PORTn)
И макрос соорудить для подсчета бит. Это совсем легко.
Негатив такого варианта: для каждой Группы нужен h-файл с макросами для подсчета бит.. Они у меня, собаки, здоровенные получились, но каши не просят smile.gif


Go to the top of the page
 
+Quote Post
MrYuran
сообщение Sep 28 2010, 09:41
Сообщение #161


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Quasy @ Sep 28 2010, 13:13) *
Остался, кажется, один шаг - заставить Вашу библиотечку разбирать: когда выводить побитно, а когда организовать критическую секцию с "Чтением-Модификацией-Записью".

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

Кстати, насчёт пресловутой атомарности.
В msp430 (моём любимом smile.gif ) с этим никаких проблем.
Зря я волновался.
У него чтение-модификация-запись производится в пределах одной команды, засчёт ортогональной системы команд и адресации.
Вот пример, выцепил из рабочей прошивки.
Код
static __inline__ void SwPortToSend(void)
{
    LINE_DIR.out.LINE_DIR_PIN = LINE_DIR_TRANSMIT;
    7a70:    f2 f0 bf ff     and.b    #-65,    &0x001d;#0xffbf
    7a74:    1d 00

На порт по адресу 001d накладывается маска 0xffbf, и всё это за одну команду, которая не может быть прервана никаким прерыванием.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Quasy
сообщение Sep 28 2010, 10:09
Сообщение #162


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 23-09-10
Пользователь №: 59 665



Цитата(MrYuran @ Sep 28 2010, 13:41) *
Компилятор сам решит, он умный.
Посчитает количество тактов либо количество занятых под программу байт - в зависимости от ключей оптимизации.
А библиотека должна быть нейтральной.

Как хорошо иметь компилятор, умеющий без лишнего кода различить, что PORTA |= 0x07 надо делать тремя SBI, а PORTA |= 0x0f с помощью RMW в критической секции.
Go to the top of the page
 
+Quote Post
neiver
сообщение Sep 28 2010, 17:15
Сообщение #163


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Цитата(Quasy @ Sep 28 2010, 13:13) *
Остался, кажется, один шаг - заставить Вашу библиотечку разбирать: когда выводить побитно, а когда организовать критическую секцию с "Чтением-Модификацией-Записью". Это, кстати, нужно только для эффективного вывода констант (для переменных вывод побитный, там групповой вывод не работает).

Меня больше интересует именно групповой вывод для переменных.
Есть у кого нибудь предложеня по дальнейшей оптимизации этой операции? Какие ещё приёмы отображения битов из входного значения в соответствующие биты портов можно придумать? Эффективные приемы для частных случаев?

А так-же какие есть предложения по дальнейшему развитию функционала?
- Отдельная функция для гарантированно атомарного вывода
- Управление подтяжкой линий
- Управление режимами прерываний
Go to the top of the page
 
+Quote Post
neiver
сообщение Dec 30 2010, 12:13
Сообщение #164


Местный
***

Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123



Доброго всем времени суток.
В моей библиотеке произошло довольно много изменений:
- поддержка МК Texas Instruments MSP430;
- поддержка STM32;
- поддерживаются компиляторы GCC, IAR, Keil;
- новый подход к конфигурации портов;
- убраны предупреждения компиляторов;
- лучшая оптимизация;
- исправлены ошибки;
- автоматические тесты;
- лиценизия изменена на BSD.

Найти ее можно по старому адресу:
https://github.com/KonstantinChizhov/AvrPro...e/master/mcucpp
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 30 2010, 15:12
Сообщение #165


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(neiver @ Dec 30 2010, 17:13) *
- лиценизия изменена на BSD.
Вот это, пожалуй, самое важное :-)
В отличие от, к примеру, портирования на STM32, это самостоятельно сделать возможности никакой не было.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

12 страниц V  « < 9 10 11 12 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 07:28
Рейтинг@Mail.ru


Страница сгенерированна за 0.0147 секунд с 7
ELECTRONIX ©2004-2016