Jump to content

    

C++ и ООП для микроконтроллеров AVR

В scmRTOS посмотрите как обработчики сделаны. У меня опыта нет упихивания С++ в контроллер.

 

И что значит "Поля в классах нужно инициализировать руками"

В Си вы пишете в module.c:

static int data;

 

И эта переменная у вас будет инициализирована нулём.

 

В С++ вы пишете в module.h:

class Module { private: int data;};

 

И эта переменная у вас инициализирована не будет.

Edited by andrewlekar

Share this post


Link to post
Share on other sites
А как быть с обработчиками прерываний? Вот я хочу сделать класс драйверов, как туда засунуть обработчик?

 

Можно так:

typedef void (*isr_func)(void* context);

class Driver 
{
    public:
        ...
        void InitIsr(isr_func isr);
        ...
};

class Device 
{
    private:
        Device()
        {
            ...
            driver->InitIsr(Isr);
            ...        
        }
        
        ...
        static void Isr(void* context);
        Driver *driver;
        ...
};

 

Share this post


Link to post
Share on other sites
В С++ вы пишете в module.h:

class Module { private: int data;};

 

И эта переменная у вас инициализирована не будет.

 

Ну я так понимаю на то конструкторы и есть. Мне вот только не совсем понятно: можно ли объявлять объект - не создавать его динамически. То есть в приведенном Вами примере создание объекта вот так:

class Module { private: int data;};

Module myModule;

int main (void)
{
    myModule.data=100500;
    while(1)
...
}

 

Можно так:

...

Не совсем понял: Вы передали указатель на функцию обработчик прерывания в метод InitIsr?

 

Share this post


Link to post
Share on other sites
можно ли объявлять объект - не создавать его динамически.

Можно. Только в вашем примере data будет недоступен.

Share this post


Link to post
Share on other sites
Не совсем понял: Вы передали указатель на функцию обработчик прерывания в метод InitIsr?

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

Моя практика показала, что если обработчик прерывания - член класса, то он должен быть статик, или не работает. Т.о. это выбрано для реализации возможности задать собственный обработчик прерывания для каждого объекта.

Share this post


Link to post
Share on other sites
... которая дает возможность использовать полиморфизм (в данном случае: переопределяемое на рантайме поведение).

 

 

...многие его средства - это абстракции уровня этапа компиляции.

 

а вот мне тут кажется противоречие. Или нет ?

 

и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )

Share this post


Link to post
Share on other sites
Ваши предложения...
class driver
{
public:
    void isr_handler();
    ....
};

driver Device1;

ISR(XXXX_vect)
{
    Device1.isr_handler();
};

 

Share this post


Link to post
Share on other sites
и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )

 

В "тело" каждого экземпляра класса добавляется указатель на таблицу виртуальных функций. Сами таблицы лежат в ПЗУ.

Share this post


Link to post
Share on other sites
и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )
Таблица в количестве одной штуки на каждый класс с виртуальными функциями. Обычно хранится в памяти кода (avr-gcc до сих пор этого не умеет, хранит в ОЗУ). В каждом объекте такого класса один указатель (уже в ОЗУ) на эту таблицу. Таблица состоит из указателей на реализации виртуальных функций, т.е. если класс имеет одну виртуальную функцию, то таблица состоит из одного указателя. Примерно так, "на пальцах".

Share this post


Link to post
Share on other sites
class driver
{
public:
    void isr_handler();
    ....
};

driver Device1;

ISR(XXXX_vect)
{
    Device1.isr_handler();
};

В таком исполнении ISR() нельзя сделать членом какого-то класса.

 

Share this post


Link to post
Share on other sites
В таком исполнении ISR() нельзя сделать членом какого-то класса.
А зачем ему быть членом класса? Оно даже логически слабо в класс просится. Членом класса является isr_handler(). Допустим у вас 4 UARTa: класс - один, объектов - 4, вектора прерываний для каждого объекта свои и каждый вектор вызывает один и тот же обработчик но для своего, конкретного объекта. С натяжкой можно было бы согласиться спрятать ISR внутрь класса для периферии, которая на кристалле одна. Но где гарантия, что завтра не придется переносить этот код на кристалл, у которого этой периферии две или три?

Share this post


Link to post
Share on other sites
А зачем ему быть членом класса? Оно даже логически слабо в класс просится. Членом класса является isr_handler(). Допустим у вас 4 UARTa: класс - один, объектов - 4, вектора прерываний для каждого объекта свои и каждый вектор вызывает один и тот же обработчик но для своего, конкретного объекта. С натяжкой можно было бы согласиться спрятать ISR внутрь класса для периферии, которая на кристалле одна. Но где гарантия, что завтра не придется переносить этот код на кристалл, у которого этой периферии две или три?

 

Для каждого объекта, естественно, свой обработчик, его и задаём при помощи InitIsr (RegisterIsr если нравится).

 

Хорошо, но допустим есть какой-то класс Device, у него есть интерфейс управления (class Spi), интерфейс передачи данных (class Uart), системный счётчик (class Timer), для каждого необходимо задать обработчик прерывания. Ну а обработчик прерывания логически просится в класс Device, т.к. он непосредственно и выполняет операции необходимые для функционирования Device.

 

Допустим в системе пять таймеров, для каждого нужен свой обработчик. Логично всё "одинаковое" запихнуть внутрь класса, обработчик, который может отличаться для каждого таймера реализовать как callback-функцию.

 

Share this post


Link to post
Share on other sites
Допустим в системе пять таймеров, для каждого нужен свой обработчик.
Угу. И каждый имеет свой вектор прерывания ISR(Timer_XX_vect) Как все пять обработчиков сделать статическими членами класса timer? Или я чего-то не понял в вашей идеологии?

Логично всё "одинаковое" запихнуть внутрь класса, обработчик, который может отличаться для каждого таймера реализовать как callback-функцию.
Угу, как callback или как виртуальную функцию. Или построить наследников на шаблонах используя Curiously recurring template pattern (я так думаю, сам не пробовал пока).

 

Share this post


Link to post
Share on other sites
Угу. И каждый имеет свой вектор прерывания ISR(Timer_XX_vect) Как все пять обработчиков сделать статическими членами класса timer? Или я чего-то не понял в вашей идеологии?

Все пять обработчиков и не являются статическими членами класса Timer. У Timer есть только функция регистрации прерывания. Обработчик прерывания необходимо зарегистрировать после создания объекта.

 

Угу, как callback или как виртуальную функцию. Или построить наследников на шаблонах используя Curiously recurring template pattern (я так думаю, сам не пробовал пока).

Тут не понял иронию, что не так в моей реализации? Всё работает и , по-идее, нет никаких противоречий. Можно и унаследовать если есть желание.

Share this post


Link to post
Share on other sites
Все пять обработчиков и не являются статическими членами класса Timer. У Timer есть только функция регистрации прерывания. Обработчик прерывания необходимо зарегистрировать после создания объекта.

 

я так и делал, но нужно при регистрации передавать this и собсвенно иметь массив этих void* на this

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this