Суть задачки: Имеется готовый пример использования (FreeRTOS+LwIP) для STM32F217 http://electronix.ru/forum/index.php?showt...98347&st=30 в котором неплохо работает прием по UDP по прерываниям с использованием бинарного семафора
CODE
void ETH_IRQHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Frame received */
if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET)
{
/* Give the semaphore to wakeup LwIP task */
xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
}
/* Clear the interrupt flags. */
/* Clear the Eth DMA Rx IT pending bits */
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
/* Switch tasks if necessary. */
if( xHigherPriorityTaskWoken != pdFALSE )
{
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
}
сам таск выглядит так
void ethernetif_input( void * pvParameters )
{
struct pbuf *p;
for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
p = low_level_input( s_pxNetIf );
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
pbuf_free(p);
p=NULL;
}
}
}
}
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Frame received */
if ( ETH_GetDMAFlagStatus(ETH_DMA_FLAG_R) == SET)
{
/* Give the semaphore to wakeup LwIP task */
xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
}
/* Clear the interrupt flags. */
/* Clear the Eth DMA Rx IT pending bits */
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
/* Switch tasks if necessary. */
if( xHigherPriorityTaskWoken != pdFALSE )
{
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}
}
сам таск выглядит так
void ethernetif_input( void * pvParameters )
{
struct pbuf *p;
for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
p = low_level_input( s_pxNetIf );
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
pbuf_free(p);
p=NULL;
}
}
}
}
Имеется необходимость передавать по Ethernet выборки ADC1 (каждую выборку или накапливать небольшой буфер пока неясно)
Наверняка выгодно для этой цели создать task в заторможенном состоянии которая будет разблокироваться прерыванием
по ADC1
Код
void ADC_IRQHandler(void)
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* ADC1 received */
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == SET)
{
/* Give the semaphore to wakeup ADC1 task */
xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
}
/* Clear the interrupt flag. */
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}
и затем уже в таске, которая будет разбужена семафором передавать UDP пакет с выборкой.{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* ADC1 received */
if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == SET)
{
/* Give the semaphore to wakeup ADC1 task */
xSemaphoreGiveFromISR( s_xSemaphore, &xHigherPriorityTaskWoken );
}
/* Clear the interrupt flag. */
ADC_ClearFlag(ADC1, ADC_FLAG_EOC);
}
Вот и непонятно можно ли использовать один и тот же бинарный семафор для разных тасков? Если да то как будет выглядеть таск который будет выполнен по прерыванию ADC1? Может так?
CODE
void AdcUdpSend(void * pvParameters)
{
struct netconn *connn;
struct netbuf *buf1;
struct ip_addr addr;
static char text[2];
// create a new connection
connn = netconn_new(NETCONN_UDP);
// set up the IP address of the remote host
IP4_ADDR(&addr, DIP_ADDR0, DIP_ADDR1, DIP_ADDR2, DIP_ADDR3);
// connect the connection to the remote host
netconn_connect(connn, &addr, 7);
// create a new netbuf
buf1 = netbuf_new();
while(1)
{
test = xnetif.ip_addr.addr;
//check if IP address assigned
if (test !=0)
{
for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
text[1] = ADC1ConvertedValue;
text[0] = ADC1ConvertedValue >> 8;
netbuf_ref(buf1, text, sizeof(text));
// послать Eth пакет
netconn_send(connn, buf1);
}
}
}
}
}
{
struct netconn *connn;
struct netbuf *buf1;
struct ip_addr addr;
static char text[2];
// create a new connection
connn = netconn_new(NETCONN_UDP);
// set up the IP address of the remote host
IP4_ADDR(&addr, DIP_ADDR0, DIP_ADDR1, DIP_ADDR2, DIP_ADDR3);
// connect the connection to the remote host
netconn_connect(connn, &addr, 7);
// create a new netbuf
buf1 = netbuf_new();
while(1)
{
test = xnetif.ip_addr.addr;
//check if IP address assigned
if (test !=0)
{
for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
text[1] = ADC1ConvertedValue;
text[0] = ADC1ConvertedValue >> 8;
netbuf_ref(buf1, text, sizeof(text));
// послать Eth пакет
netconn_send(connn, buf1);
}
}
}
}
}
В этом случае
emacBLOCK_TIME_WAITING_FOR_INPUT определен как
#define emacBLOCK_TIME_WAITING_FOR_INPUT ( ( portTickType ) 100 )
(оставил так же как и для таска приема Eth пакетов)
Как лучше определить блокировку для этой задачи - задачи передачи Eth пакетов по прерыванию ADC1?
Поскольку прерывания от ADC будут приходить довольно часто (~ 10 мкс) не будет ли это тормозом для Ethernet приемника и вобще для всего приложения?