Thanks for the quick response.
I’ve already removed the lines that sets/clears the microcontroller’s LED pin (it was just a test to indicate me something goes wrong). But, yes, they were placed as you presume (setting immediatley after taking the mutex and clearing immediately before giving the mutex back).
There are not more instances of taskStoreReadings().
The mutex is not used from any interrupt.
Below are the other tasks that uses the mutex.
~~~
static void taskBlinkLed( void *pvParameters ){
unsigned short
seconds= 0;
unsigned int
opTime;
for(;;){
//descomentar depois de terminar o debug
prvToggleOnBoardLED();
if( BIT_TEST(RUNLED_VAL_REG, RUNLED_BIT) ){
seconds++;
if( seconds == 3600 ){
seconds= 0;
while( xSemaphoreTake(spiSemaphore, portMAX_DELAY) == pdFALSE );
spiMemReadSector( 0, extMemBuf );
//extrai o tempo atual do buffer lido da memoria externa
opTime= (unsigned int)extMemBuf[ADDR_OP_TIME + 0] << 24;
opTime |= (unsigned int)extMemBuf[ADDR_OP_TIME + 1] << 16;
opTime |= (unsigned int)extMemBuf[ADDR_OP_TIME + 2] << 8;
opTime |= (unsigned int)extMemBuf[ADDR_OP_TIME + 3] << 0;
//incrementa em 60 minutos
opTime += 60;
//
extMemBuf[ADDR_OP_TIME + 0]= opTime >> 24;
extMemBuf[ADDR_OP_TIME + 1]= opTime >> 16;
extMemBuf[ADDR_OP_TIME + 2]= opTime >> 8;
extMemBuf[ADDR_OP_TIME + 3]= opTime >> 0;
spiMemEraseSector( 0 );
spiMemWriteSector( 0, extMemBuf );
xSemaphoreGive( spiSemaphore );
}
}
vTaskDelay( (TickType_t)500 / portTICK_PERIOD_MS );
}
}
~~~
~~~
static void taskSendLog( void *pvParameters ){
unsigned char
mac[6],
index,
*ptr,
count;
char
strMac[12 + 1];
unsigned short
regLength,
logsToSend,
id,
ptrConsumidor;
unsigned int
regAddr;
signed int
lcdValue;
struct httpPacket
packet,
*httpPacketPtr;
struct sensorLogData
sensorLog;
(void) pvParameters;
//
httpPacketPtr= &packet;
//
ds2411GetSerialNum( mac );
regLength= 0;
for( index= 0; index < 6; index++ )
regLength += sprintf( strMac + regLength, "%02X", mac[index] );
//
packet.method= HTTP_POST;
packet.port= 80;
packet.data= httpData;
//
for(;;){
//
while( xSemaphoreTake(spiSemaphore, portMAX_DELAY) == pdFALSE );
index= 0;
do{
packet.url[index]= spiMemReadByte( ADDR_URL + index );
index++;
}
while( packet.url[index - 1] );
//verifica quantos logs irá enviar desta vez
logsToSend= ptrProd >= ptrCons? ptrProd - ptrCons: (MAX_LOGS_SENSORES - ptrCons) + ptrProd;
if( logsToSend > 5 )
logsToSend= 5;
//usa o valor do TC1 para gerar o ID da requisicao
id= T1TC % 1000;
//
regLength= sprintf( httpData, "{"method":"gravaLogWN","params":["%s",{"ident":"%s","opTime":%u,"reg":[", chaveLogin, strMac, spiMemRead32Bits(ADDR_OP_TIME) / 60 );
//
ptrConsumidor= ptrCons;
//loop p/ montar o pacote com os logs
for( count= 1; count <= logsToSend; count++ ){
//le o registro da Flash externa
ptr= (unsigned char *)&sensorLog;
regAddr= (unsigned int) SENSOR_LOG_ADDR_INI + (ptrConsumidor * SENSOR_LOG_SIZE);
for( index= 0; index < sizeof(sensorLog); index++ ){
*ptr= spiMemReadByte( regAddr );
regAddr++;
ptr++;
}
ptrConsumidor++;
if( ptrConsumidor == MAX_LOGS_SENSORES )
ptrConsumidor= 0;
regLength += sprintf( httpData + regLength, "{"dthr":"%u-%02u-%02u %02u:%02u:%02u",",
sensorLog.rtc.year + 2000, sensorLog.rtc.month, sensorLog.rtc.date, sensorLog.rtc.hour, sensorLog.rtc.minute, sensorLog.rtc.second );
lcdValue= sensorLog.elecSensor.humidity * 10;
regLength += sprintf( httpData + regLength, ""hum":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.pressure * 10;
regLength += sprintf( httpData + regLength, ""press":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.radiation * 10;
regLength += sprintf( httpData + regLength, ""rad":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.temp * 10;
if( lcdValue < 0 ){
lcdValue *= -1;
regLength += sprintf( httpData + regLength, ""temp":-%u.%u,", lcdValue / 10, lcdValue % 10 );
}
else
regLength += sprintf( httpData + regLength, ""temp":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.co2Level * 10;
regLength += sprintf( httpData + regLength, ""CO2":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.tvocLevel * 10;
regLength += sprintf( httpData + regLength, ""TVOC":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.elecSensor.batVoltage * 10;
regLength += sprintf( httpData + regLength, ""bat":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.mecLightSensor.rainFall * 10;
regLength += sprintf( httpData + regLength, ""rainFall":%u.%u,", lcdValue / 10, lcdValue % 10 );
regLength += sprintf( httpData + regLength, ""lightDist":%u,", sensorLog.mecLightSensor.lightDist );
regLength += sprintf( httpData + regLength, ""lightCount":%u,", sensorLog.mecLightSensor.lightCount );
lcdValue= sensorLog.mecLightSensor.windAvgSpeed * 10;
regLength += sprintf( httpData + regLength, ""wAvgSpeed":%u.%u,", lcdValue / 10, lcdValue % 10 );
lcdValue= sensorLog.mecLightSensor.windPeakSpeed * 10;
regLength += sprintf( httpData + regLength, ""wPeakSpeed":%u.%u,", lcdValue / 10, lcdValue % 10 );
regLength += sprintf( httpData + regLength, "%s", ""wDir":[" );
for( index= 0; index < 8; index++ ){
if( index != 7 )
regLength += sprintf( httpData + regLength, "%u,", sensorLog.mecLightSensor.windDirectionCount[index] );
else
regLength += sprintf( httpData + regLength, "%u", sensorLog.mecLightSensor.windDirectionCount[index] );
}
regLength += sprintf( httpData + regLength, "%s", "]}" );
if( count != logsToSend )
regLength += sprintf( httpData + regLength, "%s", "," );
else
regLength += sprintf( httpData + regLength, "]}],"id":%u}n", id );
}
//devolve o mutex de acesso à Flash externa
xSemaphoreGive( spiSemaphore );
//somente executa se existe(m) log(s) pendente(s)
if( logsToSend ){
while( xQueueReceive(serverRxQueue, &ptr, 0) == pdTRUE );
//fica em loop para ter certeza de que o item foi postado na fila com sucesso.
//O processo que gerencia o modem irá processar este item, pois fica "escutando" a fila.
while( xQueueSend(sendHttpQueue, &httpPacketPtr, portMAX_DELAY) != pdTRUE );
//salva numa variavel global o indice de consumo.
//Este indice será usado na funcao que processa a resposta. A variavel global "ptrCons" irá assumir o valor de "logConsumeIndex" caso resposta com sucesso.
/*
rzingler:
- talvez passar a variavel local "ptrConsumidor" como parametro para a funcao httpProcessServerResponse().
- Evitaria a necessidade de usar uma variavel global p/ manter o valor.
*/
logConsumeIndex= ptrConsumidor;
//funcao que processa a resposta do servidor
httpProcessServerResponse();
}
//intervalo entre uma e outra verificacao por logs pendentes
vTaskDelay( 10000 / portTICK_PERIOD_MS );
}
}
~~~
The last two tasks are defined in a different file, so the mutex created in main.c is passed as a parameter, as below (in the third line inside the function, the local variable spiSemaphore points to the same place as the mutex created in main.c):
~~~
void httpRequestInit( QueueHandle
t *serverResponseQueue, QueueHandlet *lcdQueue, SemaphoreHandle_t *spiSem ){
ptrModemConf= &modemConf;
serverRxQueue= *serverResponseQueue;
spiSemaphore= *spiSem;
//obtem a fila de envio criada pelo arquivo do modem
sendHttpQueue= modemGetSendDataQueue();
//
ptrMsg= &msg;
lcdMsgQueue= *lcdQueue;
//
xTaskCreate( taskLogin, "login", configMINIMAL_STACK_SIZE * 2, NULL, 1, &loginHandle );
}
~~~