Stima V4 Slave RAIN  4.2
can_task.cpp
Go to the documentation of this file.
1 
30 #define TRACE_LEVEL CAN_TASK_TRACE_LEVEL
31 #define LOCAL_TASK_ID CAN_TASK_ID
32 
33 #include "tasks/can_task.h"
34 
35 using namespace cpp_freertos;
36 
37 // ***************************************************************************************************
38 // ********** Funzioni ed utility generiche per gestione UAVCAN **********
39 // ***************************************************************************************************
40 
44  // Normal Mode (TX/RX Full functionally)
45  if(ModeCan == CAN_ModePower::CAN_INIT) {
46  canPower = ModeCan;
47  digitalWrite(PIN_CAN_STB, LOW);
48  digitalWrite(PIN_CAN_STB, LOW);
49  // Waiting min of 5 uS for Full Operational Setup bxCan && Hal_Can_Init
50  delayMicroseconds(10);
51  digitalWrite(PIN_CAN_STB, HIGH);
52  digitalWrite(PIN_CAN_EN, HIGH);
53  }
54  // Exit if state is the same
55  if (canPower == ModeCan) return;
56  // Normal Mode (TX/RX Full functionally)
57  if(ModeCan == CAN_ModePower::CAN_NORMAL) {
58  digitalWrite(PIN_CAN_STB, HIGH);
59  delayMicroseconds(10);
60  digitalWrite(PIN_CAN_EN, HIGH);
61  // Waiting min of 65 uS for Full Operational External CAN Power Circuit
62  // Perform secure WakeUp Timer with 100 uS
63  delayMicroseconds(90);
64  }
65  // Listen Mode (Only RX circuit enabled for first paket data)
66  if(ModeCan == CAN_ModePower::CAN_LISTEN_ONLY) {
67  digitalWrite(PIN_CAN_EN, LOW);
68  delayMicroseconds(10);
69  digitalWrite(PIN_CAN_STB, HIGH);
70  }
71  // Sleep (Turn OFF HW and enter sleep mode TJA1443)
72  if(ModeCan == CAN_ModePower::CAN_SLEEP) {
73  digitalWrite(PIN_CAN_STB, LOW);
74  delayMicroseconds(10);
75  digitalWrite(PIN_CAN_EN, HIGH);
76  }
77  // Saving state
78  canPower = ModeCan;
79 }
80 
87 void CanTask::getUniqueID(uint8_t out[uavcan_node_GetInfo_Response_1_0_unique_id_ARRAY_CAPACITY_], uint64_t serNumb)
88 {
89  // A real hardware node would read its unique-ID from some hardware-specific source (typically stored in ROM).
90  // This example is a software-only node so we store the unique-ID in a (read-only) register instead.
91  static uavcan_register_Value_1_0 val = {0};
92  uavcan_register_Value_1_0_select_unstructured_(&val);
93 
94  // Crea default unique_id con 8 BYTES From local_serial Number (N.B. serNumb[0] rappresenta Tipo Nodo )
95  uint8_t *ptrData = (uint8_t*)&serNumb;
96  for (uint8_t i = 0; i < 8; i++)
97  {
98  val.unstructured.value.elements[val.unstructured.value.count++] = ptrData[i];
99  }
100  // Il resto dei 128 vengono impostati RANDOM
101  for (uint8_t i = val.unstructured.value.count; i < uavcan_node_GetInfo_Response_1_0_unique_id_ARRAY_CAPACITY_; i++)
102  {
103  val.unstructured.value.elements[val.unstructured.value.count++] = (uint8_t) rand(); // NOLINT
104  }
105  localRegisterAccessLock->Take();
106  localRegister->read(REGISTER_UAVCAN_UNIQUE_ID, &val);
107  localRegisterAccessLock->Give();
108  LOCAL_ASSERT(uavcan_register_Value_1_0_is_unstructured_(&val) &&
109  val.unstructured.value.count == uavcan_node_GetInfo_Response_1_0_unique_id_ARRAY_CAPACITY_);
110  memcpy(&out[0], &val.unstructured.value, uavcan_node_GetInfo_Response_1_0_unique_id_ARRAY_CAPACITY_);
111 }
112 
118 CanardPortID CanTask::getModeAccessID(uint8_t modeAccessID, const char* const port_name, const char* const type_name) {
119  // Deduce the register name from port name e modeAccess
120  char register_name[uavcan_register_Name_1_0_name_ARRAY_CAPACITY_] = {0};
121  // In funzione del modo imposta il registro corretto
122  switch (modeAccessID) {
123  case canardClass::Introspection_Port::PublisherSubjectID:
124  snprintf(&register_name[0], sizeof(register_name), "uavcan.pub.%s.id", port_name);
125  break;
126  case canardClass::Introspection_Port::SubscriptionSubjectID:
127  snprintf(&register_name[0], sizeof(register_name), "uavcan.sub.%s.id", port_name);
128  break;
129  case canardClass::Introspection_Port::ClientPortID:
130  snprintf(&register_name[0], sizeof(register_name), "uavcan.cln.%s.id", port_name);
131  break;
132  case canardClass::Introspection_Port::ServicePortID:
133  snprintf(&register_name[0], sizeof(register_name), "uavcan.srv.%s.id", port_name);
134  break;
135  }
136 
137  // Set up the default value. It will be used to populate the register if it doesn't exist.
138  static uavcan_register_Value_1_0 val = {0};
139  uavcan_register_Value_1_0_select_natural16_(&val);
140  val.natural16.value.count = 1;
141  val.natural16.value.elements[0] = UINT16_MAX; // This means "undefined", per Specification, which is the default.
142 
143  // Read the register with defensive self-checks.
144  localRegisterAccessLock->Take();
145  localRegister->read(&register_name[0], &val);
146  localRegisterAccessLock->Give();
147  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == 1));
148  const uint16_t result = val.natural16.value.elements[0];
149 
150  // This part is NOT required but recommended by the Specification for enhanced introspection capabilities. It is
151  // very cheap to implement so all implementations should do so. This register simply contains the name of the
152  // type exposed at this port. It should be immutable but it is not strictly required so in this implementation
153  // we take shortcuts by making it mutable since it's behaviorally simpler in this specific case.
154  // In funzione del modo imposta il registro corretto
155  switch (modeAccessID) {
156  case canardClass::Introspection_Port::PublisherSubjectID:
157  snprintf(&register_name[0], sizeof(register_name), "uavcan.pub.%s.type", port_name);
158  break;
159  case canardClass::Introspection_Port::SubscriptionSubjectID:
160  snprintf(&register_name[0], sizeof(register_name), "uavcan.sub.%s.type", port_name);
161  break;
162  case canardClass::Introspection_Port::ClientPortID:
163  snprintf(&register_name[0], sizeof(register_name), "uavcan.cln.%s.type", port_name);
164  break;
165  case canardClass::Introspection_Port::ServicePortID:
166  snprintf(&register_name[0], sizeof(register_name), "uavcan.srv.%s.type", port_name);
167  break;
168  }
169 
170  uavcan_register_Value_1_0_select_string_(&val);
171  val._string.value.count = nunavutChooseMin(strlen(type_name), uavcan_primitive_String_1_0_value_ARRAY_CAPACITY_);
172  memcpy(&val._string.value.elements[0], type_name, val._string.value.count);
173  localRegisterAccessLock->Take();
174  localRegister->read(&register_name[0], &val);
175  localRegisterAccessLock->Give();
176 
177  return result;
178 }
179 
187 bool CanTask::putFlashFile(const char* const file_name, const bool is_firmware, const bool rewrite, void* buf, size_t count)
188 {
189  #ifdef CHECK_FLASH_WRITE
190  // check data (W->R) Verify Flash integrity OK
191  uint8_t check_data[FLASH_BUFFER_SIZE];
192  #endif
193  // Request New File Init Upload
194  if(rewrite) {
195  // Qspi Security Semaphore
196  if(localQspiLock->Take(Ticks::MsToTicks(FLASH_SEMAPHORE_MAX_WAITING_TIME_MS))) {
197  // Init if required (DeInit after if required PowerDown Module)
198  if(localFlash->BSP_QSPI_Init() != Flash::QSPI_OK) {
199  localQspiLock->Give();
200  return false;
201  }
202  // Check Status Flash OK
203  Flash::QSPI_StatusTypeDef sts = localFlash->BSP_QSPI_GetStatus();
204  if (sts) {
205  localQspiLock->Give();
206  return false;
207  }
208  // Start From PtrFlash 0x100 (Reserve 256 Bytes For InfoFile)
209  if (is_firmware) {
210  // Firmware Flash
211  canFlashPtr = FLASH_FW_POSITION;
212  } else {
213  // Standard File Data Upload
214  canFlashPtr = FLASH_FILE_POSITION;
215  }
216  // Get Block Current into Flash
217  canFlashBlock = canFlashPtr / AT25SF161_BLOCK_SIZE;
218  // Erase First Block Block (Block OF 4KBytes)
219  TRACE_INFO_F(F("FLASH: Erase block: %d\r\n"), canFlashBlock);
220  if (localFlash->BSP_QSPI_Erase_Block(canFlashBlock)) {
221  localQspiLock->Give();
222  return false;
223  }
224  // Write Name File (Size at Eof...)
225  uint8_t file_flash_name[FLASH_FILE_SIZE_LEN] = {0};
226  memcpy(file_flash_name, file_name, strlen(file_name));
227  localFlash->BSP_QSPI_Write(file_flash_name, canFlashPtr, FLASH_FILE_SIZE_LEN);
228  // Write into Flash
229  TRACE_INFO_F(F("FLASH: Write [ %d ] bytes at addr: %d\r\n"), FLASH_FILE_SIZE_LEN, canFlashPtr);
230  #ifdef CHECK_FLASH_WRITE
231  localFlash->BSP_QSPI_Read(check_data, canFlashPtr, FLASH_FILE_SIZE_LEN);
232  if(memcmp(file_flash_name, check_data, FLASH_FILE_SIZE_LEN)==0) {
233  TRACE_INFO_F(F("FLASH: Reading check OK\r\n"));
234  } else {
235  TRACE_ERROR_F(F("FLASH: Reading check ERROR\r\n"));
236  localQspiLock->Give();
237  return false;
238  }
239  #endif
240  // Start Page...
241  canFlashPtr += FLASH_INFO_SIZE_LEN;
242  localQspiLock->Give();
243  }
244  }
245  // Write Data Block
246  // Qspi Security Semaphore
247  if(localQspiLock->Take(Ticks::MsToTicks(FLASH_SEMAPHORE_MAX_WAITING_TIME_MS))) {
248  // 0 = Is UavCan Signal EOF for Last Block Exact Len 256 Bytes...
249  // If Value Count is 0 no need to Write Flash Data (Only close Fule Info)
250  if(count!=0) {
251  // Write into Flash
252  TRACE_INFO_F(F("FLASH: Write [ %d ] bytes at addr: %d\r\n"), count, canFlashPtr);
253  // Starting Write at OFFSET Required... Erase here is Done
254  localFlash->BSP_QSPI_Write((uint8_t*)buf, canFlashPtr, count);
255  #ifdef CHECK_FLASH_WRITE
256  localFlash->BSP_QSPI_Read(check_data, canFlashPtr, count);
257  if(memcmp(buf, check_data, count)==0) {
258  TRACE_INFO_F(F("FLASH: Reading check OK\r\n"));
259  } else {
260  TRACE_ERROR_F(F("FLASH: Reading check ERROR\r\n"));
261  localQspiLock->Give();
262  return false;
263  }
264  #endif
265  canFlashPtr += count;
266  // Check if Next Page Addressed (For Erase Next Block)
267  if((canFlashPtr / AT25SF161_BLOCK_SIZE) != canFlashBlock) {
268  canFlashBlock = canFlashPtr / AT25SF161_BLOCK_SIZE;
269  // Erase First Block Block (Block OF 4KBytes)
270  TRACE_INFO_F(F("FLASH: Erase block: %d\r\n"), canFlashBlock);
271  if (localFlash->BSP_QSPI_Erase_Block(canFlashBlock)) {
272  localQspiLock->Give();
273  return false;
274  }
275  }
276  }
277  // Eof if != 256 Bytes Write
278  if(count!=0x100) {
279  // Write Info File for Closing...
280  // Size at
281  uint64_t lenghtFile = canFlashPtr - FLASH_INFO_SIZE_LEN;
282  if (is_firmware) {
283  // Firmware Flash
284  canFlashPtr = FLASH_FW_POSITION;
285  } else {
286  // Standard File Data Upload
287  canFlashPtr = FLASH_FILE_POSITION;
288  }
289  localFlash->BSP_QSPI_Write((uint8_t*)&lenghtFile, FLASH_SIZE_ADDR(canFlashPtr), FLASH_INFO_SIZE_U64);
290  // Write into Flash
291  TRACE_INFO_F(F("FLASH: Write [ %d ] bytes at addr: %d\r\n"), FLASH_INFO_SIZE_U64, canFlashPtr);
292  #ifdef CHECK_FLASH_WRITE
293  localFlash->BSP_QSPI_Read(check_data, FLASH_SIZE_ADDR(canFlashPtr), FLASH_INFO_SIZE_U64);
294  if(memcmp(&lenghtFile, check_data, FLASH_INFO_SIZE_U64)==0) {
295  TRACE_INFO_F(F("FLASH: Reading check OK\r\n"));
296  } else {
297  TRACE_INFO_F(F("FLASH: Reading check ERROR\r\n"));
298  }
299  #endif
300  }
301  localQspiLock->Give();
302  }
303  return true;
304 }
305 
312 bool CanTask::getFlashFwInfoFile(uint8_t *module_type, uint8_t *version, uint8_t *revision, uint64_t *len)
313 {
314  uint8_t block[FLASH_FILE_SIZE_LEN];
315  bool fileReady = false;
316 
317  // Qspi Security Semaphore
318  if(localQspiLock->Take(Ticks::MsToTicks(FLASH_SEMAPHORE_MAX_WAITING_TIME_MS))) {
319  // Init if required (DeInit after if required PowerDown Module)
320  if(localFlash->BSP_QSPI_Init() != Flash::QSPI_OK) {
321  localQspiLock->Give();
322  return false;
323  }
324  // Check Status Flash OK
325  if (localFlash->BSP_QSPI_GetStatus()) {
326  localQspiLock->Give();
327  return false;
328  }
329 
330  // Read Name file, Version and Info
331  localFlash->BSP_QSPI_Read(block, 0, FLASH_FILE_SIZE_LEN);
332  char stima_name[STIMA_MODULE_NAME_LENGTH] = {0};
333  getStimaNameByType(stima_name, MODULE_TYPE);
334  if(checkStimaFirmwareType((char*)block, module_type, version, revision)) {
335  localFlash->BSP_QSPI_Read((uint8_t*)len, FLASH_SIZE_ADDR(0), FLASH_INFO_SIZE_U64);
336  fileReady = true;
337  }
338  localQspiLock->Give();
339  }
340  return fileReady;
341 }
342 
343 // ***********************************************************************************************
344 // ***********************************************************************************************
345 // FUNZIONI CHIAMATE DA MAIN_LOOP DI PUBBLICAZIONE E RICHIESTE DATI E SERVIZI
346 // ***********************************************************************************************
347 // ***********************************************************************************************
348 
349 // ******* FUNZIONI RMAP PUBLISH LOCAL DATA *********
350 
357 void CanTask::prepareSensorsDataValue(uint8_t const sensore, const report_t *report, rmap_module_Rain_1_0 *rmap_data) {
358  // Inserisco i dati reali
359  switch (sensore) {
360  case canardClass::Sensor_Type::tbr:
361  // Prepara i dati TBR (Accumulate)
362  rmap_data->TBR.rain.val.value = report->rain;
363  rmap_data->TBR.rain.confidence.value = report->quality;
364  break;
365  case canardClass::Sensor_Type::tpr:
366  // Prepara i dati TPR (Rate)
367  rmap_data->TPR.shortRate.val.value = report->rain_tpr_60s_avg;
368  rmap_data->TPR.shortRate.confidence.value = report->quality;
369  rmap_data->TPR.longRate.val.value = report->rain_tpr_05m_avg;
370  rmap_data->TPR.longRate.confidence.value = report->quality;
371  break;
372  case canardClass::Sensor_Type::tbm:
373  // Prepara i dati TBM (Sample)
374  rmap_data->TBR.rain.val.value = report->rain_full;
375  rmap_data->TBR.rain.confidence.value = report->quality;
376  break;
377  }
378 }
379 void CanTask::prepareSensorsDataValue(uint8_t const sensore, const report_t *report, rmap_service_module_Rain_Response_1_0 *rmap_data) {
380  // Inserisco i dati reali
381  switch (sensore) {
382  case canardClass::Sensor_Type::tbr:
383  // Prepara i dati TBR (Accumulate)
384  rmap_data->TBR.rain.val.value = report->rain;
385  rmap_data->TBR.rain.confidence.value = report->quality;
386  break;
387  case canardClass::Sensor_Type::tpr:
388  // Prepara i dati TPR (Rate)
389  rmap_data->TPR.shortRate.val.value = report->rain_tpr_60s_avg;
390  rmap_data->TPR.shortRate.confidence.value = report->quality;
391  rmap_data->TPR.longRate.val.value = report->rain_tpr_05m_avg;
392  rmap_data->TPR.longRate.confidence.value = report->quality;
393  break;
394  case canardClass::Sensor_Type::tbm:
395  // Prepara i dati TBM (Sample)
396  rmap_data->TBR.rain.val.value = report->rain_full;
397  rmap_data->TBR.rain.confidence.value = report->quality;
398  break;
399  }
400 }
401 
406  // Pubblica i dati del nodo corrente se abilitata la funzione e con il corretto subjectId
407  // Ovviamente il nodo non può essere anonimo per la pubblicazione...
408  if ((!clCanard.is_canard_node_anonymous()) &&
409  (clCanard.publisher_enabled.module_rain) &&
410  (clCanard.port_id.publisher_module_rain <= CANARD_SUBJECT_ID_MAX)) {
411  rmap_module_Rain_1_0 module_rain_msg = {0};
412 
413  request_data_t request_data = {0};
414  report_t report_pub = {0};
415 
416  // preparo la struttura dati per richiedere i dati al task che li elabora
417  // in publish non inizializzo coda, pibblico in funzione del'ultima riichiesta di CFG
418  // Il dato report_time_s non risiede sullo slave ma è in chimata da master
419  request_data.is_init = false; // utilizza i dati esistenti (continua le elaborazioni precedentemente inizializzate)
420  request_data.report_time_s = last_req_rpt_time; // richiedo i dati in conformità a standard request (report)
421  request_data.observation_time_s = last_req_obs_time; // richiedo i dati in conformità a standard request (observation)
422 
423  // SET Dynamic metadata (Request data from master Only Data != Sample)
424  clCanard.module_rain.TBR.metadata.timerange.P2 = request_data.report_time_s;
425  clCanard.module_rain.TPR.metadata.timerange.P2 = request_data.report_time_s;
426 
427  // coda di richiesta dati
428  param->requestDataQueue->Enqueue(&request_data);
429 
430  // coda di attesa dati (attesa rmap_calc_data)
431  param->reportDataQueue->Dequeue(&report_pub);
432  TRACE_INFO_F(F("--> CAN rain report\t%d\t%d\t%d\t%d\r\n"), (rmapdata_t) report_pub.tips_count, (rmapdata_t) report_pub.rain, (rmapdata_t) report_pub.rain_full, (rmapdata_t) report_pub.quality);
433 
434  // Preparo i dati
435  prepareSensorsDataValue(canardClass::Sensor_Type::tbr, &report_pub, &module_rain_msg);
436  prepareSensorsDataValue(canardClass::Sensor_Type::tpr, &report_pub, &module_rain_msg);
437  // Metadata
438  module_rain_msg.TBR.metadata = clCanard.module_rain.TBR.metadata;
439  module_rain_msg.TPR.metadata = clCanard.module_rain.TPR.metadata;
440 
441  // Serialize and publish the message:
442  uint8_t serialized[rmap_module_Rain_1_0_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
443  size_t serialized_size = sizeof(serialized);
444  const int8_t err = rmap_module_Rain_1_0_serialize_(&module_rain_msg, &serialized[0], &serialized_size);
445  LOCAL_ASSERT(err >= 0);
446  if (err >= 0) {
447  const CanardTransferMetadata meta = {
448  .priority = CanardPrioritySlow,
449  .transfer_kind = CanardTransferKindMessage,
450  .port_id = clCanard.port_id.publisher_module_rain,
451  .remote_node_id = CANARD_NODE_ID_UNSET,
452  .transfer_id = (CanardTransferID)(clCanard.next_transfer_id.module_rain()), // Increment!
453  };
454  // Messaggio rapido 1/4 di secondo dal timeStamp Sincronizzato
455  clCanard.send(MEGA / 4, &meta, serialized_size, &serialized[0]);
456  }
457  }
458 }
459 
460 // ***************************************************************************************************
461 // Funzioni ed utility di ricezione dati dalla rete UAVCAN, richiamati da processReceivedTransfer()
462 // ***************************************************************************************************
463 
464 // Plug and Play Slave, Versione 1.0 compatibile con CAN_CLASSIC MTU 8
465 // Messaggi anonimi CAN non sono consentiti se messaggi > LUNGHEZZA MTU disponibile
466 
472  const uavcan_pnp_NodeIDAllocationData_1_0* const msg) {
473  // msg->unique_id_hash RX viene verificato per l'assegnazione in sicurezza del port_id corretto
474  uint64_t local_hash = StimaV4GetSerialNumber();
475  local_hash >>= HASH_EXCLUDING_BIT;
476  local_hash &= HASH_SERNUMB_MASK;
477  local_hash |= MODULE_TYPE;
478  // Verifico hash messaggio ed assegno l'ID al registro locale se corretto
479  if (msg->unique_id_hash == local_hash) {
480  if (msg->allocated_node_id.elements[0].value <= CANARD_NODE_ID_MAX) {
481  printf("Got PnP node-ID allocation: %d\n", msg->allocated_node_id.elements[0].value);
482  clCanard.set_canard_node_id((CanardNodeID)msg->allocated_node_id.elements[0].value);
483  // Richiedo immediata configurazione del modulo al master...
484  clCanard.flag.set_local_module_ready(false);
485  // Store the value into the non-volatile storage.
486  static uavcan_register_Value_1_0 reg = {0};
487  uavcan_register_Value_1_0_select_natural16_(&reg);
488  reg.natural16.value.elements[0] = msg->allocated_node_id.elements[0].value;
489  reg.natural16.value.count = 1;
490  localRegisterAccessLock->Take();
491  localRegister->write(REGISTER_UAVCAN_NODE_ID, &reg);
492  localRegisterAccessLock->Give();
493  // We no longer need the subscriber, drop it to free up the resources (both memory and CPU time).
494  clCanard.rxUnSubscribe(CanardTransferKindMessage,
495  uavcan_pnp_NodeIDAllocationData_1_0_FIXED_PORT_ID_);
496  }
497  }
498  // Otherwise, ignore it: either it is a request from another node or it is a response to another node.
499 }
500 
506 uavcan_node_ExecuteCommand_Response_1_1 CanTask::processRequestExecuteCommand(canardClass &clCanard, const uavcan_node_ExecuteCommand_Request_1_1* req,
507  uint8_t remote_node) {
508  uavcan_node_ExecuteCommand_Response_1_1 resp = {0};
509  // System Queue request Structure data
510  // Command-> Accelerometer Calibrate...
511  // Send Command directly To Task (Init to Null)
512  system_message_t system_message = {0};
513 
514  // req->command (Comando esterno ricevuto 2 BYTES RESERVED FFFF-FFFA)
515  // Gli altri sono liberi per utilizzo interno applicativo con #define interne
516  // req->parameter (array di byte MAX 255 per i parametri da request)
517  // Risposta attuale (resp) 1 Bytes RESERVED (0..6) gli altri #define interne
518  switch (req->command)
519  {
520  // **************** Comandi standard UAVCAN GENERIC_SPECIFIC_COMMAND ****************
521  // Comando di aggiornamento Firmware compatibile con Yakut e specifice UAVCAN
522  case uavcan_node_ExecuteCommand_Request_1_1_COMMAND_BEGIN_SOFTWARE_UPDATE:
523  {
524  // Nodo Server chiamante (Yakut solo Master, Yakut e Master per Slave)
525  clCanard.master.file.start_request(remote_node, (uint8_t*) req->parameter.elements,
526  req->parameter.count, true);
527  clCanard.flag.set_local_fw_uploading(true);
528  TRACE_INFO_F(F("Firmware update request from node id: %u\r\n"), clCanard.master.file.get_server_node());
529  TRACE_INFO_F(F("Filename to download: %s\r\n"), clCanard.master.file.get_name());
530  // Avvio la funzione con OK
531  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
532  break;
533  }
534  case uavcan_node_ExecuteCommand_Request_1_1_COMMAND_FACTORY_RESET:
535  {
536  localRegisterAccessLock->Take();
537  localRegister->doFactoryReset();
538  localRegisterAccessLock->Give();
539  // Istant Reboot for next Register base Setup
540  NVIC_SystemReset();
541  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
542  break;
543  }
544  case uavcan_node_ExecuteCommand_Request_1_1_COMMAND_RESTART:
545  {
546  clCanard.flag.request_system_restart();
547  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
548  break;
549  }
550  case uavcan_node_ExecuteCommand_Request_1_1_COMMAND_STORE_PERSISTENT_STATES:
551  {
552  // If your registers are not automatically synchronized with the non-volatile storage, use this command
553  // to commit them to the storage explicitly. Otherwise it is safe to remove it.
554  // In this demo, the registers are stored in files, so there is nothing to do.
555  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
556  break;
557  }
558  // **************** Comandi personalizzati VENDOR_SPECIFIC_COMMAND ****************
559  // Comando di download File generico compatibile con specifice UAVCAN, (LOG/CFG altro...)
560  case canardClass::Command_Private::download_file:
561  {
562  // Nodo Server chiamante (Yakut solo Master, Yakut e Master per Slave)
563  clCanard.master.file.start_request(remote_node, (uint8_t*) req->parameter.elements,
564  req->parameter.count, false);
565  clCanard.flag.set_local_fw_uploading(true);
566  TRACE_INFO_F(F("File standard update request from node id: %u\r\n"), clCanard.master.file.get_server_node());
567  TRACE_INFO_F(F("Filename to download: %s\r\n"), clCanard.master.file.get_name());
568  // Avvio la funzione con OK
569  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
570  break;
571  }
572  case canardClass::Command_Private::calibrate_accelerometer:
573  {
574  // Avvia calibrazione accelerometro (reset bolla elettroniuca)
575  TRACE_INFO_F(F("AVVIA Calibrazione accelerometro e salvataggio parametri\r\n"));
576  // Send queue command to TASK
577  system_message.task_dest = ACCELEROMETER_TASK_ID;
578  system_message.command.do_calib = true;
579  if(localSystemMessageQueue->Enqueue(&system_message, Ticks::MsToTicks(WAIT_QUEUE_REQUEST_COMMAND_MS))) {
580  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
581  } else {
582  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_FAILURE;
583  }
584  break;
585  }
586  case canardClass::Command_Private::module_maintenance:
587  {
588  // Avvia/Arresta modalità di manutenzione come comando sul system status
589  if(req->parameter.elements[0]) {
590  TRACE_INFO_F(F("AVVIA modalità di manutenzione modulo\r\n"));
591  } else {
592  TRACE_INFO_F(F("ARRESTA modalità di manutenzione modulo\r\n"));
593  }
594  // Send queue command to TASK
595  system_message.task_dest = SUPERVISOR_TASK_ID;
596  system_message.command.do_maint = 1;
597  system_message.param = req->parameter.elements[0];
598  if(localSystemMessageQueue->Enqueue(&system_message, Ticks::MsToTicks(WAIT_QUEUE_REQUEST_COMMAND_MS))) {
599  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
600  } else {
601  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_FAILURE;
602  }
603  break;
604  }
605  case canardClass::Command_Private::reset_flags:
606  {
607  // Avvia calibrazione accelerometro (reset bolla elettroniuca)
608  TRACE_INFO_F(F("RESET flags di sistema e salvataggio stati\r\n"));
609  // Reset counter on new or restored firmware
610  boot_state->tot_reset = 0;
611  boot_state->wdt_reset = 0;
612  // Save info bootloader block
613  localEeprom->Write(BOOT_LOADER_STRUCT_ADDR, (uint8_t*) boot_state, sizeof(bootloader_t));
614  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
615  break;
616  }
617  case canardClass::Command_Private::enable_publish_rmap:
618  {
619  // Abilita pubblicazione fast_loop data_and_metadata modulo locale (test yakut e user master)
620  clCanard.publisher_enabled.module_rain = true;
621  TRACE_INFO_F(F("ATTIVO Trasmissione dati in publish\r\n"));
622  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
623  break;
624  }
625  case canardClass::Command_Private::disable_publish_rmap:
626  {
627  // Disabilita pubblicazione fast_loop data_and_metadata modulo locale (test yakut e user master)
628  clCanard.publisher_enabled.module_rain = false;
629  TRACE_INFO_F(F("DISATTIVO Trasmissione dati in publish\r\n"));
630  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
631  break;
632  }
633  case canardClass::Command_Private::enable_publish_port_list:
634  {
635  // Abilita pubblicazione slow_loop elenco porte (Cypal facoltativo)
636  clCanard.publisher_enabled.port_list = true;
637  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
638  break;
639  }
640  case canardClass::Command_Private::disable_publish_port_list:
641  {
642  // Disabilita pubblicazione slow_loop elenco porte (Cypal facoltativo)
643  clCanard.publisher_enabled.port_list = false;
644  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_SUCCESS;
645  break;
646  }
647  case canardClass::Command_Private::remote_test:
648  {
649  // Test locale / remoto
650  resp.status = canardClass::Command_Private::remote_test_value;
651  break;
652  }
653  default:
654  {
655  resp.status = uavcan_node_ExecuteCommand_Response_1_1_STATUS_BAD_COMMAND;
656  break;
657  }
658  }
659  return resp;
660 }
661 
667 rmap_service_module_Rain_Response_1_0 CanTask::processRequestGetModuleData(canardClass &clCanard, rmap_service_module_Rain_Request_1_0* req, CanParam_t *param) {
668  rmap_service_module_Rain_Response_1_0 resp = {0};
669  // Richiesta parametri univoca a tutti i moduli
670  // req->parametri tipo: rmap_service_setmode_1_0
671  // req->parameter.command (Comando esterno ricevuto 3 BIT)
672  // req->parametri.run_sectime (Timer to run 13 bit)
673 
674  request_data_t request_data = {0};
675  report_t report_srv = {0};
676  bool isRunIdleHookEnabled;
677 
678  // Case comandi RMAP su GetModule Data (Da definire con esattezza quali e quanti altri)
679  switch (req->parameter.command) {
680 
683  case rmap_service_setmode_1_0_get_istant: // saturated uint3 get_istant = 0
684  case rmap_service_setmode_1_0_get_current: // saturated uint3 get_current = 1
685  case rmap_service_setmode_1_0_get_last: // saturated uint3 get_last = 2
686 
687  // preparo la struttura dati per richiedere i dati al task che li elabora
688  if(req->parameter.command == rmap_service_setmode_1_0_get_istant) {
689  // Solo Sample istantaneo
690  request_data.is_init = false; // No Init, Sample
691  request_data.report_time_s = 0; // richiedo i dati su 0 secondi (Sample)
692  request_data.observation_time_s = 0; // richiedo i dati mediati su 0 secondi (Sample)
693  }
694  if((req->parameter.command == rmap_service_setmode_1_0_get_current)||
695  (req->parameter.command == rmap_service_setmode_1_0_get_last)) {
696  // Dato corrente con o senza inizializzazione (get_last...)
697  if(req->parameter.command == rmap_service_setmode_1_0_get_current)
698  request_data.is_init = false; // utilizza i dati esistenti (continua le elaborazioni precedentemente inizializzate)
699  else
700  request_data.is_init = true; // Reinit delle elaborazioni
701  request_data.report_time_s = req->parameter.run_sectime; // richiedo i dati su request secondi
702  request_data.observation_time_s = req->parameter.obs_sectime; // richiedo i dati mediati su request secondi
703  last_req_rpt_time = req->parameter.run_sectime; // report_time_request_backup;
704  last_req_obs_time = req->parameter.obs_sectime; // observation_time_request_backup;
705  // SET Dynamic metadata (Request data from master Only Data != Sample)
706  clCanard.module_rain.TBR.metadata.timerange.P2 = request_data.report_time_s;
707  clCanard.module_rain.TPR.metadata.timerange.P2 = request_data.report_time_s;
708  }
709 
710  // Preparo gli event Reboot and WDT Event
711  resp.rbt_event = boot_state->tot_reset;
712  resp.wdt_event = boot_state->wdt_reset;
713 
714  // coda di richiesta dati immediata. Full power for make report
715  isRunIdleHookEnabled = LowPower.isIdleHookEnabled();
716  LowPower.idleHookDisable();
717  param->requestDataQueue->Enqueue(&request_data);
718  // coda di attesa dati (attesa rmap_calc_data)
719  param->reportDataQueue->Dequeue(&report_srv);
720  if(isRunIdleHookEnabled) LowPower.idleHookEnable();
721 
722  TRACE_INFO_F(F("--> CAN rain report\t%d\t%d\t%d\t%d\r\n"), (rmapdata_t) report_srv.tips_count, (rmapdata_t) report_srv.rain, (rmapdata_t) report_srv.rain_full, (rmapdata_t) report_srv.quality);
723 
724  // Preparo il ritorno dei flag event status del sensore (Successivo a request/reset. Init reset interno con var di appoggio)
725  resp.is_accelerometer_error = param->system_status->events.is_accelerometer_error;
726  resp.is_bubble_level_error = param->system_status->events.is_bubble_level_error;
727  resp.is_clogged_up = param->system_status->events.is_clogged_up;
728  resp.is_main_error = param->system_status->events.is_main_error;
729  resp.is_redundant_error = param->system_status->events.is_redundant_error;
730  resp.is_tipping_error = param->system_status->events.is_tipping_error;
731 
732  // Ritorno lo stato (Copia dal comando... con stato maintenence e versioni di modulo)
733  resp.state = req->parameter.command; // saturated 4BIT (3BITCommand + FlagMaintenance)
735  resp.version = MODULE_MAIN_VERSION;
736  resp.revision = MODULE_MINOR_VERSION;
737 
738  // Preparo la risposta con i dati recuperati dalla coda (come da request CAN)
739  if(req->parameter.command == rmap_service_setmode_1_0_get_istant) {
740  // Solo Istantaneo (Sample display request)
741  prepareSensorsDataValue(canardClass::Sensor_Type::tbm, &report_srv, &resp);
742  } else {
743  prepareSensorsDataValue(canardClass::Sensor_Type::tbr, &report_srv, &resp);
744  prepareSensorsDataValue(canardClass::Sensor_Type::tpr, &report_srv, &resp);
745  }
746  break;
747 
748  // NOT USED
749  // saturated uint3 stop_acq = 4
750  // #define rmap_service_setmode_1_0_stop_acq (4U)
751  // saturated uint3 loop_acq = 5
752  // #define rmap_service_setmode_1_0_loop_acq (5U)
753  // saturated uint3 continuos_acq = 6
754  // #define rmap_service_setmode_1_0_continuos_acq (6U)
755 
757  case rmap_service_setmode_1_0_test_acq:
758  resp.state = req->parameter.command;
759  break;
760 
762  default:
763  resp.state = GENERIC_STATE_UNDEFINED;
764  break;
765  }
766 
767  // Copio i metadati fissi e mobili
768  resp.TBR.metadata = clCanard.module_rain.TBR.metadata;
769  resp.TPR.metadata = clCanard.module_rain.TPR.metadata;
770 
771  return resp;
772 }
773 
777 uavcan_register_Access_Response_1_0 CanTask::processRequestRegisterAccess(const uavcan_register_Access_Request_1_0* req) {
778  char name[uavcan_register_Name_1_0_name_ARRAY_CAPACITY_ + 1] = {0};
779  LOCAL_ASSERT(req->name.name.count < sizeof(name));
780  memcpy(&name[0], req->name.name.elements, req->name.name.count);
781  name[req->name.name.count] = '\0';
782 
783  uavcan_register_Access_Response_1_0 resp = {0};
784 
785  // If we're asked to write a new value, do it now:
786  if (!uavcan_register_Value_1_0_is_empty_(&req->value)) {
787  uavcan_register_Value_1_0_select_empty_(&resp.value);
788  localRegisterAccessLock->Take();
789  localRegister->read(&name[0], &resp.value);
790  localRegisterAccessLock->Give();
791  // If such register exists and it can be assigned from the request value:
792  if (!uavcan_register_Value_1_0_is_empty_(&resp.value) && localRegister->assign(&resp.value, &req->value)) {
793  localRegisterAccessLock->Take();
794  localRegister->write(&name[0], &resp.value);
795  localRegisterAccessLock->Give();
796  }
797  }
798 
799  // Regardless of whether we've just wrote a value or not, we need to read the current one and return it.
800  // The client will determine if the write was successful or not by comparing the request value with response.
801  uavcan_register_Value_1_0_select_empty_(&resp.value);
802  localRegisterAccessLock->Take();
803  localRegister->read(&name[0], &resp.value);
804  localRegisterAccessLock->Give();
805 
806  // Currently, all registers we implement are mutable and persistent. This is an acceptable simplification,
807  // but more advanced implementations will need to differentiate between them to support advanced features like
808  // exposing internal states via registers, perfcounters, etc.
809  resp._mutable = true;
810  resp.persistent = true;
811 
812  // Our node does not synchronize its time with the network so we can't populate the timestamp.
813  resp.timestamp.microsecond = uavcan_time_SynchronizedTimestamp_1_0_UNKNOWN;
814 
815  return resp;
816 }
817 
820 uavcan_node_GetInfo_Response_1_0 CanTask::processRequestNodeGetInfo() {
821  uavcan_node_GetInfo_Response_1_0 resp = {0};
822  resp.protocol_version.major = CANARD_CYPHAL_SPECIFICATION_VERSION_MAJOR;
823  resp.protocol_version.minor = CANARD_CYPHAL_SPECIFICATION_VERSION_MINOR;
824 
825  // The hardware version is not populated in this demo because it runs on no specific hardware.
826  // An embedded node would usually determine the version by querying the hardware.
827 
828  resp.software_version.major = MODULE_MAIN_VERSION;
829  resp.software_version.minor = MODULE_MINOR_VERSION;
830  resp.software_vcs_revision_id = RMAP_PROCOTOL_VERSION;
831 
832  getUniqueID(resp.unique_id, StimaV4GetSerialNumber());
833 
834  // The node name is the name of the product like a reversed Internet domain name (or like a Java package).
835  char stima_name[STIMA_MODULE_NAME_LENGTH] = {0};
836  getStimaNameByType(stima_name, MODULE_TYPE);
837  resp.name.count = strlen(stima_name);
838  memcpy(&resp.name.elements, stima_name, resp.name.count);
839 
840  // The software image CRC and the Certificate of Authenticity are optional so not populated in this demo.
841  return resp;
842 }
843 
844 // ******************************************************************************************
845 // CallBack di classe canardClass ( Gestisce i metodi uavcan sottoscritti )
846 // Processo multiplo di ricezione messaggi e comandi. Gestione entrata ed uscita dei messaggi
847 // Chiamata direttamente nel main loop in ricezione dalla coda RX
848 // Richiama le funzioni qui sopra di preparazione e risposta alle richieste
849 // ******************************************************************************************
850 
855 void CanTask::processReceivedTransfer(canardClass &clCanard, const CanardRxTransfer* const transfer, void *param) {
856 
857  // System Queue request Structure data
858  // Command-> Accelerometer Calibrate...
859  // Send Command directly To Task (Init to Null)
860  system_message_t system_message = {0};
861 
862  // Gestione dei Messaggi in ingresso
863  if (transfer->metadata.transfer_kind == CanardTransferKindMessage)
864  {
865  if (transfer->metadata.port_id == uavcan_node_Heartbeat_1_0_FIXED_PORT_ID_)
866  {
867  // Ricevo messaggi Heartbeat per stato rete (Controllo esistenza del MASTER)
868  // Solo a scopo precauzionale per attività da gestire alla cieca (SAVE QUEUE LOG, DATA ecc...)
869  size_t size = transfer->payload_size;
870  uavcan_node_Heartbeat_1_0 msg = {0};
871  if (uavcan_node_Heartbeat_1_0_deserialize_(&msg, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
872  // Controllo e gestisco solo il nodo MASTER
873  if(transfer->metadata.remote_node_id == clCanard.get_canard_master_id()) {
874  // Entro in OnLine se precedentemente arrivo dall'OffLine
875  // ed eseguo eventuali operazioni di entrata in attività se necessario
876  // Opzionale Controllo ONLINE direttamente dal messaggio Interno
877  // if (!clCanard.master.heartbeat.is_online()) {
878  // Il master è entrato in modalità ONLine e gestisco
879  // TRACE_VERBOSE(F("Master controller ONLINE !!! Starting application..."));
880  // }
881  // Set PowerMode da comando HeartBeat Remoto remoteVSC.powerMode
882  // Eventuali alri flag gestiti direttamente quà e SET sulla classe
883  canardClass::heartbeat_VSC remoteVSC;
884  // remoteVSC.powerMode
885  remoteVSC.uint8_val = msg.vendor_specific_status_code;
886  TRACE_VERBOSE_F(F("RX HeartBeat from master, master power mode SET: -> %u\r\n"), remoteVSC.powerMode);
887 
888  // Processo e registro il nodo: stato, OnLine e relativi flag
889  // Set canard_us local per controllo NodoOffline (validità area di OnLine)
891  // SET Modalità Power richiesta dal Master (in risposta ad HeartBeat locale...)
892  // SErve come conferma al master e come flag locale di azione Power
893  clCanard.flag.set_local_power_mode(remoteVSC.powerMode);
894 
895  // PowerOn, Non faccio nulla o eventuale altra gestione (Tutto ON)
896  // if(remoteVSC.powerMode == canardClass::Power_Mode::pwr_on) {
897  // Ipotesi All Power Sensor ON...
898  // }
899 
900  // Gestisco lo stato Power come richiesto dal Master immediatamente se != power_on
901  if(remoteVSC.powerMode == Power_Mode::pwr_nominal) {
902  // ENTER STANDARD SLEEP FROM CAN COMMAND
903  #ifndef _EXIT_SLEEP_FOR_DEBUGGING
904  system_message.task_dest = ALL_TASK_ID;
905  system_message.command.do_sleep = true;
906  localSystemMessageQueue->Enqueue(&system_message, Ticks::MsToTicks(WAIT_QUEUE_REQUEST_COMMAND_MS));
907  #endif
908  }
909 
910  // if(remoteVSC.powerMode == canardClass::Power_Mode::pwr_deep_save) {
911  // Ipotesi CAN ON solo al passaggio del minuto 57..60 per syncroTime, Cmd e DataSend
912  // }
913 
914  // if(remoteVSC.powerMode == canardClass::Power_Mode::pwr_critical) {
915  // Ipotesi DeepSleep. Save Param in Flash e PowerDown completo 60 Minuti...
916  // }
917  }
918  }
919  }
920  else if (transfer->metadata.port_id == uavcan_time_Synchronization_1_0_FIXED_PORT_ID_)
921  {
922  // Ricevo messaggi Heartbeat per syncro_time CanardMicrosec (Base dei tempi locali dal MASTER)
923  // Gestione differenze del tempo tra due comunicazioni Canard time_incro del master (local adjust time)
924  size_t size = transfer->payload_size;
925  uavcan_time_Synchronization_1_0 msg = {0};
926  if (uavcan_time_Synchronization_1_0_deserialize_(&msg, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
927  // Controllo e gestisco solo il nodo MASTER come SyncroTime (a gestione locale)
928  // Non sono previsti multi sincronizzatori ma la selezione è esterna alla classe
929  if(transfer->metadata.remote_node_id == clCanard.get_canard_master_id()) {
930  bool isSyncronized = false;
931  CanardMicrosecond timestamp_synchronized_us;
932  // Controllo coerenza messaggio per consentire e verificare l'aggiornamento timestamp
934  transfer->metadata.transfer_id,
935  msg.previous_transmission_timestamp_microsecond)) {
936  // Leggo il time stamp sincronizzato da gestire per Setup RTC
937  timestamp_synchronized_us = clCanard.master.timestamp.get_timestamp_syncronized(
938  transfer->timestamp_usec,
939  msg.previous_transmission_timestamp_microsecond);
940  isSyncronized = true;
941  } else {
942  TRACE_VERBOSE_F(F("RX TimeSyncro from master, reset or invalid Value at local_time_stamp (uSec): %u\r\n"), transfer->timestamp_usec);
943  }
944  // Aggiorna i temporizzatori locali per il prossimo controllo
945  CanardMicrosecond last_message_diff_us = clCanard.master.timestamp.update_timestamp_message(
946  transfer->timestamp_usec, msg.previous_transmission_timestamp_microsecond);
947  // Stampa e/o SETUP RTC con sincronizzazione valida
948  if (isSyncronized) {
949  #if (TRACE_LEVEL >= TRACE_LEVEL_VERBOSE)
950  uint32_t low_ms = timestamp_synchronized_us % 1000u;
951  uint32_t high_ms = timestamp_synchronized_us / 1000u;
952  TRACE_VERBOSE_F(F("RX TimeSyncro from master, syncronized value is (uSec): "));
953  TRACE_VERBOSE_F(F("%lu"), high_ms);
954  TRACE_VERBOSE_F(F("%lu\r\n"), low_ms);
955  TRACE_VERBOSE_F(F(" from 2 message difference is (uSec): %lu\r\n"), (uint32_t)last_message_diff_us);
956  #endif
957  // *********** Adjust Local RTC Time *************
958  uint32_t currentSubsecond;
959  volatile uint64_t canardEpoch_ms;
960  // Get Millisecond from TimeStampSyncronized
961  uint64_t timeStampEpoch_ms = timestamp_synchronized_us / 1000ul;
962  // Second Epoch in Millisecond With Add Subsecond
963  canardEpoch_ms = (uint64_t) rtc.getEpoch(&currentSubsecond);
964  canardEpoch_ms *= 1000ul;
965  canardEpoch_ms += currentSubsecond;
966  // Refer to milliSecond for TimeStamp ( Set Epoch with abs (ull) difference > 250 mSec )
967  if(canardEpoch_ms > timeStampEpoch_ms) {
968  currentSubsecond = canardEpoch_ms - timeStampEpoch_ms;
969  } else {
970  currentSubsecond = timeStampEpoch_ms - canardEpoch_ms;
971  }
972  // currentSubsecond -> millisDifference from RTC and TimeStamp_Syncro_ms
973  if(currentSubsecond > 250) {
974  // Set RTC Epoch DateTime with timeStampEpoch (round mSec + 1)
975  TRACE_VERBOSE_F(F("RTC: Adjust time with TimeSyncro from master (difference %lu mS)\r\n"), currentSubsecond);
976  timeStampEpoch_ms++;
977  rtc.setEpoch(timeStampEpoch_ms / 1000, timeStampEpoch_ms % 1000);
978  }
979  }
980  }
981  }
982  }
983  else if (transfer->metadata.port_id == uavcan_pnp_NodeIDAllocationData_1_0_FIXED_PORT_ID_)
984  {
985  // PLUG AND PLAY (Dovrei ricevere solo in anonimo)
986  size_t size = transfer->payload_size;
987  uavcan_pnp_NodeIDAllocationData_1_0 msg = {0};
988  if (uavcan_pnp_NodeIDAllocationData_1_0_deserialize_(&msg, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
989  processMessagePlugAndPlayNodeIDAllocation(clCanard, &msg);
990  }
991  }
992  else
993  {
994  // Gestione di un messaggio senza sottoscrizione. Se arrivo quà è un errore di sviluppo
995  LOCAL_ASSERT(false);
996  }
997  }
998  else if (transfer->metadata.transfer_kind == CanardTransferKindRequest)
999  {
1000  // Gestione delle richieste esterne
1001  if (transfer->metadata.port_id == clCanard.port_id.service_module_rain) {
1002  // Richiesta ai dati e metodi di sensor drive
1003  rmap_service_module_Rain_Request_1_0 req = {0};
1004  size_t size = transfer->payload_size;
1005  TRACE_INFO_F(F("<<-- Ricevuto richiesta dati da master\r\n"));
1006  // The request object is empty so we don't bother deserializing it. Just send the response.
1007  if (rmap_service_module_Rain_Request_1_0_deserialize_(&req, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
1008  // I dati e metadati sono direttamente popolati in processRequestGetModuleData
1009  rmap_service_module_Rain_Response_1_0 module_rain_resp = processRequestGetModuleData(clCanard, &req, (CanParam_t *) param);
1010  // Serialize and publish the message:
1011  uint8_t serialized[rmap_service_module_Rain_Response_1_0_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
1012  size_t serialized_size = sizeof(serialized);
1013  const int8_t res = rmap_service_module_Rain_Response_1_0_serialize_(&module_rain_resp, &serialized[0], &serialized_size);
1014  if (res >= 0) {
1015  // Risposta standard con validità time out RMAP_DATA personalizzato dal timeStamp Sincronizzato
1016  clCanard.sendResponse(CANARD_RMAPDATA_TRANSFER_ID_TIMEOUT_USEC, &transfer->metadata, serialized_size, &serialized[0]);
1017  }
1018  }
1019  }
1020  else if (transfer->metadata.port_id == uavcan_node_GetInfo_1_0_FIXED_PORT_ID_)
1021  {
1022  // The request object is empty so we don't bother deserializing it. Just send the response.
1023  const uavcan_node_GetInfo_Response_1_0 resp = processRequestNodeGetInfo();
1024  uint8_t serialized[uavcan_node_GetInfo_Response_1_0_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
1025  size_t serialized_size = sizeof(serialized);
1026  const int8_t res = uavcan_node_GetInfo_Response_1_0_serialize_(&resp, &serialized[0], &serialized_size);
1027  if (res >= 0) {
1028  // Risposta standard ad un secondo dal timeStamp Sincronizzato
1029  clCanard.sendResponse(MEGA, &transfer->metadata, serialized_size, &serialized[0]);
1030  }
1031  }
1032  else if (transfer->metadata.port_id == uavcan_register_Access_1_0_FIXED_PORT_ID_)
1033  {
1034  uavcan_register_Access_Request_1_0 req = {0};
1035  size_t size = transfer->payload_size;
1036  TRACE_INFO_F(F("<<-- Ricevuto richiesta accesso ai registri\r\n"));
1037  if (uavcan_register_Access_Request_1_0_deserialize_(&req, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
1038  const uavcan_register_Access_Response_1_0 resp = processRequestRegisterAccess(&req);
1039  uint8_t serialized[uavcan_register_Access_Response_1_0_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
1040  size_t serialized_size = sizeof(serialized);
1041  if (uavcan_register_Access_Response_1_0_serialize_(&resp, &serialized[0], &serialized_size) >= 0) {
1042  // Risposta standard ad un secondo dal timeStamp Sincronizzato
1043  clCanard.sendResponse(MEGA, &transfer->metadata, serialized_size, &serialized[0]);
1044  }
1045  }
1046  }
1047  else if (transfer->metadata.port_id == uavcan_register_List_1_0_FIXED_PORT_ID_)
1048  {
1049  uavcan_register_List_Request_1_0 req = {0};
1050  size_t size = transfer->payload_size;
1051  TRACE_INFO_F(F("<<-- Ricevuto richiesta lettura elenco registri\r\n"));
1052  if (uavcan_register_List_Request_1_0_deserialize_(&req, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
1053  const uavcan_register_List_Response_1_0 resp = {.name = localRegister->getNameByIndex(req.index)};
1054  uint8_t serialized[uavcan_register_List_Response_1_0_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
1055  size_t serialized_size = sizeof(serialized);
1056  if (uavcan_register_List_Response_1_0_serialize_(&resp, &serialized[0], &serialized_size) >= 0) {
1057  // Risposta standard ad un secondo dal timeStamp Sincronizzato
1058  clCanard.sendResponse(CANARD_REGISTERLIST_TRANSFER_ID_TIMEOUT_USEC, &transfer->metadata, serialized_size, &serialized[0]);
1059  }
1060  }
1061  }
1062  else if (transfer->metadata.port_id == uavcan_node_ExecuteCommand_1_1_FIXED_PORT_ID_)
1063  {
1064  uavcan_node_ExecuteCommand_Request_1_1 req = {0};
1065  size_t size = transfer->payload_size;
1066  TRACE_INFO_F(F("<<-- Ricevuto comando esterno\r\n"));
1067  if (uavcan_node_ExecuteCommand_Request_1_1_deserialize_(&req, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
1068  const uavcan_node_ExecuteCommand_Response_1_1 resp = processRequestExecuteCommand(clCanard, &req, transfer->metadata.remote_node_id);
1069  uint8_t serialized[uavcan_node_ExecuteCommand_Response_1_1_SERIALIZATION_BUFFER_SIZE_BYTES_] = {0};
1070  size_t serialized_size = sizeof(serialized);
1071  if (uavcan_node_ExecuteCommand_Response_1_1_serialize_(&resp, &serialized[0], &serialized_size) >= 0) {
1072  // Risposta standard ad un secondo dal timeStamp Sincronizzato
1073  clCanard.sendResponse(MEGA, &transfer->metadata, serialized_size, &serialized[0]);
1074  }
1075  }
1076  }
1077  else
1078  {
1079  // Gestione di una richiesta senza controllore locale. Se arrivo quà è un errore di sviluppo
1080  LOCAL_ASSERT(false);
1081  }
1082  }
1083  else if (transfer->metadata.transfer_kind == CanardTransferKindResponse)
1084  {
1085  if (transfer->metadata.port_id == uavcan_file_Read_1_1_FIXED_PORT_ID_) {
1086  // Accetto solo messaggi indirizzati dal node_id che ha fatto la richiesta di upload
1087  // E' una sicurezza per il controllo dell'upload, ed evità errori di interprete
1088  // Inoltre non accetta messaggi extra standard UAVCAN, necessarià prima la CALL al comando
1089  // SEtFirmwareUpload o SetFileUpload, che impostano il node_id, resettato su EOF dalla classe
1090  if (clCanard.master.file.get_server_node() == transfer->metadata.remote_node_id) {
1091  uavcan_file_Read_Response_1_1 resp = {0};
1092  size_t size = transfer->payload_size;
1093  if (uavcan_file_Read_Response_1_1_deserialize_(&resp, static_cast<uint8_t const*>(transfer->payload), &size) >= 0) {
1094  if(clCanard.master.file.is_firmware()) {
1095  TRACE_VERBOSE_F(F("RX FIRMWARE READ BLOCK LEN: "));
1096  } else {
1097  TRACE_VERBOSE_F(F("RX FILE READ BLOCK LEN: "));
1098  }
1099  TRACE_VERBOSE_F(F("%d\r\n"), resp.data.value.count);
1100  // Save Data in Flash File at Block Position (Init = Rewrite file...)
1101  if(putFlashFile(clCanard.master.file.get_name(), clCanard.master.file.is_firmware(), clCanard.master.file.is_first_data_block(),
1102  resp.data.value.elements, resp.data.value.count)) {
1103  // Reset pending command (Comunico request/Response Serie di comandi OK!!!)
1104  // Uso l'Overload con controllo di EOF (-> EOF se msgLen != UAVCAN_BLOCK_DEFAULT [256 Bytes])
1105  // Questo Overload gestisce in automatico l'offset del messaggio, per i successivi blocchi
1106  clCanard.master.file.reset_pending(resp.data.value.count);
1107  } else {
1108  // Error Save... Abort request
1109  TRACE_ERROR_F(F("SAVING BLOCK FILE ERROR, ABORT RX !!!"));
1110  clCanard.master.file.download_end();
1111  }
1112  }
1113  } else {
1114  // Errore Nodo non settato...
1115  TRACE_ERROR_F(F("RX FILE READ BLOCK REJECT: Node_Id not valid or not set\r\n"));
1116  }
1117  }
1118  }
1119  else
1120  {
1121  // Se arrivo quà è un errore di sviluppo, controllare setup sottoscrizioni e Rqst (non gestito slave)
1122  LOCAL_ASSERT(false);
1123  }
1124 }
1125 
1131 CanTask::CanTask(const char *taskName, uint16_t stackSize, uint8_t priority, CanParam_t canParam) : Thread(taskName, stackSize, priority), param(canParam)
1132 {
1133  // Start WDT controller and TaskState Flags
1136 
1137  // Setup register mode
1139 
1140  // Setup Flash Access
1142 
1143  // Local static access to global queue and Semaphore
1147 
1150 
1151  // FullChip Power Mode after Startup
1152  // Resume from LowPower or reset the controller TJA1443ATK
1153  // Need FullPower for bxCan Programming (Otherwise Handler_Error()!)
1155 
1156  TRACE_INFO_F(F("Starting CAN Configuration\r\n"));
1157 
1158  // ******************* CANARD MTU CLASSIC (FOR UAVCAN REQUIRE) *******************
1159  // Open Register in Write se non inizializzati correttamente...
1160  // Populate INIT Default Value
1161  static uavcan_register_Value_1_0 val = {0};
1162  uavcan_register_Value_1_0_select_natural16_(&val);
1163  val.natural16.value.count = 1;
1164  val.natural16.value.elements[0] = CAN_MTU_BASE; // CAN_CLASSIC MTU 8
1165  localRegisterAccessLock->Take();
1167  localRegisterAccessLock->Give();
1168  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == 1));
1169 
1170  // ******************* CANARD SETUP TIMINGS AND SPEED *******************
1171  // CAN BITRATE Dinamico su LoadRegister (CAN_FD 2xREG natural32 0=Speed, 1=0 (Not Used))
1172  uavcan_register_Value_1_0_select_natural32_(&val);
1173  val.natural32.value.count = 2;
1174  val.natural32.value.elements[0] = CAN_BIT_RATE;
1175  val.natural32.value.elements[1] = 0ul; // Ignored for CANARD_MTU_CAN_CLASSIC
1176  localRegisterAccessLock->Take();
1178  localRegisterAccessLock->Give();
1179  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural32_(&val) && (val.natural32.value.count == 2));
1180 
1181  // Dynamic BIT RATE Change CAN Speed to CAN_BIT_RATE (register default/defined)
1182  BxCANTimings timings;
1183  bool result = bxCANComputeTimings(HAL_RCC_GetPCLK1Freq(), val.natural32.value.elements[0], &timings);
1184  if (!result) {
1185  TRACE_VERBOSE_F(F("Error redefinition bxCANComputeTimings, try loading default...\r\n"));
1186  val.natural32.value.count = 2;
1187  val.natural32.value.elements[0] = CAN_BIT_RATE;
1188  val.natural32.value.elements[1] = 0ul; // Ignored for CANARD_MTU_CAN_CLASSIC
1189  localRegisterAccessLock->Take();
1191  localRegisterAccessLock->Give();
1192  result = bxCANComputeTimings(HAL_RCC_GetPCLK1Freq(), val.natural32.value.elements[0], &timings);
1193  if (!result) {
1194  TRACE_ERROR_F(F("Error initialization bxCANComputeTimings\r\n"));
1195  LOCAL_ASSERT(false);
1196  return;
1197  }
1198  }
1199 
1200  // HW Setup solo con modulo CAN Attivo
1201  #if (ENABLE_CAN)
1202 
1203  // Configurea bxCAN speed && mode
1204  result = bxCANConfigure(0, timings, false);
1205  if (!result) {
1206  TRACE_ERROR_F(F("Error initialization bxCANConfigure\r\n"));
1207  LOCAL_ASSERT(false);
1208  return;
1209  }
1210  // ******************* CANARD SETUP TIMINGS AND SPEED COMPLETE *******************
1211 
1212  // Check error starting CAN
1213  if (HAL_CAN_Start(&hcan1) != HAL_OK) {
1214  TRACE_ERROR_F(F("CAN startup ERROR!!!\r\n"));
1215  LOCAL_ASSERT(false);
1216  return;
1217  }
1218 
1219  // Enable Interrupt RX Standard CallBack -> CAN1_RX0_IRQHandler
1220  if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) {
1221  TRACE_ERROR_F(F("Error initialization interrupt CAN base\r\n"));
1222  LOCAL_ASSERT(false);
1223  return;
1224  }
1225  // Setup Priority e CB CAN_IRQ_RX Enable
1226  HAL_NVIC_SetPriority(CAN1_RX0_IRQn, CAN_NVIC_INT_PREMPT_PRIORITY, 0);
1227  HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
1228 
1229  // Setup Complete
1230  TRACE_VERBOSE_F(F("CAN Configuration complete...\r\n"));
1231 
1232  #endif
1233 
1234  // Run Task Init
1236  Start();
1237 };
1238 
1239 #if (ENABLE_STACK_USAGE)
1241 void CanTask::TaskMonitorStack()
1242 {
1243  uint16_t stackUsage = (uint16_t)uxTaskGetStackHighWaterMark( NULL );
1244  if((stackUsage) && (stackUsage < param.system_status->tasks[LOCAL_TASK_ID].stack)) {
1245  param.systemStatusLock->Take();
1246  param.system_status->tasks[LOCAL_TASK_ID].stack = stackUsage;
1247  param.systemStatusLock->Give();
1248  }
1249 }
1250 #endif
1251 
1254 void CanTask::TaskWatchDog(uint32_t millis_standby)
1255 {
1256  // Local TaskWatchDog update
1257  param.systemStatusLock->Take();
1258  // Update WDT Signal (Direct or Long function Timered)
1259  if(millis_standby)
1260  {
1261  // Check 1/2 Freq. controller ready to WDT only SET flag
1262  if((millis_standby) < WDT_CONTROLLER_MS / 2) {
1264  } else {
1266  // Add security milimal Freq to check
1268  }
1269  }
1270  else
1272  param.systemStatusLock->Give();
1273 }
1274 
1279 void CanTask::TaskState(uint8_t state_position, uint8_t state_subposition, task_flag state_operation)
1280 {
1281  // Local TaskWatchDog update
1282  param.systemStatusLock->Take();
1283  // Signal Task sleep/disabled mode from request (Auto SET WDT on Resume)
1285  (state_operation==task_flag::normal))
1287  param.system_status->tasks[LOCAL_TASK_ID].state = state_operation;
1288  param.system_status->tasks[LOCAL_TASK_ID].running_pos = state_position;
1289  param.system_status->tasks[LOCAL_TASK_ID].running_sub = state_subposition;
1290  param.systemStatusLock->Give();
1291 }
1292 
1295 
1296  // Data Local Task (Class + Registro)
1297  // Avvia l'istanza alla classe State_Canard ed inizializza Ram, Buffer e variabili base
1298  canardClass clCanard;
1299  static uavcan_register_Value_1_0 val = {0};
1300 
1301  // System message data queue structured
1302  system_message_t system_message;
1303 
1304  // LoopTimer Publish
1305  CanardMicrosecond last_pub_rmap_data;
1306  CanardMicrosecond last_pub_heartbeat;
1307  CanardMicrosecond last_pub_port_list;
1308 
1309  // Set when Firmware Upgrade is required
1310  bool start_firmware_upgrade = false;
1311 
1312  // OnlineMaster (Set/Reset Application Code Function Here Enter/Exit Function OnLine)
1313  bool masterOnline = false;
1314 
1315  // Start Running Monitor and First WDT normal state
1316  #if (ENABLE_STACK_USAGE)
1317  TaskMonitorStack();
1318  #endif
1320 
1321  // Main Loop TASK
1322  while (true) {
1323 
1324  // ********* SYSTEM QUEUE MESSAGE ***********
1325  // enqueud system message from caller task
1326  if (!param.systemMessageQueue->IsEmpty()) {
1327  // Read queue in test mode
1328  if (param.systemMessageQueue->Peek(&system_message, 0))
1329  {
1330  // Its request addressed into ALL TASK... -> no pull (only SUPERVISOR or exernal gestor)
1331  if(system_message.task_dest == ALL_TASK_ID)
1332  {
1333  // Pull && elaborate command,
1334  if(system_message.command.do_sleep)
1335  {
1336  // Enter module sleep procedure (OFF Module)
1338 
1339  // Enter sleep module OK and update WDT
1342  Delay(Ticks::MsToTicks(CAN_TASK_SLEEP_DELAY_MS));
1344 
1345  // Restore module from Sleep
1347  }
1348  }
1349  }
1350  }
1351 
1352  // ********************************************************************************
1353  // SETUP CONFIG CYPAL, CLASS, REGISTER, DATA
1354  // ********************************************************************************
1355  switch (state) {
1356  // Setup Class CB and NodeId
1357  case CAN_STATE_INIT:
1358 
1359  // Avvio inizializzazione (Standard UAVCAN MSG). Reset su INIT END OK
1360  // Segnale al Master necessità di impostazioni ev. parametri, Data/Ora ecc..
1361  clCanard.flag.set_local_node_mode(uavcan_node_Mode_1_0_INITIALIZATION);
1362 
1363  // Attiva il callBack su RX Messaggio Canard sulla funzione interna processReceivedTransfer
1364  clCanard.setReceiveMessage_CB(processReceivedTransfer, (void *) &param);
1365 
1366  // ******************** Lettura Registri standard UAVCAN ********************
1367  // Restore the node-ID from the corresponding standard regioster. Default to anonymous.
1368  #ifdef USE_NODE_SLAVE_ID_FIXED
1369  // Canard Slave NODE ID Fixed dal defined value in module_config
1370  clCanard.set_canard_node_id((CanardNodeID)NODE_SLAVE_ID);
1371  #else
1372  uavcan_register_Value_1_0_select_natural16_(&val);
1373  val.natural16.value.count = 1;
1374  val.natural16.value.elements[0] = UINT16_MAX; // This means undefined (anonymous), per Specification/libcanard.
1375  localRegisterAccessLock->Take();
1376  localRegister->read(REGISTER_UAVCAN_NODE_ID, &val); // The names of the standard registers are regulated by the Specification.
1377  localRegisterAccessLock->Give();
1378  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == 1));
1379  if (val.natural16.value.elements[0] <= CANARD_NODE_ID_MAX) {
1380  clCanard.set_canard_node_id((CanardNodeID)val.natural16.value.elements[0]);
1381  }
1382  #endif
1383 
1384  // The description register is optional but recommended because it helps constructing/maintaining large networks.
1385  // It simply keeps a human-readable description of the node that should be empty by default.
1386  uavcan_register_Value_1_0_select_string_(&val);
1387  val._string.value.count = 0;
1388  localRegisterAccessLock->Take();
1389  localRegister->read(REGISTER_UAVCAN_NODE_DESCR, &val); // We don't need the value, we just need to ensure it exists.
1390  localRegisterAccessLock->Give();
1391 
1392  // ******************** Lettura Registri personalizzati RMAP ********************
1393  // Restore the master-ID from the corresponding standard register -> Default to anonymous.
1394  #ifdef USE_NODE_MASTER_ID_FIXED
1395  // Canard Slave NODE ID Fixed dal defined value in module_config
1396  clCanard.set_canard_master_id((CanardNodeID)NODE_MASTER_ID);
1397  #else
1398  uavcan_register_Value_1_0_select_natural16_(&val);
1399  val.natural16.value.count = 1;
1400  val.natural16.value.elements[0] = NODE_MASTER_ID; // Setting default Master ID Value
1401  localRegisterAccessLock->Take();
1402  localRegister->read(REGISTER_RMAP_MASTER_ID, &val); // The names of the standard registers are regulated by the Specification.
1403  localRegisterAccessLock->Give();
1404  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == 1));
1405  if (val.natural16.value.elements[0] <= CANARD_NODE_ID_MAX) {
1406  clCanard.set_canard_master_id((CanardNodeID)val.natural16.value.elements[0]);
1407  }
1408  #endif
1409 
1410  // Carico i/il port-ID/subject-ID del modulo locale dai registri relativi associati nel namespace UAVCAN
1411  #ifdef USE_PORT_PUBLISH_RMAP_FIXED
1412  clCanard.port_id.publisher_module_rain = (CanardPortID)SUBJECTID_PUBLISH_RMAP;
1413  #else
1414  clCanard.port_id.publisher_module_rain =
1415  getModeAccessID(canardClass::Introspection_Port::PublisherSubjectID,
1416  REGISTER_DATA_PUBLISH, rmap_module_Rain_1_0_FULL_NAME_AND_VERSION_);
1417  #endif
1418  #ifdef USE_PORT_SERVICE_RMAP_FIXED
1419  clCanard.port_id.service_module_rain = (CanardPortID)PORT_SERVICE_RMAP;
1420  #else
1421  clCanard.port_id.service_module_rain =
1422  getModeAccessID(canardClass::Introspection_Port::ServicePortID,
1423  REGISTER_DATA_SERVICE, rmap_service_module_Rain_1_0_FULL_NAME_AND_VERSION_);
1424  #endif
1425 
1426  // Set configured Module Ready (IF service_id is valid)
1427  // If Not Master receive flag module not ready and start configuration aumatically
1428  if(clCanard.port_id.service_module_rain != UINT16_MAX)
1429  clCanard.flag.set_local_module_ready(true);
1430 
1431  // ************************* LETTURA REGISTRI METADATI RMAP ****************************
1432  // POSITION ARRAY METADATA CONFIG: (TOT ELEMENTS = SENSOR_METADATA_COUNT)
1433  // SENSOR_METADATA_TBR (0)
1434  // SENSOR_METADATA_TPR (1)
1435  // *********************************** L1 *********************************************
1436  uavcan_register_Value_1_0_select_natural16_(&val);
1437  val.natural16.value.count = SENSOR_METADATA_COUNT;
1438  for(uint8_t id=0; id<SENSOR_METADATA_COUNT; id++) {
1439  val.natural16.value.elements[id] = SENSOR_METADATA_LEVEL_1;
1440  }
1441  localRegisterAccessLock->Take();
1443  localRegisterAccessLock->Give();
1444  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == SENSOR_METADATA_COUNT));
1445  clCanard.module_rain.TBR.metadata.level.L1.value = val.natural16.value.elements[SENSOR_METADATA_TBR];
1446  clCanard.module_rain.TPR.metadata.level.L1.value = val.natural16.value.elements[SENSOR_METADATA_TPR];
1447  // *********************************** L2 *********************************************
1448  uavcan_register_Value_1_0_select_natural16_(&val);
1449  val.natural16.value.count = SENSOR_METADATA_COUNT;
1450  for(uint8_t id=0; id<SENSOR_METADATA_COUNT; id++) {
1451  val.natural16.value.elements[id] = SENSOR_METADATA_LEVEL_2;
1452  }
1453  localRegisterAccessLock->Take();
1455  localRegisterAccessLock->Give();
1456  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == SENSOR_METADATA_COUNT));
1457  clCanard.module_rain.TBR.metadata.level.L2.value = val.natural16.value.elements[SENSOR_METADATA_TBR];
1458  clCanard.module_rain.TPR.metadata.level.L2.value = val.natural16.value.elements[SENSOR_METADATA_TPR];
1459  // ******************************* LevelType1 *****************************************
1460  uavcan_register_Value_1_0_select_natural16_(&val);
1461  val.natural16.value.count = SENSOR_METADATA_COUNT;
1462  for(uint8_t id=0; id<SENSOR_METADATA_COUNT; id++) {
1463  val.natural16.value.elements[id] = SENSOR_METADATA_LEVELTYPE_1;
1464  }
1465  localRegisterAccessLock->Take();
1467  localRegisterAccessLock->Give();
1468  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == SENSOR_METADATA_COUNT));
1469  clCanard.module_rain.TBR.metadata.level.LevelType1.value = val.natural16.value.elements[SENSOR_METADATA_TBR];
1470  clCanard.module_rain.TPR.metadata.level.LevelType1.value = val.natural16.value.elements[SENSOR_METADATA_TPR];
1471  // ******************************* LevelType2 *****************************************
1472  uavcan_register_Value_1_0_select_natural16_(&val);
1473  val.natural16.value.count = SENSOR_METADATA_COUNT;
1474  for(uint8_t id=0; id<SENSOR_METADATA_COUNT; id++) {
1475  val.natural16.value.elements[id] = SENSOR_METADATA_LEVELTYPE_2;
1476  }
1477  localRegisterAccessLock->Take();
1479  localRegisterAccessLock->Give();
1480  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == SENSOR_METADATA_COUNT));
1481  clCanard.module_rain.TBR.metadata.level.LevelType2.value = val.natural16.value.elements[SENSOR_METADATA_TBR];
1482  clCanard.module_rain.TPR.metadata.level.LevelType2.value = val.natural16.value.elements[SENSOR_METADATA_TPR];
1483  // *********************************** P1 *********************************************
1484  uavcan_register_Value_1_0_select_natural16_(&val);
1485  val.natural16.value.count = SENSOR_METADATA_COUNT;
1486  for(uint8_t id=0; id<SENSOR_METADATA_COUNT; id++) {
1487  val.natural16.value.elements[id] = SENSOR_METADATA_LEVEL_P1;
1488  }
1489  localRegisterAccessLock->Take();
1491  localRegisterAccessLock->Give();
1492  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural16_(&val) && (val.natural16.value.count == SENSOR_METADATA_COUNT));
1493  clCanard.module_rain.TBR.metadata.timerange.P1.value = val.natural16.value.elements[SENSOR_METADATA_TBR];
1494  clCanard.module_rain.TPR.metadata.timerange.P1.value = val.natural16.value.elements[SENSOR_METADATA_TPR];
1495  // *********************************** P2 *********************************************
1496  // P2 Non memorizzato sul modulo, parametro dipendente dall'acquisizione locale
1497  clCanard.module_rain.TBR.metadata.timerange.P2 = 0;
1498  clCanard.module_rain.TPR.metadata.timerange.P2 = 0;
1499  // *********************************** P2 *********************************************
1500  uavcan_register_Value_1_0_select_natural8_(&val);
1501  val.natural8.value.count = SENSOR_METADATA_COUNT;
1502  // Default are single different value for type sensor
1503  val.natural8.value.elements[SENSOR_METADATA_TBR] = SENSOR_METADATA_LEVEL_P_IND_TBR;
1504  val.natural8.value.elements[SENSOR_METADATA_TPR] = SENSOR_METADATA_LEVEL_P_IND_TPR;
1505  localRegisterAccessLock->Take();
1507  localRegisterAccessLock->Give();
1508  LOCAL_ASSERT(uavcan_register_Value_1_0_is_natural8_(&val) && (val.natural8.value.count == SENSOR_METADATA_COUNT));
1509  clCanard.module_rain.TBR.metadata.timerange.Pindicator.value = val.natural8.value.elements[SENSOR_METADATA_TBR];
1510  clCanard.module_rain.TPR.metadata.timerange.Pindicator.value = val.natural8.value.elements[SENSOR_METADATA_TPR];
1511 
1512  // Passa alle sottoscrizioni
1514  break;
1515 
1516  // ********************************************************************************
1517  // AVVIA SOTTOSCRIZIONI ai messaggi per servizi RPC ecc...
1518  // ********************************************************************************
1519  case CAN_STATE_SETUP:
1520 
1521  // Plug and Play Versione 1_0 CAN_CLASSIC senza nodo ID valido
1522  if (clCanard.is_canard_node_anonymous()) {
1523  // PnP over Classic CAN, use message v1.0
1524  if (!clCanard.rxSubscribe(CanardTransferKindMessage,
1525  uavcan_pnp_NodeIDAllocationData_1_0_FIXED_PORT_ID_,
1526  uavcan_pnp_NodeIDAllocationData_1_0_EXTENT_BYTES_,
1527  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1528  LOCAL_ASSERT(false);
1529  }
1530  }
1531 
1532  // Service Client: -> Verifica della presenza Heartbeat del MASTER [Networks OffLine]
1533  if (!clCanard.rxSubscribe(CanardTransferKindMessage,
1534  uavcan_node_Heartbeat_1_0_FIXED_PORT_ID_,
1535  uavcan_node_Heartbeat_1_0_EXTENT_BYTES_,
1536  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1537  LOCAL_ASSERT(false);
1538  }
1539 
1540  // Service Client: -> Sincronizzazione timestamp Microsecond del MASTER [su base time local]
1541  if (!clCanard.rxSubscribe(CanardTransferKindMessage,
1542  uavcan_time_Synchronization_1_0_FIXED_PORT_ID_,
1543  uavcan_time_Synchronization_1_0_EXTENT_BYTES_,
1544  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1545  LOCAL_ASSERT(false);
1546  }
1547 
1548  // Service servers: -> Risposta per GetNodeInfo richiesta esterna master (Yakut, Altri)
1549  if (!clCanard.rxSubscribe(CanardTransferKindRequest,
1550  uavcan_node_GetInfo_1_0_FIXED_PORT_ID_,
1551  uavcan_node_GetInfo_Request_1_0_EXTENT_BYTES_,
1552  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1553  LOCAL_ASSERT(false);
1554  }
1555 
1556  // Service servers: -> Risposta per ExecuteCommand richiesta esterna master (Yakut, Altri)
1557  if (!clCanard.rxSubscribe(CanardTransferKindRequest,
1558  uavcan_node_ExecuteCommand_1_1_FIXED_PORT_ID_,
1559  uavcan_node_ExecuteCommand_Request_1_1_EXTENT_BYTES_,
1560  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1561  LOCAL_ASSERT(false);
1562  }
1563 
1564  // Service servers: -> Risposta per Accesso ai registri richiesta esterna master (Yakut, Altri)
1565  if (!clCanard.rxSubscribe(CanardTransferKindRequest,
1566  uavcan_register_Access_1_0_FIXED_PORT_ID_,
1567  uavcan_register_Access_Request_1_0_EXTENT_BYTES_,
1568  CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC)) {
1569  LOCAL_ASSERT(false);
1570  }
1571 
1572  // Service servers: -> Risposta per Lista dei registri richiesta esterna master (Yakut, Altri)
1573  // Time OUT Canard raddoppiato per elenco registri (Con molte Call vado in TimOut)
1574  // Con raddoppio del tempo Default problema risolto
1575  if (!clCanard.rxSubscribe(CanardTransferKindRequest,
1576  uavcan_register_List_1_0_FIXED_PORT_ID_,
1577  uavcan_register_List_Request_1_0_EXTENT_BYTES_,
1579  LOCAL_ASSERT(false);
1580  }
1581 
1582  // Service servers: -> Risposta per dati e metadati sensore modulo corrente da master (Yakut, Altri)
1583  if (!clCanard.rxSubscribe(CanardTransferKindRequest,
1584  clCanard.port_id.service_module_rain,
1585  rmap_service_module_Rain_Request_1_0_EXTENT_BYTES_,
1587  LOCAL_ASSERT(false);
1588  }
1589 
1590  // Service client: -> Risposta per Read (Receive) File local richiesta esterna (Yakut, Altri)
1591  if (!clCanard.rxSubscribe(CanardTransferKindResponse,
1592  uavcan_file_Read_1_1_FIXED_PORT_ID_,
1593  uavcan_file_Read_Response_1_1_EXTENT_BYTES_,
1595  LOCAL_ASSERT(false);
1596  }
1597 
1598  // Avvio il modulo UAVCAN in modalità operazionale normale
1599  // Eventuale SET Flag dopo acquisizione di configurazioni e/o parametri da Remoto
1600  clCanard.flag.set_local_node_mode(uavcan_node_Mode_1_0_OPERATIONAL);
1601 
1602  // Set PNP pseudo Random Generator on enabled PinMapped Analog Input
1603  randomSeed(analogRead(PA_4));
1604 
1605  // Set START Timetable LOOP RX/TX. Set Canard microsecond start, per le sincronizzazioni
1606  clCanard.getMicros(clCanard.start_syncronization);
1607  last_pub_rmap_data = clCanard.getMicros(clCanard.syncronized_time);
1608  last_pub_heartbeat = clCanard.getMicros(clCanard.syncronized_time);
1609  last_pub_port_list = last_pub_heartbeat + MEGA * (0.1);
1610 
1611  // Passo alla gestione Main
1613  break;
1614 
1615  // ********************************************************************************
1616  // AVVIA LOOP CANARD PRINCIPALE gestione TX/RX Code -> Messaggi
1617  // ********************************************************************************
1618  case CAN_STATE_CHECK:
1619 
1620  // Set Canard microsecond corrente monotonic, per le attività temporanee di ciclo
1621  clCanard.getMicros(clCanard.start_syncronization);
1622 
1623  // TEST VERIFICA sincronizzazione time_stamp locale con remoto... (LED/OUT sincronizzati)
1624  // Test con reboot e successiva risincronizzazione automatica (FAKE RTC!!!!)
1625  #if defined(LED_ON_SYNCRO_TIME) && defined(LED2_PIN)
1626  // Utilizzo di RTC o locale o generato dal tickMicros locale a partire dall' ultimo SetTimeStamp
1627  // E' utilizzabile come RTC_FAKE e/o come Setup Perfetto per regolazione RTC al cambio del secondo
1628  // RTC Infatti non permette la regolazione dei microsecondi, e questa tecnica lo consente
1629  // Verifico LED al secondo... su timeSTamp sincronizzato remoto
1630  if((clCanard.master.timestamp.get_timestamp_syncronized() / MEGA) % 2) {
1631  digitalWrite(LED2_PIN, HIGH);
1632  } else {
1633  digitalWrite(LED2_PIN, LOW);
1634  }
1635  #endif
1636 
1637  // ************************************************************************
1638  // *********** CHECK OFFLINE/ONLINE ***********
1639  // ************************************************************************
1640 
1641  // Check eventuale Nodo Master OFFLINE (Ultimo comando sempre perchè posso)
1642  // Effettuare eventuali operazioni di SET,RESET Cmd in sicurezza
1643  // Entro in OffLine ed eseguo eventuali operazioni di entrata
1644  if (clCanard.master.heartbeat.is_online(false)) {
1645  // Solo quando passo da OffLine ad OnLine controllo con VarLocale
1646  if (masterOnline != true) {
1647  TRACE_INFO_F(F("Master controller ONLINE !!! -> OnLineFunction()\r\n"));
1648  // .... Codice OnLineFunction()
1649  }
1650  masterOnline = true;
1651  // **************************************************************************
1652  // STATO MODULO (Decisionale in funzione di stato remoto)
1653  // Gestione continuativa del modulo di acquisizione master.clCanard (flag remoto)
1654  // **************************************************************************
1655  // Eventuale codice di gestione MasterOnline OK...
1656  } else {
1657  // Solo quando passo da OffLine ad OnLine
1658  if (masterOnline) {
1659  TRACE_INFO_F(F("Master controller OFFLINE !!! ALERT -> OffLineFunction()\r\n"));
1660  // When enter off_line Master. Full power are automatic resetted for slave module
1662  }
1663  masterOnline = false;
1664  // Gestisco situazione con Master OFFLine...
1665  }
1666 
1667  // **************************************************************************
1668  // *********************** FILE UPLOAD PROCESS HANDLER **********************
1669  // **************************************************************************
1670 
1671  // Verifica file download in corso (entro se in download)
1672  // Attivato da ricezione comando appropriato rxFile o rxFirmware
1673  if(clCanard.master.file.download_request()) {
1674  if(clCanard.master.file.is_firmware())
1675  // Set Flag locale per comunicazione HeartBeat... uploading OK in corso
1676  // Utilizzo locale per blocco procedure, sleep ecc. x Uploading
1677  clCanard.flag.set_local_fw_uploading(true);
1678  // Controllo eventuale timeOut del comando o RxBlocco e gestisco le Retry
1679  // Verifica TimeOUT Occurs per File download
1680  if(clCanard.master.file.event_timeout()) {
1681  TRACE_ERROR_F(F("Time OUT File... event occurs\r\n"));
1682  // Gestione Retry previste dal comando per poi abbandonare
1683  uint8_t retry; // In overload x LOGGING
1684  if(clCanard.master.file.next_retry(&retry)) {
1685  TRACE_VERBOSE_F(F("Next Retry File read: %u\r\n"), retry);
1686  } else {
1687  TRACE_VERBOSE_F(F("MAX Retry File occurs, download file ABORT !!!\r\n"));
1688  clCanard.master.file.download_end();
1689  }
1690  }
1691  // Se messaggio in pending non faccio niente è attendo la fine del comando in run
1692  // In caso di errore subentrerà il TimeOut e verrà essere gestita la retry
1693  if(!clCanard.master.file.is_pending()) {
1694  // Fine pending, con messaggio OK. Verifico se EOF o necessario altro blocco
1695  if(clCanard.master.file.is_download_complete()) {
1696  if(clCanard.master.file.is_firmware()) {
1697  TRACE_INFO_F(F("RX FIRMWARE COMPLETED !!!\r\n"));
1698  } else {
1699  TRACE_INFO_F(F("RX FILE COMPLETED !!!\r\n"));
1700  }
1701  TRACE_VERBOSE_F(F("File name: %s\r\n"), clCanard.master.file.get_name());
1702  // GetInfo && Verify Start Updating...
1703  if(clCanard.master.file.is_firmware()) {
1704  // Module type also checked before startin firmware_upgrade
1705  uint8_t module_type;
1706  uint8_t version;
1707  uint8_t revision;
1708  uint64_t fwFileLen = 0;
1709  getFlashFwInfoFile(&module_type, &version, &revision, &fwFileLen);
1710  TRACE_VERBOSE_F(F("Firmware V%d.%d, Size: %lu bytes is ready for flash updating\r\n"),version, revision, (uint32_t) fwFileLen);
1711  } // Nessun altro evento necessario, chiudo File e stati
1712  // procedo all'aggiornamento Firmware dopo le verifiche di conformità
1713  // Ovviamente se si tratta di un file firmware
1714  clCanard.master.file.download_end();
1715  // Comunico a HeartBeat (Yakut o Altri) l'avvio dell'aggiornamento (se il file è un firmware...)
1716  // Per Yakut Pubblicare un HeartBeat prima dell'Avvio quindi con il flag
1717  // clCanard.local_node.file.updating_run = true >> HeartBeat Comunica Upgrade...
1718  if(clCanard.master.file.is_firmware()) {
1719  clCanard.flag.set_local_node_mode(uavcan_node_Mode_1_0_SOFTWARE_UPDATE);
1720  start_firmware_upgrade = true;
1721  // Preparo la struttua per informare il Boot Loader
1728  }
1729  // Il Firmware Upload dovrà partire necessariamente almeno dopo l'invio completo
1730  // di HeartBeat (svuotamento coda), quindi via subito in heart_beat send
1731  // Counque non rispondo più ai comandi di update con file.updating_run = true
1732  } else {
1733  // Avvio prima request o nuovo blocco (Set Flag e TimeOut)
1734  // Prima request (clCanard.local_node.file.offset == 0)
1735  // Firmmware Posizione blocco gestito automaticamente in sequenza Request/Read
1736  // Gestione retry (incremento su TimeOut/Error) Automatico in Init/Request-Response
1737  // Esco se raggiunga un massimo numero di retry x Frame... sopra
1738  // Get Data Block per popolare il File
1739  // Se il Buffer è pieno = 256 Caratteri è necessario continuare
1740  // Altrimenti se inferiore o (0 Compreso) il trasferimento file termina.
1741  // Se = 0 il blocco finale non viene considerato ma serve per il protocollo
1742  // Se l'ultimo buffer dovesse essere pieno discrimina l'eventualità di MaxBuf==Eof
1744  }
1745  }
1746  }
1747  // **************************************************************************
1748 
1749  // -> Scheduler temporizzato dei messaggi standard da inviare alla rete UAVCAN
1750 
1751  // *************************** RMAP DATA PUBLISHER **************************
1752  // Pubblica i dati del nodo corrente se configurata e abilitata la funzione
1753  // Ovviamente il nodo non può essere anonimo per la pubblicazione...
1754  if ((!clCanard.is_canard_node_anonymous()) &&
1755  (clCanard.publisher_enabled.module_rain) &&
1756  (clCanard.port_id.publisher_module_rain <= CANARD_SUBJECT_ID_MAX)) {
1757  if (clCanard.getMicros(clCanard.syncronized_time) >= last_pub_rmap_data)
1758  {
1759  // Update publisher
1760  last_pub_rmap_data += MEGA * TIME_PUBLISH_MODULE_DATA;
1761  // Funzione locale privata
1762  publish_rmap_data(clCanard, &param);
1763  }
1764  }
1765 
1766  // ************************* HEARTBEAT DATA PUBLISHER ***********************
1767  if((start_firmware_upgrade)||
1768  (clCanard.getMicros(clCanard.syncronized_time) >= last_pub_heartbeat)) {
1769  if(clCanard.is_canard_node_anonymous()) {
1770  TRACE_INFO_F(F("Publish SLAVE PNP Request Message -->> [ Random over %u sec ]\r\n"), TIME_PUBLISH_PNP_REQUEST);
1772  last_pub_heartbeat += random(MEGA * TIME_PUBLISH_PNP_REQUEST);
1773  } else {
1774  TRACE_INFO_F(F("Publish SLAVE Heartbeat -->> [ %u sec]\r\n"), TIME_PUBLISH_HEARTBEAT);
1775  clCanard.slave_heartbeat_send_message();
1776  // Update publisher when real syncro onLine Master (Synch with master publish HeartBeat)
1777  if(clCanard.master.heartbeat.is_online(true))
1778  last_pub_heartbeat = clCanard.master.heartbeat.last_online() + MEGA * TIME_PUBLISH_HEARTBEAT;
1779  else
1780  last_pub_heartbeat = clCanard.getMicros(clCanard.syncronized_time) + MEGA * TIME_PUBLISH_HEARTBEAT;
1781  }
1782  }
1783 
1784  // ********************** SERVICE PORT LIST PUBLISHER ***********************
1785  if (clCanard.flag.get_local_power_mode() == Power_Mode::pwr_on) {
1786  if (clCanard.getMicros(clCanard.syncronized_time) >= last_pub_port_list) {
1787  // Publish list service only if full power mode are selected
1788  TRACE_INFO_F(F("Publish Local PORT LIST -->> [ %u sec]\r\n"), TIME_PUBLISH_PORT_LIST);
1789  last_pub_port_list = clCanard.getMicros(clCanard.syncronized_time) + MEGA * TIME_PUBLISH_PORT_LIST;
1790  // Update publisher
1791  clCanard.slave_servicelist_send_message();
1792  }
1793  } else {
1794  // Mantengo il publish Port avanti nel tempo e Avvio solo a MAX Power e tempo
1795  // di pubblicazione interamente trascorso. Evita Publish inutile in Request PowerUP
1796  // da Master, per semplici operazioni di lettura e/o configurazione ( In Power::Sleep )
1797  last_pub_port_list = clCanard.getMicros(clCanard.syncronized_time);
1798  }
1799 
1800  // ***************************************************************************
1801  // Gestione Coda messaggi in trasmissione (ciclo di svuotamento messaggi)
1802  // ***************************************************************************
1803  // Transmit pending frames, avvia la trasmissione gestita da canard a priorità.
1804  // Il metodo può essere chiamato direttamente in preparazione messaggio x coda
1805  if (clCanard.transmitQueueDataPresent()) {
1806  // Access driver con semaforo
1807  if(param.canLock->Take(Ticks::MsToTicks(CAN_SEMAPHORE_MAX_WAITING_TIME_MS))) {
1808  clCanard.transmitQueue();
1809  param.canLock->Give();
1810  }
1811  }
1812 
1813  // ***************************************************************************
1814  // Gestione Coda messaggi in ricezione (ciclo di caricamento messaggi)
1815  // ***************************************************************************
1816  // Gestione con Intererupt RX Only esterna (verifica dati in coda gestionale)
1817  if (clCanard.receiveQueueDataPresent()) {
1818  // Log Packet
1819  #ifdef LOG_RX_PACKET
1820  char logMsg[50];
1821  clCanard.receiveQueue(logMsg);
1822  TRACE_DEBUG_F(F("RX [ %s ]\r\n"), logMsg);
1823  #else
1824  clCanard.receiveQueue();
1825  #endif
1826  }
1827 
1828  // Request Reboot (Firmware upgrade... Or Reset)
1829  if (clCanard.flag.is_requested_system_restart() || (start_firmware_upgrade)) {
1830  TRACE_INFO_F(F("Send signal to system Reset...\r\n"));
1831  delay(250); // Waiting security queue empty send HB (Updating start...)
1832  NVIC_SystemReset();
1833  }
1834  break;
1835  }
1836 
1837  #if (ENABLE_STACK_USAGE)
1838  TaskMonitorStack();
1839  #endif
1840 
1841  // Local TaskWatchDog update;
1843 
1844  // Run switch TASK CAN one STEP every...
1845  // If File Uploading MIN TimeOut For Task for Increse Speed Transfer RATE
1846  if(clCanard.master.file.download_request()) {
1847  DelayUntil(Ticks::MsToTicks(CAN_TASK_WAIT_MAXSPEED_DELAY_MS));
1848  }
1849  else
1850  {
1851  DelayUntil(Ticks::MsToTicks(CAN_TASK_WAIT_DELAY_MS));
1852  }
1853 
1854  }
1855 }
#define AT25SF161_BLOCK_SIZE
Definition: AT25SF161.h:46
#define LOCAL_TASK_ID
Definition: can_task.cpp:31
Uavcan over CanBus cpp_Freertos header file.
#define CAN_TASK_WAIT_MAXSPEED_DELAY_MS
Definition: can_task.h:88
#define CAN_FLAG_IS_MAINTENANCE_MODE
Definition: can_task.h:96
CAN_ModePower
Mode Power HW CanBus Controller state.
Definition: can_task.h:104
@ CAN_NORMAL
CAN is in normal state (TX and RX Ready)
Definition: can_task.h:106
@ CAN_SLEEP
Power CAN is OFF.
Definition: can_task.h:108
@ CAN_INIT
CAN is in init or configuration mode.
Definition: can_task.h:105
@ CAN_LISTEN_ONLY
CAN in only listen mode (turn off TX board)
Definition: can_task.h:107
#define CAN_SEMAPHORE_MAX_WAITING_TIME_MS
Definition: can_task.h:92
#define CAN_TASK_WAIT_DELAY_MS
Definition: can_task.h:87
#define FLASH_SEMAPHORE_MAX_WAITING_TIME_MS
Definition: can_task.h:93
#define CAN_TASK_SLEEP_DELAY_MS
Definition: can_task.h:89
#define SENSOR_METADATA_LEVEL_P_IND_TBR
#define CANARD_READFILE_TRANSFER_ID_TIMEOUT_USEC
#define SENSOR_METADATA_LEVELTYPE_2
#define TIME_PUBLISH_PNP_REQUEST
#define NODE_SLAVE_ID
#define SENSOR_METADATA_TPR
#define GENERIC_STATE_UNDEFINED
#define CAN_BIT_RATE
#define TIME_PUBLISH_HEARTBEAT
#define SUBJECTID_PUBLISH_RMAP
#define SENSOR_METADATA_LEVELTYPE_1
#define NODE_GETFILE_TIMEOUT_US
#define MEGA
#define MASTER_OFFLINE_TIMEOUT_US
#define TIME_PUBLISH_MODULE_DATA
#define SENSOR_METADATA_COUNT
#define SENSOR_METADATA_TBR
#define NODE_MASTER_ID
#define HASH_SERNUMB_MASK
#define SENSOR_METADATA_LEVEL_P1
#define CANARD_RMAPDATA_TRANSFER_ID_TIMEOUT_USEC
#define SENSOR_METADATA_LEVEL_P_IND_TPR
#define SENSOR_METADATA_LEVEL_1
#define LOCAL_ASSERT
#define HASH_EXCLUDING_BIT
#define TIME_PUBLISH_PORT_LIST
#define SENSOR_METADATA_LEVEL_2
#define CANARD_REGISTERLIST_TRANSFER_ID_TIMEOUT_USEC
#define CAN_MTU_BASE
#define PORT_SERVICE_RMAP
static Flash * localFlash
Definition: can_task.h:187
void TaskWatchDog(uint32_t millis_standby)
local watchDog and Sleep flag Task (optional)
Definition: can_task.cpp:1254
static EERegister * localRegister
Definition: can_task.h:184
void TaskState(uint8_t state_position, uint8_t state_subposition, task_flag state_operation)
local suspend flag and positor running state Task (optional)
Definition: can_task.cpp:1279
static void prepareSensorsDataValue(uint8_t const sensore, const report_t *report, rmap_module_Rain_1_0 *rmap_data)
Prepara il blocco messaggio dati per il modulo corrente istantaneo NB: Aggiorno solo i dati fisici in...
Definition: can_task.cpp:357
static cpp_freertos::Queue * localSystemMessageQueue
Definition: can_task.h:178
static bool putFlashFile(const char *const file_name, const bool is_firmware, const bool rewrite, void *buf, size_t count)
Scrive dati in append su Flash per scrittura sequenziale file data remoto.
Definition: can_task.cpp:187
static uavcan_node_GetInfo_Response_1_0 processRequestNodeGetInfo()
Risposta a uavcan.node.GetInfo which Info Node (nome, versione, uniqueID di verifica ecc....
Definition: can_task.cpp:820
static void processMessagePlugAndPlayNodeIDAllocation(canardClass &clsCanard, const uavcan_pnp_NodeIDAllocationData_1_0 *const msg)
Plug and Play Slave, Versione 1.0 compatibile con CAN_CLASSIC MTU 8 Messaggi anonimi CAN non sono con...
Definition: can_task.cpp:471
static bootloader_t * boot_state
Definition: can_task.h:176
static void publish_rmap_data(canardClass &clsCanard, CanParam_t *param)
Pubblica i dati RMAP con il metodo publisher se abilitato e configurato.
Definition: can_task.cpp:405
virtual void Run()
RUN Task.
Definition: can_task.cpp:1294
CanTask(const char *taskName, uint16_t stackSize, uint8_t priority, CanParam_t canParam)
Construct the Can Task::CanTask object Main TASK && INIT TASK — UAVCAN.
Definition: can_task.cpp:1131
static CanardPortID getModeAccessID(uint8_t modeAccessID, const char *const port_name, const char *const type_name)
Legge il subjectID per il modulo corrente per la risposta al servizio di gestione dati.
Definition: can_task.cpp:118
static EEprom * localEeprom
Definition: can_task.h:177
@ CAN_STATE_CHECK
Definition: can_task.h:139
@ CAN_STATE_INIT
Definition: can_task.h:137
@ CAN_STATE_SETUP
Definition: can_task.h:138
@ CAN_STATE_CREATE
Definition: can_task.h:136
static uavcan_node_ExecuteCommand_Response_1_1 processRequestExecuteCommand(canardClass &clsCanard, const uavcan_node_ExecuteCommand_Request_1_1 *req, uint8_t remote_node)
Chiamate gestioni RPC remote da master (yakut o altro servizio di controllo)
Definition: can_task.cpp:506
static void HW_CAN_Power(CAN_ModePower ModeCan)
Enable Power CAN_Circuit TJA1443.
Definition: can_task.cpp:43
static cpp_freertos::BinarySemaphore * localQspiLock
Definition: can_task.h:185
static cpp_freertos::BinarySemaphore * localRegisterAccessLock
Definition: can_task.h:186
static bool getFlashFwInfoFile(uint8_t *module_type, uint8_t *version, uint8_t *revision, uint64_t *len)
GetInfo for Firmware File on Flash.
Definition: can_task.cpp:312
static uavcan_register_Access_Response_1_0 processRequestRegisterAccess(const uavcan_register_Access_Request_1_0 *req)
Accesso ai registri UAVCAN risposta a richieste.
Definition: can_task.cpp:777
static void processReceivedTransfer(canardClass &clsCanard, const CanardRxTransfer *const transfer, void *param)
Canard CallBACK Receive message to Node (Solo con sottoscrizioni)
Definition: can_task.cpp:855
CanParam_t param
Definition: can_task.h:173
State_t state
Definition: can_task.h:172
static rmap_service_module_Rain_Response_1_0 processRequestGetModuleData(canardClass &clsCanard, rmap_service_module_Rain_Request_1_0 *req, CanParam_t *param)
Chiamate gestioni dati remote da master (yakut o altro servizio di controllo)
Definition: can_task.cpp:667
static void getUniqueID(uint8_t out[uavcan_node_GetInfo_Response_1_0_unique_id_ARRAY_CAPACITY_], uint64_t serNumb)
Ritorna unique-ID 128-bit del nodo locale. E' utilizzato in uavcan.node.GetInfo.Response e durante pl...
Definition: can_task.cpp:87
void read(const char *const register_name, uavcan_register_Value_1_0 *const inout_value)
Legge un registro Cypal/Uavcan wrapper UAVCAN (Imposta Default su Set inout_value su value se non esi...
void write(const char *const register_name, const uavcan_register_Value_1_0 *const value)
Store the given register value into the persistent storage.
bool Write(uint16_t address, uint8_t *buffer, uint16_t length)
Write a number of data byte into EEPROM.
Definition: eeprom.cpp:86
QSPI_StatusTypeDef
Definition: flash.h:64
@ QSPI_OK
Definition: flash.h:66
void set_local_power_mode(Power_Mode powerMode)
Proprietà SET per il valore VendorStatusCode di Heartbeat e per gli utilizzi locali La proprietà è im...
void set_local_fw_uploading(bool fwUploading)
Proprietà SET per il valore VendorStatusCode di Heartbeat e per gli utilizzi locali.
Power_Mode get_local_power_mode(void)
Proprietà GET per il valore VendorStatusCode di Heartbeat e per gli utilizzi locali.
void set_local_node_mode(uint8_t heartLocalMODE)
Imposta la modalità nodo standard UAVCAN, gestita nelle funzioni heartbeat.
bool is_requested_system_restart(void)
Verifica una richiesta di riavvio del sistema standard UAVCAN.
void set_local_module_ready(bool moduleReady)
Proprietà SET per il valore VendorStatusCode di Heartbeat e per gli utilizzi locali.
void request_system_restart(void)
Avvia una richiesta standard UAVCAN per il riavvio del sistema.
CanardNodeID get_server_node(void)
Legge il nodo master file server che richiede il caricamento del file.
bool download_request(void)
Gestione file, verifica richiesta di download da un nodo remoto.
char * get_name(void)
Nome del file in download.
bool event_timeout(void)
Gestione timeout pending file. Controlla il raggiungimento del timeout.
bool is_pending(void)
Verifica se un comando per il relativo modulo è in attesa. Diventerà false o verrà attivato il timeou...
bool is_first_data_block(void)
Verifica se è il primo blocco di un file. Da utilizzare per rewrite file o init E2Prom Space.
void download_end(void)
Gestione file, abbandona o termina richiesta di download da un nodo remoto. Il nodo non risponde più ...
bool is_firmware(void)
Controlla se il file è di tipo firmware o altra tipologia.
void reset_pending(void)
Resetta lo stato dei flag pending per il metodo corrente.
bool next_retry(void)
Gestione automatica totale retry del comando file all'interno della classe MAX retry è gestito nel fi...
bool is_download_complete(void)
Gestione file, fine con successo del download file da un nodo remoto. Il nodo non risponde più alle r...
void start_request(uint8_t remote_node, uint8_t *param_request_name, uint8_t param_request_len, bool is_firmware)
Avvia una richiesta remota di download file ed inizializza le risorse nella classe.
void set_online(uint32_t dead_line_us)
Imposta il nodo OnLine, richiamato in heartbeat o altre comunicazioni client.
CanardMicrosecond last_online(void)
Imposta il nodo OnLine, richiamato in heartbeat o altre comunicazioni client.
bool is_online(bool is_heart_syncronized)
Controlla se il modulo master è online.
bool check_valid_syncronization(uint8_t current_transfer_id, CanardMicrosecond previous_tx_timestamp_us)
Controlla se messaggio valido (coerenza sequenza e validità di time_stamp)
CanardMicrosecond update_timestamp_message(CanardMicrosecond current_rx_timestamp_us, CanardMicrosecond previous_tx_timestamp_us)
Aggiorna i time stamp della classe sul messaggio standard UAVCAN per le successive sincronizzazioni.
CanardMicrosecond get_timestamp_syncronized(CanardMicrosecond current_rx_timestamp_us, CanardMicrosecond previous_tx_timestamp_us)
Legge il tempo sincronizzato dal master, utilizzabile dopo controllo di validità del messaggio.
class canardClass::master::file file
class canardClass::master::timestamp timestamp
class canardClass::master::heartbeat heartbeat
uint8_t module_rain(void)
Gestione transfer ID UAVCAN per la classe relativa.
CanardPortID publisher_module_rain
CanardPortID service_module_rain
class canardClass::port_id port_id
rmap_module_Rain_1_0 module_rain
void rxUnSubscribe(const CanardTransferKind transfer_kind, const CanardPortID port_id)
Rimozione di una sottoscrizione di una funzione Canard.
bool master_file_read_block_pending(uint32_t timeout_us)
Avvia la richiesta di un blocco file contiguo al file_server tramite classe e controllo Master.
static CanardMicrosecond getMicros()
Get MonotonicTime Interno realTime.
void send(CanardMicrosecond tx_deadline_usec, const CanardTransferMetadata *const metadata, const size_t payload_size, const void *const payload)
Send messaggio Canard con daeadline del tempo sincronizzato.
class canardClass::publisher_enabled publisher_enabled
bool slave_heartbeat_send_message(void)
Invia il messaggio di HeartBeat ai nodi remoti.
void set_canard_node_id(CanardNodeID local_id)
Imposta l'ID Nodo locale per l'istanza Canard privata della classe Canard.
class canardClass::master master
class canardClass::flag flag
void receiveQueue(void)
Gestione metodo ricezione coda messaggi dal buffer FIFO preparato di BxCAN Il buffer gestito nella IS...
void setReceiveMessage_CB(void(*ptrFunction)(canardClass &, const CanardRxTransfer *, void *), void *param)
Setta il CallBack Function per il processo esterno di interprete su messaggio ricevuto e conforme a C...
void transmitQueue(void)
Trasmette la coda con timeStamp sincronizzato. Per inviare con real_time va aggiornata la sincronizza...
class canardClass::next_transfer_id next_transfer_id
bool slave_servicelist_send_message(void)
Invia il messaggio dei servizi attivi ai nodi remoti.
bool is_canard_node_anonymous(void)
Controlla se il nodo è anonimo (senza ID Impostato)
void sendResponse(const CanardMicrosecond tx_deadline_usec, const CanardTransferMetadata *const request_metadata, const size_t payload_size, const void *const payload)
Send risposta al messaggio Canard con daeadline del tempo sincronizzato.
bool slave_pnp_send_request(uint64_t serial_number)
Invia il messaggio di PNP request (richiesta di node_id valido) al nodo server PNP (master)
CanardNodeID get_canard_master_id(void)
Get master node id for local set and flag operation automatic (sleep, power...)
void set_canard_master_id(CanardNodeID remote_id)
Set node master ID (slave respond to RMAP command and flag with master ID)
bool transmitQueueDataPresent(void)
Test coda presenza dati in trasmissione di Canard.
bool rxSubscribe(const CanardTransferKind transfer_kind, const CanardPortID port_id, const size_t extent, const CanardMicrosecond transfer_id_timeout_usec)
Sottoscrizione di una funzione Canard.
bool receiveQueueDataPresent(void)
Ritorna true se ci sono dati utili da gestire dal buffer di RX per BxCAN.
#define MODULE_MAIN_VERSION
Module main version.
Definition: config.h:34
#define WDT_CONTROLLER_MS
Task milliseconds minimal check.
Definition: config.h:90
#define MODULE_MINOR_VERSION
Module minor version.
Definition: config.h:37
#define SUPERVISOR_TASK_ID
Supervisor task ID.
Definition: config.h:168
#define RMAP_PROCOTOL_VERSION
rmap protocol version
Definition: config.h:40
#define ALL_TASK_ID
All task ID. Send message to ALL Task.
Definition: config.h:166
#define MODULE_TYPE
Type of module. It is defined in registers.h.
Definition: config.h:55
#define BOOT_LOADER_STRUCT_ADDR
Bootloader start address
Definition: config.h:118
#define WAIT_QUEUE_REQUEST_COMMAND_MS
Time to wait pushing command queue.
Definition: config.h:188
#define WDT_STARTING_TASK_MS
Init WatchDog Task local milliseconds.
Definition: config.h:88
#define ACCELEROMETER_TASK_ID
Accelerometer task ID.
Definition: config.h:176
#define UNUSED_SUB_POSITION
Monitor Sub Position not used flag.
Definition: config.h:94
#define TRACE_DEBUG_F(...)
Definition: debug_F.h:63
#define TRACE_ERROR_F(...)
Definition: debug_F.h:45
#define TRACE_INFO_F(...)
Definition: debug_F.h:57
#define TRACE_VERBOSE_F(...)
Definition: debug_F.h:71
#define FLASH_INFO_SIZE_LEN
Definition: flash.h:53
#define FLASH_FILE_POSITION
Definition: flash.h:50
#define FLASH_INFO_SIZE_U64
Definition: flash.h:56
#define FLASH_SIZE_ADDR(X)
Definition: flash.h:55
#define FLASH_FILE_SIZE_LEN
Definition: flash.h:54
#define FLASH_FW_POSITION
Definition: flash.h:48
#define FLASH_BUFFER_SIZE
Definition: flash.h:52
@ set
Set WDT (From Application TASK... All OK)
Definition: local_typedef.h:60
@ timer
Set Timered WDT (From Application long function WDT...)
Definition: local_typedef.h:61
@ pwr_nominal
Every Second (Nominale base)
Definition: local_typedef.h:33
@ pwr_on
Never (All ON, test o gestione locale)
Definition: local_typedef.h:32
task_flag
Task state Flag type.
Definition: local_typedef.h:65
@ suspended
Task is excluded from WDT Controller or Suspended complete.
Definition: local_typedef.h:68
@ sleepy
Task is in sleep mode or longer wait (Inform WDT controller)
Definition: local_typedef.h:67
@ normal
Normal operation Task controller.
Definition: local_typedef.h:66
#define CAN_NVIC_INT_PREMPT_PRIORITY
CAN_HandleTypeDef hcan1
#define PIN_CAN_STB
uint64_t StimaV4GetSerialNumber(void)
Get StimaV4 Serial Number from UID Cpu and Module TYPE.
#define PIN_CAN_EN
#define REGISTER_DATA_PUBLISH
#define REGISTER_METADATA_LEVEL_L1
#define REGISTER_RMAP_MASTER_ID
#define REGISTER_METADATA_TIME_PIND
#define REGISTER_UAVCAN_NODE_DESCR
#define REGISTER_UAVCAN_BITRATE
#define REGISTER_UAVCAN_NODE_ID
#define REGISTER_METADATA_LEVEL_TYPE1
#define REGISTER_UAVCAN_UNIQUE_ID
#define REGISTER_METADATA_LEVEL_TYPE2
#define REGISTER_METADATA_LEVEL_L2
#define REGISTER_METADATA_TIME_P1
#define REGISTER_UAVCAN_MTU
#define REGISTER_DATA_SERVICE
struct local elaborate data parameter
Definition: can_task.h:113
Flash * flash
Object Flash C++ access.
Definition: can_task.h:126
cpp_freertos::BinarySemaphore * registerAccessLock
Semaphore to register Cyphal access.
Definition: can_task.h:119
cpp_freertos::Queue * reportDataQueue
Queue to report data.
Definition: can_task.h:125
cpp_freertos::Queue * systemMessageQueue
Queue for system message.
Definition: can_task.h:123
cpp_freertos::Queue * requestDataQueue
Queue to request data.
Definition: can_task.h:124
configuration_t * configuration
system configuration pointer struct
Definition: can_task.h:114
EERegister * clRegister
Object Register C++ access.
Definition: can_task.h:128
system_status_t * system_status
system status pointer struct
Definition: can_task.h:115
cpp_freertos::BinarySemaphore * canLock
Semaphore to CAN Bus access.
Definition: can_task.h:120
bootloader_t * boot_request
Boot struct pointer.
Definition: can_task.h:116
cpp_freertos::BinarySemaphore * qspiLock
Semaphore to QSPI Memory flash access.
Definition: can_task.h:121
EEprom * eeprom
Object EEprom C++ access.
Definition: can_task.h:127
cpp_freertos::BinarySemaphore * systemStatusLock
Semaphore to system status access.
Definition: can_task.h:118
Backup && Upload Firmware TypeDef (BootLoader)
bool rollback_executed
An rollback of firmware was executed.
bool backup_executed
Firmware backup is executed.
bool app_forcing_start
Force starting APP from Flash RUN APP Memory Position.
bool app_executed_ok
Flag running APP (setted after new firmware, prevert a rollback operation)
bool request_upload
Request an upload of firmware.
uint64_t serial_number
module serial number
Definition: local_typedef.h:52
Report module.
rmapdata_t rain
Rain official (without Maintenance value)
rmapdata_t rain_full
Rain unofficial (With Maintenance value, for Display LCD)
rmapdata_t rain_tpr_60s_avg
Rain official (TPR on 1')
rmapdata_t quality
Rain quality of measure.
rmapdata_t tips_count
Number of tips readed (without Maintenance value)
rmapdata_t rain_tpr_05m_avg
Rain official (TPR on 5')
System message for queue.
uint32_t param
32 Bit for generic data or casting to pointer
uint8_t do_maint
Request maintenance (system_status)
uint8_t task_dest
Command struct.
uint8_t do_sleep
Optional param for difference level Sleep.
uint8_t do_calib
Calibrate accelerometr.
struct system_message_t::@7 command
struct system_status_t::@4 flags
Module error or alert.
bool is_clogged_up
Sensor is clogged up.
bool is_main_error
Main sensor in error.
struct system_status_t::@5 events
Module error or alert timings continuos verify.
task_t tasks[TOTAL_INFO_TASK]
Info Task && WDT.
Definition: local_typedef.h:92
bool is_bubble_level_error
Bubble software accelerometer error.
bool is_redundant_error
Redundant sensor in error.
bool is_maintenance
Module is in maintenance mode.
Definition: local_typedef.h:98
bool is_tipping_error
Tipping event error run.
bool is_accelerometer_error
Accelerometer error.
int32_t watch_dog_ms
WatchDog of Task Timer.
Definition: local_typedef.h:75
uint8_t running_pos
!=0 (CREATE) Task Started (Generic state of Task)
Definition: local_typedef.h:78
task_flag state
Long sleep Task.
Definition: local_typedef.h:77
wdt_flag watch_dog
WatchDog of Task.
Definition: local_typedef.h:74
uint16_t stack
Stack Max Usage Monitor.
Definition: local_typedef.h:76
uint8_t running_sub
Optional SubState of Task.
Definition: local_typedef.h:79