QUOTE (Pavel V. @ Nov 15 2010, 15:50)

Идею Вашу понял, очень интересно! Насколько я понял, константы STA и STO служат признаками начала и конца пакета. Почему их отправку Вы поместили именно в конструктор и деструктор, а не в функцию send()?
Потому что функцию send() можно вызывать несколько раз во время передачи пакета.
CODE
void raw_message::send(frame & link) const
{
link.send(Type);
link.send(&Header, sizeof(Header));
link.send(this + 1, Size);
}
void Test()
{
frame Frame(Uplink);
pMessage->send(Frame);
}
QUOTE (Pavel V. @ Nov 15 2010, 15:50)

Функция Uart.send() помещает данные в кольцевой буфер, который опустошается в прерываниях? Не могли бы Вы показать как сделано это место? Интересует сама функция Uart.send() и обработчик прерывания.
Под MSP430F2618 у меня нет, вот под AVR:
CODE
#define UART_H__
#include <stdint.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <scmRTOS.h>
#define UART_RX_BUFF_SIZE 64
#define UART_TX_BUFF_SIZE 64
ISR(USART_RXC_vect);
ISR(USART_UDRE_vect);
class uart_t
{
public:
uart_t() {};
bool hasinput();
uint8_t receive();
template <typename T>
bool receive(T & item, timeout_t timeout = 0)
{
return RxBuffer.read((uint8_t * const)&item, sizeof(T), timeout);
}
void send(uint8_t byte);
void sendHEX(uint8_t byte);
void send(PGM_P pString);
bool tx_complete() { return UCSRA & ( 1 << TXC ); }
private:
friend void USART_RXC_vect();
friend void USART_UDRE_vect();
void RXC_Handler();
void UDRE_Handler();
private:
OS::channel<uint8_t, UART_RX_BUFF_SIZE> RxBuffer;
OS::channel<uint8_t, UART_TX_BUFF_SIZE> TxBuffer;
};
inline bool uart_t::hasinput (void)
{
return RxBuffer.get_count();
}
extern uart_t UART;
#endif // UART_H__
// ========= uart.cpp ==============
#include <avr/interrupt.h>
#include "Hardware.h"
#include "UART.h"
uint8_t uart_t::receive ()
{
uint8_t Data;
RxBuffer.pop(Data);
return Data;
}
void uart_t::send(uint8_t byte)
{
TxBuffer.push(byte);
UCSRB |= (1<<UDRIE); // UCSRB in io-space, no critical section required
}
#include <avr/pgmspace.h>
void uart_t::sendHEX(uint8_t byte)
{
static char const PROGMEM Table[] = "0123456789ABCDEF";
send(pgm_read_byte(&Table[byte >> 4]));
send(pgm_read_byte(&Table[byte & 0x0F]));
}
void uart_t::send(PGM_P pString)
{
char c;
while( (c = pgm_read_byte(pString++)) )
{
send©;
}
}
inline void uart_t::RXC_Handler()
{
char RxData = UDR;
if(RxBuffer.get_free_size())
{
RxBuffer.push(RxData);
}
}
OS_INTERRUPT void USART_RXC_vect()
{
OS::TISRW isr;
UART.RXC_Handler();
}
inline void uart_t::UDRE_Handler()
{
UCSRB &= ~(1<<UDRIE);
sei();
{
if(TxBuffer.get_count())
{
uint8_t Data;
TxBuffer.pop(Data);
UDR = Data;
cli(); // avoid recursive call
UCSRB |= (1<<UDRIE);
}
}
}
OS_INTERRUPT void USART_UDRE_vect()
{
OS::TISRW isr;
UART.UDRE_Handler();
}
uart_t UART;
QUOTE (Pavel V. @ Nov 15 2010, 15:50)

Я когда экспериментировал с модулем UART (на процессоре MSP430F2618), при постоянно разрешенных прерываниях по отправке, у меня были сложности. Поэтому в текущей реализации я запрещаю прерывание по отправке после отправки пакета целиком, а по попадании пакета в буфер отправки, соответственно, это прерывание разрешаю (тавтология какая-то получилась, но Вы, наверное, поняли что я имею в виду).
В AVR иначе и не сделаешь. Там нет возможности программно сбросить флаг готовности передатчика, и мне кажется это правильно: все передали (буфер пуст), нет необходимости в дальнейших прерываниях - запретили прерывания. Появилась необходимость (положили что-то в буфер) - разрешили прерывания, и если передатчик готов (флаг взведен) - сразу побежали в обработчик. А если прерывание было разрешено, опустошило буфер и отключило само себя до того, как в send() его разрешили снова - в обработчике есть проверка на пустоту буфера. Минимум лишних движений.