Domande progetto

Domande progetto

di Davide Pirolo -
Numero di risposte: 18

Buongiorno creo questa sezione così che possiamo mettere le varie domande per il progetto di esame

In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Mi chiedevo: con utilizzo di comunicazione asincrona come si calcolano i WCET di comunicazione con I2C? Dovrebbe rimanere 650 us? Oppure in caso di utilizzo di dma i tempi si abbassano? Perché se rimangono uguali, anche se la cpu è libera comunque non legge valori freschi ogni volta per il giroscopio, giusto?
In riposta a Davide Pirolo

Ri: Domande progetto

di Pietro Braione -
Nel caso di comunicazione asincrona, dal momento che la CPU non è impegnata ad aspettare il termine della comunicazione, il tempo *non* è più quello della comunicazione I2C. A quel punto diventa solo quello deile istruzioni restanti; calcolarlo è piuttosto difficiile, si può fare una specie di benchmark, che è come ho fatto io per calcolare i WCET delle comunicazioni I2C. Ossia: supponiamo che il codice sia diviso in due task, uno che prepara la comunicazione I2C, ed uno che legge i risultati (il secondo attivato dall'interrupt che segnala che la comunicazione è finitaI, Faccio partire un timer; quindi faccio un certo numero (diciamo 10.000) di comunicazioni I2C, ma solo la preparazione (primo task); alla fine delle 10.000 ripetizioni del primo task fermo il timer e stampo la differenza di tempo. La durata media del primo task è la differenza di tempo diviso 10.000. Se il primo task contiene degli if o dei cicli for-while, occorre fare in modo che il primo task esegua passando per il percorso più lumgo. Faccio lo stesso lavoro con il task che elabora i dati ricevuti dalla comunicazione I2C, e calcolo una stima del WCET anche per quello. Questo è il meglio che, con gli strumenti che abbiamo a disposizione, possiamo fare.
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Avrei un'altra domanda: ho implementato freertos e ho sviluppato 4 task. Poi ho creato 4 timers, con frequenze differenti per "svegliare" i task nel momento in cui questi producono un interrupt. Però i task continuano a girare da soli, ovvero non vengono svegliati dai timer, ma all'istante 0 vengono fatti partire tutti. Allora forse non ho capito come funzionano i timer con freertos, non è che devo implementare i software timers, quelli presenti in freertos?
Oppure fare come abbiamo fatto in laboratorio, che i task usano i timers per gestire al loro interno il tempo che devono aspettare?
In riposta a Davide Pirolo

Ri: Domande progetto

di Pietro Braione -
Sicuramente se usa i timer insieme a freertos deve usare i software timer offerrti da freertos stesso: altrimenti il sistema operativo non può sapere che vuole "mettere a dormire" un task, e quindi lo schedula per l'esecuzione. Provi così e vediamo se funziona.
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Quando scrivo la funzione per la lettura asincrona del giroscopio nell'indirizzo di lettura del DMA quale registro bisogna scrivere? Ho visto che lsm6dsl ha 2 indirizzi di lettura dati
#define LSM6DSL_I2C_ADD_L 0xD5U
#define LSM6DSL_I2C_ADD_H 0xD7U
quale devo utilizzare dei due per la lettura del giroscopio?

static int32_t lsm6dsl_angular_rate_raw_get_async(void *handle, uint8_t *destBuf)
{
return HAL_I2C_Mem_Read_DMA((I2C_HandleTypeDef *) handle, LSM6DSL_I2C_ADD_L, (LSM6DSL_OUTX_L_G | 0x22U), I2C_MEMADD_SIZE_8BIT, destBuf, 6);
}
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Ho trovato la risposta nel file iks01a2_env_sensors_ex.c (riga 1071) e utilizza LSM6DSL_I2C_ADD_H
come si specifica qui sotto
io_ctx.Address = LSM6DSL_I2C_ADD_H;
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Mi chiedevo se ci fosse la possibilità di differenziare il tipo di dato disponibile nella callback della comunicazione asincrona, perché vorrei che si sapesse che dato è stato trasmesso in memoria. C'è un modo per saperlo, tipo aggiungendo un parametro nella callback?
In riposta a Davide Pirolo

Ri: Domande progetto

di Pietro Braione -
Non c'è modo: se aggiunge un parametro nella callback. la signature della callback diventa diversa e il compilatore non la riconosce più come una callback (non fa l'override di quella di default).
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
buongiorno volevo sapere che valore mettere nella dichiarazione della funzione HAL_I2C_Mem_Read e HAL_I2C_Mem_Write subito dopo il parametro reg, ovver l'indirizzo di memoria.

static int32_t my_read_reg_lsm6dsl(void *handle, uint8_t reg, uint8_t *data, uint16_t len)
{
return HAL_I2C_Mem_Read((I2C_HandleTypeDef *) handle, LSM6DSL_I2C_ADD_H, (reg | 0x80U), I2C_MEMADD_SIZE_8BIT, data, len, 400);
}
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Mi è capitato che quando il programma fa l'output con le println (quando ne devo fare 6 di seguito) possa andare nel blocco HardFault, sa perché genera questo errore?
Pensavo perché non fossero inizializzate le variabili, ma le ho controllate tutte e hanno tutte un valore.
Pensavo perché magari il micocontrollore non riuscisse a tenere il "ritmo", perché se provo ad eseguirle passo passo le esegue ma non le stampa in console
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Sto provando anche con semplici stringhe ma dopo alcune stampe va nel blocco hard_fault. Non capisco a cosa sia dovuto. Anche eseguendolo step by step arriva ad una certa stampa e va in errore
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Per ora ho risolto allargando lo stack size del task di scrittura, mettendolo a 1024
In riposta a Davide Pirolo

Ri: Domande progetto

di Pietro Braione -
Buongiorno; probabilmente bisogna inserire un minimo timing tra una printf e l'altra, come fa notare. A me non è mai successo, ma non ho mai fatto stampe da freertos. Un'altra possibilità potrebbe essere un accesso concorrente alla printf, che le ricordo non è rientrante. Ci sono due task o più che fanno printf in parallelo?
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
Ho un problema da tempo con gli accelerometri e il giroscopio: non raccolgono nessun dato. Ho provato svariate configurazioni per l'inizializzazione. La cosa strana che nel sensore lsm303agr il magnetometro raccoglie dati, mentre l'accelerometro no. Per questo sensore ho creato 2 contesti, come suggeriva il file lsm303agr. Mentre per il sensore lsm6dsl ne ho creato uno solo, dato che riesce (leggendo il datasheet) a leggere entambi.
Riporto qui sotto le init dell'accelerometro lsm303agr e del giroscopio + accelerometro di lsm6dsl.

static void lsm6dsl_init(void){
ctx1.handle = &hi2c1;
ctx1.read_reg = my_read_reg_lsm6dsl;
ctx1.write_reg = my_write_reg_lsm6dsl;

/* Enable BDU */
if (lsm6dsl_block_data_update_set(&ctx1, PROPERTY_ENABLE) != HAL_OK)
{
Error_Handler();
}
/* FIFO mode selection */
if (lsm6dsl_fifo_mode_set(&ctx1, LSM6DSL_BYPASS_MODE) != HAL_OK)
{
Error_Handler();
}
/* Enable register address automatically incremented during a multiple byte access with a serial interface. */
if (lsm6dsl_auto_increment_set(&ctx1, PROPERTY_ENABLE) != HAL_OK)
{
Error_Handler();
}
/* Set power mode */
if(lsm6dsl_xl_power_mode_set(&ctx1, LSM6DSL_XL_HIGH_PERFORMANCE) != HAL_OK)
{
Error_Handler();
}
/* Select default output data rate. */
if (lsm6dsl_xl_data_rate_set(&ctx1, LSM6DSL_XL_ODR_1k66Hz) != HAL_OK)
{
Error_Handler();
}
/* Full scale selection. */
if (lsm6dsl_xl_full_scale_set(&ctx1, LSM6DSL_2g) != HAL_OK)
{
Error_Handler();
}
/* Set power mode */
if(lsm6dsl_gy_power_mode_set(&ctx1, LSM6DSL_GY_HIGH_PERFORMANCE) != HAL_OK)
{
Error_Handler();
}
/* Select default output data rate. */
if (lsm6dsl_gy_data_rate_set(&ctx1, LSM6DSL_GY_ODR_6k66Hz) != HAL_OK)
{
Error_Handler();
}
/* Full scale selection. */
if (lsm6dsl_gy_full_scale_set(&ctx1, LSM6DSL_2000dps) != HAL_OK)
{
Error_Handler();
}
}

/**
* Inizializza il contesto del sensore lsm303agr solo magnetometro
*/
static void lsm303agr_magno_init(void){
ctx2.handle = &hi2c1;
ctx2.read_reg = my_read_reg_lsm303agr;
ctx2.write_reg = my_write_reg_lsm303agr;

/* Enable BDU */
if (lsm303agr_mag_block_data_update_set(&ctx2, PROPERTY_ENABLE) != HAL_OK)
{
Error_Handler();
}

if (lsm303agr_mag_operating_mode_set(&ctx2, LSM303AGR_CONTINUOUS_MODE) != HAL_OK)
{
Error_Handler();
}

/* Output data rate selection */
if (lsm303agr_mag_data_rate_set(&ctx2, LSM303AGR_MG_ODR_100Hz) != HAL_OK)
{
Error_Handler();
}

/* Self Test disabled. */
if (lsm303agr_mag_self_test_set(&ctx2, PROPERTY_DISABLE) != HAL_OK)
{
Error_Handler();
}
}

/**
* Inizializza contesto del sensore lsm303agr solo l'accelerometro
*/
static void lsm303agr_accel_init(void){
ctx4.handle = &hi2c1;
ctx4.read_reg = my_read_reg_lsm303agr_xl;
ctx4.write_reg = my_write_reg_lsm303agr_xl;

/* Enable BDU */
if (lsm303agr_xl_block_data_update_set(&ctx4, PROPERTY_ENABLE) != HAL_OK)
{
Error_Handler();
}

if(lsm303agr_xl_operating_mode_set(&ctx4, LSM303AGR_LP_8bit) != HAL_OK){
Error_Handler();
}

/* FIFO mode selection */
if (lsm303agr_xl_fifo_mode_set(&ctx4, LSM303AGR_BYPASS_MODE) != HAL_OK)
{
Error_Handler();
}

/* Output data rate selection */
if (lsm303agr_xl_data_rate_set(&ctx4, LSM303AGR_XL_ODR_1kHz620_LP) != HAL_OK)
{
Error_Handler();
}

/* Full scale selection. */
if (lsm303agr_xl_full_scale_set(&ctx4, LSM303AGR_2g) != HAL_OK)
{
Error_Handler();
}
}

Manca qualcosa? Ho aggiunto qualcosa di troppo? Ho pensato che magari fossero guasti?
In riposta a Davide Pirolo

Ri: Domande progetto

di Davide Pirolo -
e il setting dei registri è quanto segue:

static int32_t my_read_reg_lsm6dsl(void *handle, uint8_t reg, uint8_t *data, uint16_t len)
{
//need to set the most significant bit of register to allow address auto increment with multiple commands mode
return HAL_I2C_Mem_Read((I2C_HandleTypeDef *) handle, LSM6DSL_I2C_ADD_H, (reg | 0x80U), I2C_MEMADD_SIZE_8BIT, data, len, 400);
}

static int32_t my_write_reg_lsm6dsl(void *handle, uint8_t reg, uint8_t *data, uint16_t len)
{
//need to set the most significant bit of register to allow address auto increment with multiple commands mode
return HAL_I2C_Mem_Write((I2C_HandleTypeDef *) handle, LSM6DSL_I2C_ADD_H, (reg | 0x80U), I2C_MEMADD_SIZE_8BIT, data, len, 400);
}

static int32_t my_read_reg_lsm303agr_xl(void *handle, uint8_t reg, uint8_t *data, uint16_t len)
{
//need to set the most significant bit of register to allow address auto increment with multiple commands mode
return HAL_I2C_Mem_Read((I2C_HandleTypeDef *) handle, LSM303AGR_I2C_ADD_XL, (reg | 0x80U), I2C_MEMADD_SIZE_8BIT, data, len, 400);
}

static int32_t my_write_reg_lsm303agr_xl(void *handle, uint8_t reg, uint8_t *data, uint16_t len)
{
//need to set the most significant bit of register to allow address auto increment with multiple commands mode
return HAL_I2C_Mem_Write((I2C_HandleTypeDef *) handle, LSM303AGR_I2C_ADD_XL, (reg | 0x80U), I2C_MEMADD_SIZE_8BIT, data, len, 400);
}