LinkedIn YouTube Facebook
Szukaj

Wstecz
Artykuły

ISIX-RTOS – przykład 4 – wątkowa obsługa portu szeregowego RS232

Klasa the_serialapp zawiera obiekt usart klasy led_receiver, która stanowi obiekt portu szeregowego RS232. Obiekt ledrcv klasy led_receiver odpowiedzialny jest za odbiór znaków z portu szeregowego oraz sterowanie pracą LED w zależności od odebranego znaku. Obiekt keytran klasy key_transmitter odpowiedzialny jest za odczyt stanu styków joysticka oraz wysyłanie informacji do portu. Oba obiekty przyjmują referencję do wspólnego obiektu klasy usart_buffered oraz dziedziczą z klasy isix::task_base, więc stanowią odrębne wątki. Transmisja z wykorzystaniem portu szeregowego RS232 jest dupleksowa. Ponieważ jeden wątek tylko odczytuje dane z portu, natomiast drugi tylko zapisuje dane do tego portu, pracują one zupełnie niezależnie i nie wymagają wzajemnej synchronizacji za pomocą semafora, jak miało to miejsce w przypadku obsługi magistrali I2C, która jest simpleksowa. Klasa usart_buffered jest uniwersalną klasą sterownika portu szeregowego RS232 wykorzystującą sprzętowy port USART mikrokontrolera rodziny STM32. Klasa została napisana w taki sposób, aby była możliwość użycia dowolnego portu szeregowego dostępnego w mikrokontrolerze. Deklaracja klasy znajduje się w pliku i2c_host.cpp (list. 3).

 

List. 3. Deklaracja klasy sterownika portu szeregowego

class usart_buffered
{
    friend void usart1_isr_vector(void);
    friend void usart2_isr_vector(void);
 
public:
 
    enum parity            //Baud enumeration
    {
        parity_none,
        parity_odd,
        parity_even
    };
 
    //Constructor
    explicit usart_buffered(
        USART_TypeDef *_usart, unsigned cbaudrate = 115200,
        std::size_t queue_size=192, parity cpar=parity_none
    );
 
    //Set baudrate
    void set_baudrate(unsigned new_baudrate);
 
    //Set parity
    void set_parity(parity new_parity);
 
    //Putchar
    int putchar(unsigned char c, int timeout=isix::ISIX_TIME_INFINITE)
    {
        int result = tx_queue.push( c, timeout );
        start_tx();
        return result;
    }
 
    //Getchar
    int getchar(unsigned char &c, int timeout=isix::ISIX_TIME_INFINITE)
    {
        return rx_queue.pop(c, timeout );
    }
 
    //Put string into the uart
    int puts(const char *str);
 
    //Get string into the uart
    int gets(char *str, std::size_t max_len, int timeout=isix::ISIX_TIME_INFINITE);
 
private:
    static const unsigned IRQ_PRIO = 1;
    static const unsigned IRQ_SUB = 7;
 
private:
    void start_tx();
    void isr();
    void irq_mask() { ::irq_mask(IRQ_PRIO, IRQ_SUB); }
    void irq_umask() { ::irq_umask(); }
    void periphcfg_usart1(bool is_alternate);
    void periphcfg_usart2(bool is_alternate);
private:
    USART_TypeDef *usart;
    isix::fifo tx_queue;
    isix::fifo rx_queue;
    volatile bool tx_en;
 
private:     //Noncopyable
    usart_buffered(usart_buffered &);
    usart_buffered& operator=(const usart_buffered&);
};