2021-01-23 06:34 AM
I'm using the STM32L031 and Low Layer code, generated with STM32CubeMX (lateset version)
If the selected oscillator for the RTC is not LSE (e.g. after poweron) the code generated with STM32CubeMX will disable the LSE via a ForceBackupDomainReset right after enabling it.
This is the entire SystemClock_Config:
void SystemClock_Config(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_0);
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_MSI_Enable();
while(LL_RCC_MSI_IsReady() != 1);
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_5);
LL_RCC_MSI_SetCalibTrimming(0);
LL_PWR_EnableBkUpAccess();
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
LL_RCC_LSE_Enable();
while(LL_RCC_LSE_IsReady() != 1);
if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE)
{
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
}
LL_RCC_EnableRTC();
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI);
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI);
LL_Init1msTick(2097000);
LL_SetSystemCoreClock(2097000);
LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_LSE, LL_RCC_MCO1_DIV_16);
}
and this is the part that first enables the LSE and disables it when the RTC does not have the LSE as source clock:
LL_PWR_EnableBkUpAccess();
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
LL_RCC_LSE_Enable();
while(LL_RCC_LSE_IsReady() != 1);
if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE)
{
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
}
It needs to (re-) enable the LSE inside the if statment again.
2021-01-27 09:00 AM
Useless disables, enables, resets, rewrites etc. introducing bugs, which wouldn't be there without that useless bloat - that's just the way HAL/Cube "professionals" write code. Drop the CubeMX code generation and leave those problems behind.
2021-01-27 09:36 AM
This isn't the HAL, it is the LL which is somewhat similar to the old SPL. It works quite well and I think that writing :
LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_3);
makes the intentions of the programmer more clear than:
GPIOA->BSRR = 0x0004;
It may be not as efficient but sometimes that is less important, in the code I showed there simply is a mistake where the LSE accidentally gets disabled. I sometimes make mistakes like that, it just needs to be fixed. Which is what I did in my code and hopefully ST will do in theirs.
2021-01-30 06:43 AM
Writing magic numbers is a misrepresentation of register level programming. A correct direct analogy to your example would be:
GPIOA->BSRR = GPIO_BSRR_BS3;
I know what LL is. Using it one still must read the reference manual, but, as it renames the registers and bits, it doubles the amount of work, because one has to translate from register names to LL names and back all the time. And you are still writing port A, pin 3, which doesn't make anything clear. If you want to make something really clear, then you have to write like this:
DRV_GPIO_PinSet1(BSP_LED_SYSTEM);
Now that's a clear intent of what exactly is being done there. Therefore make your own high-level sane driver libraries with typical often used functionality, but implement them with an effective register level code inside.
2021-01-30 10:51 AM