Buongiorno creo questa sezione così che possiamo mettere le varie domande per il progetto di esame
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?
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.
Vorrei anche dirle che, nel caso avesse difficoltà a farlo, possiamo fissare un appuntamento quando ha i task pronti e facciamo la stima del WCET insieme.
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?
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.
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);
}
#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);
}
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;
come si specifica qui sotto
io_ctx.Address = LSM6DSL_I2C_ADD_H;
Nella sezione 6.3.1 del datasheet del sensore lsm6dsl viene spiegato il significato del bit meno significativo dell'indirizzo, e perché questo può essere messo sia a 0 che a 1.
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?
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).
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);
}
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);
}
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
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
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
Per ora ho risolto allargando lo stack size del task di scrittura, mettendolo a 1024
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?
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?
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?
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);
}
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);
}
Buongiorno; così a prima vista non vedo nulla che mi sembri sospetto. Vuole prendere un appuntamento con me per verificare il codice e lo shield?