Вот коллега не поверите - даже не знаю. Специально такую команду я в обработчик от UARTa не вставлял. Если не сложно ответьте - как это влияет на взаимодействие обработчика прерывания и семафора? Я пишу на С, стоит глянуть дизассемблер, может компилятор сам это генерит для обработчика?
Приведу, чтобы было от чего отталкиваться:
Инит-код для UARTa:
Код
***************************************************************************
***
Инициализация аппаратных средств для RS-485
**/
void RS485_Setup(void)
{
/* Конфигурируем GPIO pins для RS-485 */
GPIO_PinModeSet(RS485_TX_PORT, RS485_TX_PIN, gpioModePushPull, 1);
GPIO_PinModeSet(RS485_RX_PORT, RS485_RX_PIN, gpioModeInputPull, 1);
GPIO_PinModeSet(RS485_CX_PORT, RS485_CX_PIN, gpioModePushPull, 0); // на прием
/* Инициализация UART для RS-485, тактирование USART должно быть включено
- BaudRate = 19200 baud
- Word Length = 9 Bits
- One Stop Bit
- No parity
Don't enable UART upon intialization */
const USART_InitAsync_TypeDef init =
{
usartDisable, // Disable RX/TX when init completed
0, // Provide information on reference frequency. When set to 0, the reference frequency is
19200, // Baud rate
usartOVS16, // Oversampling. Range is 4x, 6x, 8x or 16x
usartDatabits9, // Number of data bits. Range is 4 to 10
usartNoParity, // Parity mode
usartStopbits1, // Number of stop bits. Range is 0 to 2
false, // Disable majority voting
false, // Disable USART Rx via Peripheral Reflex System
usartPrsRxCh0 // Select PRS channel if enabled
};
USART_InitAsync(RS485_USART, &init); // Инициализируем асинхронный режим
/* Вкл автоформирование CS для драйвера RS-485,
устанавливаем Multi-processor mode, 9-бит = 1 - адрес устройства */
RS485_USART->CTRL |= USART_CTRL_AUTOCS | USART_CTRL_CSINV | USART_CTRL_MPM
| USART_CTRL_MPAB | USART_CTRL_TXDELAY_TRIPLE;
/* Enable signals TX, RX, CS */
RS485_USART->ROUTE |= USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CSPEN;
// | USART_ROUTE_LOCATION_LOC0 - подразумеваем (т.к. = 0);
/* Prepare UART Rx and Tx interrupts */
RS485_USART->IFC = _USART_IF_MASK; // сбрасываем флаги прерывания от UARTa
// вкл прерывания RX - на прием и MPAF-адрес мультипроцессорной системы
RS485_USART->IEN |= USART_IEN_RXDATAV | USART_IEN_MPAF;
NVIC_ClearPendingIRQ(RS485_RX_IRQn);
NVIC_EnableIRQ(RS485_RX_IRQn);
// Включаем UART на прием с блокировкой RX - работает только прием адресов
RS485_USART->CMD = USART_CMD_RXEN | USART_CMD_RXBLOCKEN;
}
Обработчик прерывания:
Код
/**
***************************************************************************
***
Обработчик прерывания на прием RS-485
**/
void RS485_RX_IRQHandler(void)
{
uint8_t rxData;
/* Обработка прерывания по адресу */
if (RS485_USART->IF & _USART_IF_MPAF_MASK)
{
rxData = (uint8_t)(RS485_USART->RXDATA); // Считываем адрес из буфера UART
RS485_USART->IFC = USART_IFC_MPAF; // Очистить флаг MPAF interrupt
if(rxData == SVO_ADR) // Совпадение с адресом СВО
{
RX_Counter = 0;
RX_Length = PR_POS_TYPE; // Минимум данных до длинны
RS485_USART->CMD = USART_CMD_RXBLOCKDIS; // Разблокируем прием RX
}
else
return;
}
/* Обработка прерывания по приему данных */
if (RS485_USART->IF & _USART_IF_RXDATAV_MASK)
{
rxData = (uint8_t)(RS485_USART->RXDATA); // Считываем адрес из буфера UART
switch (RX_Counter) // На лету декодируем заголовок пакета
{
case PR_POS_LENGTH:
if (rxData >= RS485_RX_BUFFERSIZE)
{
RS485_USART->CMD = USART_CMD_RXBLOCKEN;
return;
}
RX_Length = rxData;
break;
case PR_POS_TYPE: // Если не для СВО пакет, останавливаем прием, ждем следующего флага начала пакета
if (rxData != SVO_TYPE)
{
RS485_USART->CMD = USART_CMD_RXBLOCKEN;
return;
}
}
}
RS485_RX_Buf[RX_Counter] = rxData;
RX_Counter++;
if (RX_Counter == RX_Length)
{
RS485_USART->CMD = USART_CMD_RXDIS; // Блокируем прием по RX
/* Выдаем двоичный семофор в задачу-обработчик по приему полного пакета */
portBASE_TYPE xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xRxSemaphore ,&xHigherPriorityTaskWoken );
if( xHigherPriorityTaskWoken == pdTRUE )
vPortYieldFromISR();
}
}
Задача:
Код
/**
***************************************************************************
***
Задача работы с RS-485
**/
void taskRS485_ISR(void * pvParameters)
{
portBASE_TYPE xStatus;
extern xQueueHandle xQueueRelay; // Очередь на реле в модуле Board.с
extern uint16_t TermoArray[];
extern tDiscreteInput DiscreteArray[];
extern uint8_t DIPackByte;
uint16_t CRC;
uint8_t* TxPacket;
uint8_t i, ContNum, ReadCount, idx;
vSemaphoreCreateBinary(xRxSemaphore);
vQueueAddToRegistry(xRxSemaphore, "SEM");
vTaskDelay( TimeoutBeforeStart ); // Пауза для точной идентификации перезагрузки СВО
// и прихода паспортного пакета от контроллера
for (;; )
{
xStatus = xSemaphoreTake(xRxSemaphore, 200); // Ждем приема пакета от ISR по RX
if (xStatus == pdPASS)
{
CRC = GetCRC(RS485_RX_Buf, RS485_RX_Buf[PR_POS_LENGTH]-2); // Проверяем CRC пакета
if (CRC == PACK_WORD(RS485_RX_Buf[RS485_RX_Buf[PR_POS_LENGTH]-2], RS485_RX_Buf[RS485_RX_Buf[PR_POS_LENGTH]-1]))
{
................................................................................
.........................................................
SendPacket( TxPacket, TxPacket[PR_POS_LENGTH] );
}
// Включаем UART на прием с блокировкой RX - работает только прием адресов
RS485_USART->CMD = USART_CMD_RXEN | USART_CMD_RXBLOCKEN;
}
}
vTaskDelete( NULL );
}