Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

STM32 LL non documentate???

Tipologie, strumenti di sviluppo, hardware e progetti

Moderatore: Foto UtentePaolino

0
voti

[1] STM32 LL non documentate???

Messaggioda Foto Utentedadduni » 25 ago 2018, 15:50

salve a tutti,
La ST ha dichiarato di non sviluppare più le HAL e sta migrando verso le Low Level Library che sono più vicine all'hardware. Io mi sto muovendo in questa direzione a livello didattico. Ho fatto tutta la tesi con le HAL e sono abbastanza pratico, sto cercando di "migrare" anche io piano piano, periferica per periferica. Il problema è che non c'è documentazione! Come faccio a trovare come far funzionare una periferica se non c'è scritto da nessuna parte come fare? Il manuale è solo l'elenco di funzioni contenute nelle librerie senza spiegare come usarle.
Probabilmente mi manca qualche pezzo
Avatar utente
Foto Utentedadduni
1.602 1 6 12
Expert EY
Expert EY
 
Messaggi: 983
Iscritto il: 23 mag 2014, 16:26

0
voti

[2] Re: STM32 LL non documentate???

Messaggioda Foto Utentepusillus » 25 ago 2018, 17:31

dadduni ha scritto:La ST ha dichiarato di non sviluppare più le HAL...

Questa sarebbe una buona notizia le HAL fanno pena!
Dove hai letto la notizia?
Se ha deciso di concentrarsi su le LL dovrà anche impegnarsi con la documentazione. Hai provato a guardare i sorgenti delle LL? Magari le funzioni sono documentate con esaurienti commenti.
Mi pare comunque che le HAL si appoggiano a loro volta sulle LL.
Non ho capito perché non ha proseguito lo sviluppo delle SPL che erano un buon compromesso e il codice abbastanza maturo!
Immagine
Un lungo viaggio di mille miglia comincia con un solo passo
Lao Tzu
Avatar utente
Foto Utentepusillus
1.497 1 5 11
Sostenitore
Sostenitore
 
Messaggi: 572
Iscritto il: 5 mar 2016, 15:19
Località: Latina

0
voti

[3] Re: STM32 LL non documentate???

Messaggioda Foto Utenteluxinterior » 25 ago 2018, 19:41

Le HAL sono un delirio (io ho inziato tre volte con le HAL e tre volte ho rinunciato) Complimenti a dadduni per esser riuscito ad utilizzarle.
La LL è molto molto meglio (sempre parere personale) è un vestito cucito sull'HW. A me non dispiacciono,
Come dice pusillus la documentazione la trovi leggendo i files. Leggendo i manuali e la spiegazione dei registri devi solo capire come avviene la traduzione nelle LL. E' un po' che non uso STM ma dovrebbero esserci anche esempi di utilizzo.
Se non ricordo male HAL è uno strato costruito sopra le LL quindi spulciando il codice delle HAL dovresti trovare indicaizoni sulle LL.
Avatar utente
Foto Utenteluxinterior
2.322 2 4 8
Expert EY
Expert EY
 
Messaggi: 1323
Iscritto il: 6 gen 2016, 17:48

0
voti

[4] Re: STM32 LL non documentate???

Messaggioda Foto Utentedadduni » 25 ago 2018, 20:31

Mah oddio, perché dite che sono un delirio? Io mi ci sono trovato benissimo, dico l'onesta verità: sto cambiando solo perché tutti ne parlano male e consigliano di starne alla larga. Per il data processing che mi è servito nella tesi le Hal sono andate più che bene!
Venendo a noi. Sto sbattendo la testa contro il PWM. Partendo da CubeMX genero il file di impostazione del Timer con il prescaler, fine conteggio, Output Compare e pin configurato in uscita come AlternateFunction che (in teoria) dovrebbe essere il pin con PWM.
Nelle HAL il comando: HAL_Tim_PWM_Start fa questo
Codice: Seleziona tutto
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
{
  /* Check the parameters */
  assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel));

  /* Enable the Capture compare channel */
  TIM_CCxChannelCmd(htim->Instance, Channel, TIM_CCx_ENABLE);

  if(IS_TIM_BREAK_INSTANCE(htim->Instance) != RESET)
  {
    /* Enable the main output */
    __HAL_TIM_MOE_ENABLE(htim);
  }

  /* Enable the Peripheral */
  __HAL_TIM_ENABLE(htim);

  /* Return function status */
  return HAL_OK;
}


- Attiva il Caputre compare
- Attiva gli output
- Attiva la periferica

Provando a fare lo stesso in LL non funziona.
Codice: Seleziona tutto
 
LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH1);
  LL_TIM_EnableAllOutputs(TIM3);
  LL_TIM_EnableCounter(TIM3);


attivo il canale 1 del timer 3 per Capture compare, attivo tutti gli output, attivo il counter: come penso che facciano le HAL. Secondo voi perché non funziona? Credo che il codice genreato da CubeMX sia corretto, Credo di essere io a sbagliare ad attivare la periferica dal main.
Daivde
Avatar utente
Foto Utentedadduni
1.602 1 6 12
Expert EY
Expert EY
 
Messaggi: 983
Iscritto il: 23 mag 2014, 16:26

0
voti

[5] Re: STM32 LL non documentate???

Messaggioda Foto Utenteluxinterior » 26 ago 2018, 9:21

Ecco appunto una volta entrato in una funzione della HAL non sia mai quando e come ne uscirai.

Venendo al tuo problema ....non so risponderti
Le LL svolgono funzioni elementari sull' HW quindi devi organizzare tu il tutto. Una checklist (a memoria)
- Abilitare il clock per la periferica timer
- Abilitare il clock per la porta di I/O utilizzata
- Configurare i pin I/O per alternate function
- Configurare il timer per la funzione voluta
- Abilitare il timer

Se lavori con un debugger puoi verificare e modificare i registri drettamente senza ricompilare ogni volta il tutto.
Comincia verificando RCC e GPIO se la configuraizone è OK controlla il timer
Avatar utente
Foto Utenteluxinterior
2.322 2 4 8
Expert EY
Expert EY
 
Messaggi: 1323
Iscritto il: 6 gen 2016, 17:48

0
voti

[6] Re: STM32 LL non documentate???

Messaggioda Foto Utentepusillus » 27 ago 2018, 12:40

ho installato un tool che fa la migrazione da SPL a LL.
Ho provato a dargli in pasto un programmino (stm32f103c8) che con il PWM sul TIM4 regola l'intensita di un led collegato a CH1 PB6. con due pulsanti su PA0 ed PA1 si alza o abbassa il duty cycle.
SPL:
Codice: Seleziona tutto
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"

#define PERIOD 1000
int main(void)
{
   int TIM_Pulse = 0;
   int i;

   GPIO_InitTypeDef port;
   TIM_TimeBaseInitTypeDef timer;
   TIM_OCInitTypeDef timerPWM;

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

   GPIO_StructInit(&port);
   port.GPIO_Mode = GPIO_Mode_IPU;
   port.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
   port.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO_Init(GPIOA, &port);

   GPIO_StructInit(&port);
   port.GPIO_Mode = GPIO_Mode_AF_PP;
   port.GPIO_Pin = GPIO_Pin_6;
   port.GPIO_Speed = GPIO_Speed_2MHz;
   GPIO_Init(GPIOB, &port);

   TIM_TimeBaseStructInit(&timer);
   timer.TIM_Prescaler = 720;
   timer.TIM_Period = PERIOD;
   timer.TIM_ClockDivision = 0;
   timer.TIM_CounterMode = TIM_CounterMode_Up;
   TIM_TimeBaseInit(TIM4, &timer);

   TIM_OCStructInit(&timerPWM);
   timerPWM.TIM_Pulse = 10;
   timerPWM.TIM_OCMode = TIM_OCMode_PWM1;
   timerPWM.TIM_OutputState = TIM_OutputState_Enable;
   timerPWM.TIM_OCPolarity = TIM_OCPolarity_High;
   TIM_OC1Init(TIM4, &timerPWM);

    TIM_Cmd(TIM4, ENABLE);

    while(1)
    {
       if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) {
          if (TIM_Pulse < PERIOD)
             TIM_Pulse++;
          //TIM4->CCR1 = TIM_Pulse;
          TIM_SetCompare1(TIM4, TIM_Pulse);


       }
       if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) == 0) {
          if (TIM_Pulse > 0)
             TIM_Pulse--;
          TIM4->CCR1 = TIM_Pulse;
       }

       /* delay */
       for(i=0;i<0x10000;i++);
    }
}


LL:
Codice: Seleziona tutto
#include "stm32f1xx_hal_conf.h"
#include "stm32f1xx_ll_rcc.h"
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_gpio.h"
#include "stm32f1xx_ll_tim.h"

#define PERIOD 1000
int main(void)
{
   int TIM_Pulse = 0;
   int i;

   LL_GPIO_InitTypeDef port;
   LL_TIM_InitTypeDef timer;
   LL_TIM_OC_InitTypeDef timerPWM;

   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
   LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4);

   LL_GPIO_StructInit(&port);
   port.Mode = LL_GPIO_MODE_INPUT;
   port.Pin = LL_GPIO_PIN_0 | LL_GPIO_PIN_1;
   port.Speed = LL_GPIO_SPEED_FREQ_LOW;
   LL_GPIO_Init(GPIOA, &port);

   LL_GPIO_StructInit(&port);
   port.Mode = LL_GPIO_MODE_ALTERNATE;
   port.Pin = LL_GPIO_PIN_6;
   port.Speed = LL_GPIO_SPEED_FREQ_LOW;
   LL_GPIO_Init(GPIOB, &port);

   LL_TIM_StructInit(&timer);
   timer.Prescaler = 720;
   timer.Autoreload = PERIOD;
   timer.ClockDivision = 0;
   timer.CounterMode = LL_TIM_COUNTERMODE_UP;
   LL_TIM_Init(TIM4, &timer);

   LL_TIM_OC_StructInit(&timerPWM);
   timerPWM.CompareValue = 10;
   timerPWM.OCMode = LL_TIM_OCMODE_PWM1;
   timerPWM.OCState = LL_TIM_OCSTATE_ENABLE;
   timerPWM.OCPolarity = LL_TIM_OCPOLARITY_HIGH;
   LL_TIM_OC_Init(TIM4, LL_TIM_CHANNEL_CH1, &timerPWM);

    LL_TIM_EnableCounter(TIM4);

    while(1)
    {
       if (LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_0) == 0) {
          if (TIM_Pulse < PERIOD)
             TIM_Pulse++;
          //TIM4->CCR1 = TIM_Pulse;
          LL_TIM_OC_SetCompareCH1(TIM4, TIM_Pulse);


       }
       if (LL_GPIO_IsInputPinSet(GPIOA, LL_GPIO_PIN_1) == 0) {
          if (TIM_Pulse > 0)
             TIM_Pulse--;
          TIM4->CCR1 = TIM_Pulse;
       }

       /* delay */
       for(i=0;i<0x10000;i++);
    }
}


Come noterai il codice non cambia quasi per niente. Le funzioni sono molto low level, ho guardato i sorgenti dell LL per il TIMER.
Ad esempio per variare il valore di comparazione di CH1 nel programma SPL ho usato la funzione:
Codice: Seleziona tutto
TIM_SetCompare1(TIM4, TIM_Pulse);

oppure direttamente il registro:
Codice: Seleziona tutto
TIM4->CCR1 = TIM_Pulse;

con le LL puoi scrivere direttamente il registro o utilizzare una funzione:
Codice: Seleziona tutto
LL_TIM_OC_SetCompareCH1(TIM4, TIM_Pulse);


se guardi i sorgenti delle rispettive funzioni sono molto simili:
LL:
Codice: Seleziona tutto
/**
  * @brief  Set compare value for output channel 1 (TIMx_CCR1).
  * @note Macro @ref IS_TIM_CC1_INSTANCE(TIMx) can be used to check whether or not
  *       output channel 1 is supported by a timer instance.
  * @rmtoll CCR1         CCR1          LL_TIM_OC_SetCompareCH1
  * @param  TIMx Timer instance
  * @param  CompareValue between Min_Data=0 and Max_Data=65535
  * @retval None
  */
__STATIC_INLINE void LL_TIM_OC_SetCompareCH1(TIM_TypeDef *TIMx, uint32_t CompareValue)
{
  WRITE_REG(TIMx->CCR1, CompareValue);
}


SPL:
Codice: Seleziona tutto
/**
   * @brief  Sets the TIMx Capture Compare1 Register value
   * @param  TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
   * @param  Compare1: specifies the Capture Compare1 register new value.
   * @retval None
   */
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
   /* Check the parameters */
   assert_param(IS_TIM_LIST8_PERIPH(TIMx));
   /* Set the Capture Compare1 Register value */
   TIMx->CCR1 = Compare1;
}

Immagine
Un lungo viaggio di mille miglia comincia con un solo passo
Lao Tzu
Avatar utente
Foto Utentepusillus
1.497 1 5 11
Sostenitore
Sostenitore
 
Messaggi: 572
Iscritto il: 5 mar 2016, 15:19
Località: Latina

0
voti

[7] Re: STM32 LL non documentate???

Messaggioda Foto Utentedadduni » 28 ago 2018, 12:35

Ti ringrazio davvero per la prova effettuata, era come immaginavo: le LL sono solo un mini aggiornamento delle SPL. Avevo pensato di fare questa prova con il convertitore ma non conoscendo le SPL avrei dovuto copiare il codice di sana pianta e se non avesse funzionato avrebbe solo aggiunto incertezza al mio test perché non avevo idea di dove stava l'errore.
Nel mio modo di procedere le inizializzazioni del clock e del timer le ho fatte fare in automatico a CubeMX, sono uscite uguali a quelle scritte da te e convertite.
Il problema che anche io all'inizio ho avviato il timer con:
Codice: Seleziona tutto
LL_TIM_EnableCounter(TIM3); //io ho provato col timer 3


E così non funzionava. Ho dovuto aggiungere lo start del Output Compare per farlo funzionare:
Codice: Seleziona tutto
  LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH1);

Forse ho fatto qualche errore in giro, dopo pranzo controllo e vi aggiorno.
Davide
Avatar utente
Foto Utentedadduni
1.602 1 6 12
Expert EY
Expert EY
 
Messaggi: 983
Iscritto il: 23 mag 2014, 16:26

0
voti

[8] Re: STM32 LL non documentate???

Messaggioda Foto Utentedadduni » 29 ago 2018, 16:29

Svelato l'arcano!
Io mi faccio generare le inizializzazioni da CubeMX Per comodità. Non avevo fatto caso che nell'inizializzaizone della struttura del PWM c'è OCMODE e OCSTATE e lo state era "Disable" di default non so per quale motivo. Infatti se lo lascio Disable nell'Inizializzazione allora devo abilitarlo a mano con il comando. Se lo abilito all'inizio poi basta fare LL_TIM_EnableCount.
Grazie mille, sono agli inizi con queste librerie e mi perdo su delle fesserie
Davide
Avatar utente
Foto Utentedadduni
1.602 1 6 12
Expert EY
Expert EY
 
Messaggi: 983
Iscritto il: 23 mag 2014, 16:26

0
voti

[9] Re: STM32 LL non documentate???

Messaggioda Foto Utentedadduni » 1 set 2018, 13:17

Vado avanti su questo 3d. Sempre parlando di documentazione delle LowLevelLibrary da parte di ST vi presento un'altra grande novità: le voci mancanti!
Per inizializzare le perfieriche la ST ci ha abituato a rimpire delle struct e poi passarle come puntatore ad una funzione di inizializzazione che si occupa di mettere le impostazioni al posto giusto. Il manuale contiene questa struttura per l'ADC:
LL.png


In cui sembra che il tipo LL_ADC_CommonInitTypeDef sia una struct che contiene quei 4 campi. Eppure, guardando nelle librerie......... sorpresa!
Codice: Seleziona tutto
typedef struct
{
  uint32_t Multimode;                   /*!< Set ADC multimode configuration..........
} LL_ADC_CommonInitTypeDef;


Ce ne sta solo uno! E gli altri? Bho... bisogna lanciare funzioni apposite. Mi chiedo se non c'è scritto nel codice: perché c'è scritto nel manuale? :mrgreen: :mrgreen: :mrgreen:
Avatar utente
Foto Utentedadduni
1.602 1 6 12
Expert EY
Expert EY
 
Messaggi: 983
Iscritto il: 23 mag 2014, 16:26

0
voti

[10] Re: STM32 LL non documentate???

Messaggioda Foto Utentepusillus » 1 set 2018, 16:47

ho visto alcuni sorgenti delle librerie stm32f1xx_ll_xxx.h.
Mi pare che il codice è commentato per poter generare documentazione con Doxygen.
Possibile che non c'è nulla in giro?
Immagine
Un lungo viaggio di mille miglia comincia con un solo passo
Lao Tzu
Avatar utente
Foto Utentepusillus
1.497 1 5 11
Sostenitore
Sostenitore
 
Messaggi: 572
Iscritto il: 5 mar 2016, 15:19
Località: Latina

Prossimo

Torna a Realizzazioni, interfacciamento e nozioni generali.

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite