Простенькая вроде прога и все хорошо и логично, и работает… но только 40 сек.
Программка общения МК с терминалкой. Терминалка посылает каждые 50 мс команду опроса длиной 4 байта плюс кс- 3f 0 0 0 3f, в ответ МК кидает также 4 байта плюс кс: 47 0 0 0 47, но это детали. Проц АТмега 8, 12МГц, сист. тик- 6 мс
Проблема в том, что примерно через 40 сек, видимо, не проходит сброс счетчика принятых байт и контрольной суммы. Перерывания по- уарту (прием байта) вызываются.
Подскажите, где тут может быть баг или неправильное понимание?
Код
#define scmRTOS_ISRW_TYPE TISRW_SS
……………………………………………………
#define scmRTOS_CONTEXT_SWITCH_SCHEME 0
……………………………………………………
OS::channel<unsigned char,10> chn_Rx;//канал на 10 байт
……………………………………………………
//-------------------------------------------------------------------------
#pragma vector = USART_RXC_vect
OS_INTERRUPT void RX(void)
{
OS::scmRTOS_ISRW_TYPE ISR;
UART_Rx();
}
//-------------------------------------------------------------------------
void UART_Rx(void)
{
unsigned char udrx=UDR;//принимаем байт
if(chn_Rx.get_free_size()) chn_Rx.push(udrx);// запихиваем принятый байт в канал
}
//---------------------------------------------------------------------------
…………………………………………………………………………
OS_PROCESS void TPRx::Exec()
{
unsigned char count_rx_byte=0;// счетчик принятых байт
unsigned char RxBuffer[LEN_RX];//приемный буфер
unsigned char rx_crc=0;// контрольная сумма
for(;;)
{
unsigned char rx=0;
if (chn_Rx.pop(rx,2))//вытаскиваем из очереди очередной байт
{
RxBuffer[count_rx_byte]=rx;//в буфер его
//вычисляем КС:
if(count_rx_byte<LEN_RX-1) rx_crc=rx_crc^RxBuffer[count_rx_byte];
else //если подошел последний байт пакета и КС совпала:
if((count_rx_byte==LEN_RX-1)&&(RxBuffer[count_rx_byte]==rx_crc))
Answer();//функция загрузки в ответ первого байта передачи в UDR
// дальнейшие загрузки байтов- по прерыванию от UART (передача)
count_rx_byte++;//на следующий байт
} else //если через 2 тика сист. таймера (12 мс) ничего не пришло- сбрасываем параметры приема:
{
count_rx_byte=0;//сюда через сек 40 уже не приходим...
rx_crc=0;
};
}//end_of_for(;;)
} end_of_ OS_PROCESS
//---------------------------------------------------------------------------
…………………………………………………………………
……………………………………………………
#define scmRTOS_CONTEXT_SWITCH_SCHEME 0
……………………………………………………
OS::channel<unsigned char,10> chn_Rx;//канал на 10 байт
……………………………………………………
//-------------------------------------------------------------------------
#pragma vector = USART_RXC_vect
OS_INTERRUPT void RX(void)
{
OS::scmRTOS_ISRW_TYPE ISR;
UART_Rx();
}
//-------------------------------------------------------------------------
void UART_Rx(void)
{
unsigned char udrx=UDR;//принимаем байт
if(chn_Rx.get_free_size()) chn_Rx.push(udrx);// запихиваем принятый байт в канал
}
//---------------------------------------------------------------------------
…………………………………………………………………………
OS_PROCESS void TPRx::Exec()
{
unsigned char count_rx_byte=0;// счетчик принятых байт
unsigned char RxBuffer[LEN_RX];//приемный буфер
unsigned char rx_crc=0;// контрольная сумма
for(;;)
{
unsigned char rx=0;
if (chn_Rx.pop(rx,2))//вытаскиваем из очереди очередной байт
{
RxBuffer[count_rx_byte]=rx;//в буфер его
//вычисляем КС:
if(count_rx_byte<LEN_RX-1) rx_crc=rx_crc^RxBuffer[count_rx_byte];
else //если подошел последний байт пакета и КС совпала:
if((count_rx_byte==LEN_RX-1)&&(RxBuffer[count_rx_byte]==rx_crc))
Answer();//функция загрузки в ответ первого байта передачи в UDR
// дальнейшие загрузки байтов- по прерыванию от UART (передача)
count_rx_byte++;//на следующий байт
} else //если через 2 тика сист. таймера (12 мс) ничего не пришло- сбрасываем параметры приема:
{
count_rx_byte=0;//сюда через сек 40 уже не приходим...
rx_crc=0;
};
}//end_of_for(;;)
} end_of_ OS_PROCESS
//---------------------------------------------------------------------------
…………………………………………………………………
Еще по-теме,- в одной из веток по scmRTOS:
Ну например прерывание передачи по UART забирает данные из OS:channel<uint8_t>. А данные там кончились... В этом случае pop() попытается передать управление другой задаче, и это приведет к краху. Поэтому прежде чем вызвать pop() надо проверить - а есть ли данные. Аналогично для push().
Почему должен быть крах? Вроде так и надо- нет работы- уйди… А в случае вызова рор() или push() из обработчика прерывания ,- перепланировщик там же не имеет действия!
Хотя, если из void UART_Rx(void) исключить "if(chn_Rx.get_free_size()) "- проц виснет савсем.