Author Topic: Is ST Cube IDE a piece of buggy crap?  (Read 164283 times)

0 Members and 2 Guests are viewing this topic.

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #100 on: August 04, 2021, 06:08:38 pm »
Yes that is very true.

One wonders whether Wiznet put more effort into their code than ST put into their ETH libs :)
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Online SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14464
  • Country: fr
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #101 on: August 04, 2021, 06:15:11 pm »
However since IOT devices are typically behind a firewall / NAT router, the chances of a real attack are very low.

Pretty blunt assertion. Do you really think that most IoT devices in use are connected to perfectly secure networks? Yeah. ::)

Now, one thing we could say is that, particularly these days, a connection via Ethernet has chances to be better protected than via WiFi, for instance, for a number of reasons. But even so, claiming that chances of a real attack are very low?
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #102 on: August 04, 2021, 06:23:07 pm »
However since IOT devices are typically behind a firewall / NAT router, the chances of a real attack are very low.
Only when the device is very small, the Wizz will probably be too small.
However devices such as a raspberri pi run Linux are large enough such that a hacker can easily install a reverse shell or reverse proxy rendering any firewall that only scans incoming traffic useless.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #103 on: August 04, 2021, 06:25:53 pm »
Yes that is very true.
One wonders whether Wiznet put more effort into their code than ST put into their ETH libs :)
Because for Wizznet it is their product they earn money with.
ST sells microcontrollers, the libraries are for getting started, if you look at st.com they list around six commercial IP stacks and vendors. Those stack vendors will also put a lof of effort in their core product  ;)
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #104 on: August 04, 2021, 06:48:34 pm »
"ST sells microcontrollers, the libraries are for getting started, "

Is there any detail available on this topic?

For example a list of known bugs?
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1668
  • Country: us
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #105 on: August 04, 2021, 06:56:18 pm »
"ST sells microcontrollers, the libraries are for getting started, "

Is there any detail available on this topic?

For example a list of known bugs?

Many forests have given their lives to print lists of ST microcontroller bugs.
Complexity is the number-one enemy of high-quality code.
 

Offline JOEBOBSICLE

  • Regular Contributor
  • *
  • Posts: 63
  • Country: gb
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #106 on: August 04, 2021, 07:39:28 pm »
I've had good fortune with lwIP and the st ethernet drivers.  I have a lot worse luck with other stacks from other vendors.

I did read the ethernet HAL driver from ST completely and I couldn't find any problems.
I'd say 90% of issues are from folk not understanding data cache. You have to use the MPU to get ethernet working on any parts with data cache turned on.
« Last Edit: August 04, 2021, 07:41:35 pm by JOEBOBSICLE »
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #107 on: August 05, 2021, 07:59:57 am »
"I'd say 90% of issues are from folk not understanding data cache. You have to use the MPU to get ethernet working on any parts with data cache turned on."

Isn't that supposed to be transparent?

I did a google on "MPU" and it seems to be just the microprocessor :)

I see Cube generating two lots of partly duplicated startup code.  This bit is from SetSysClock(void) which is called from SystemInit() which is called from the .s startup (so this happens first)

Code: [Select]
/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

The second bit is from HAL_Init from stm32f4xx_hal.c

Code: [Select]
#if (INSTRUCTION_CACHE_ENABLE != 0U)
__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */

#if (DATA_CACHE_ENABLE != 0U)
__HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */

#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */

and there was this. The yellow bit was set to 0 and I changed it to 1 (stm32f4xx_hal_conf.h) and the code runs fine



For some reason the 1st version does not enable FLASH_ACR_PRFTEN. Well, they want to do the minimum init at startup and then use the .h config setting to control the last bit. But this is yet another example of Cube generating crap code where multiple funcs do the same things. For example the clock divisors get set up in two places, too - identically as it happens but I spent some time working out why changing the SPI clocks did nothing, until I found the other place.

But this isn't the data cache, is it? How is this relevant to ethernet?

EDIT: the data cache issue seems real:
https://community.st.com/s/question/0D50X0000AnsIJeSQM/how-to-get-ethernet-working-again-after-upgrading-to-firmware-fwh7v140-
But it isn't clear if this is relevant to 32F4xx.

Here appears to be a long list of Cube bugs: https://nadler.com/backups/20200111_draft2_STM_Cube_Issues_and_Workflow.html
« Last Edit: August 05, 2021, 11:33:30 am by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline dietert1

  • Super Contributor
  • ***
  • Posts: 2068
  • Country: br
    • CADT Homepage
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #108 on: August 05, 2021, 02:36:15 pm »
When i open the last link, i see a red warning "cube will trash your code". It happened to me once. Then i discovered that the generated code contains markup for "user code" that stays protected from code generation. Seems like the author of that web page was unable to discover the scheme, at least i did not see it on his page. Application of these frameworks requires a certain level of insight.
Concerning double generated code the same applies. Try to understand how you got the redundant initialization sequence and you will be able to resolve it. You may have to repeat the initial steps of project setup to see at which step it happens. Cube isn't a random number generator. For example i could invent a setup where the IDE and cube both insert initialization code. The IDE does it to support the CRT for easy main() testing, lets say at some default clock of 4 MHz. Cube does it in great detail according to visual configuration. Now if you include the cortex libraries from arm, it gets even more thrilling.

Regards, Dieter
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #109 on: August 05, 2021, 03:04:05 pm »
Yes indeed the Cube generated code contains constructs where you are allowed to insert your own code:

Code: [Select]
/**
  * Initializes the Global MSP.
  */
void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */

  /* USER CODE END MspInit 0 */

  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_RCC_PWR_CLK_ENABLE();

  /* System interrupt init*/
  /* PendSV_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(PendSV_IRQn, 15, 0);

  /* USER CODE BEGIN MspInit 1 */

  /* USER CODE END MspInit 1 */
}



However I am not sure that is anywhere near the whole story. I have just gone through the entire initialisation code and compiled the various bits into one piece of code which is inline and starts at the start of main(). The first bit of it was in SystemInit() which was called from the assembler startup code, just before it went to main(). Why from there? Why call a C function from asm startup, immediately before you go main()?

There is a number of clear duplicates, but I am not 100% sure if there might be a reason behind them, to do with subtle timing issues (like the famous Ethernet one where having a PCLK2 divisor of 8 or 16 broke the ethernet subsystem, unless timing was ensured via another route):

Code: [Select]
int main(void)
{
// This was in SystemInit()
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
#endif
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;

/* Reset CFGR register */
RCC->CFGR = 0x00000000;

/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;

/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x24003010;

/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;

/* Disable all interrupts */
RCC->CIR = 0x00000000;

/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
// This was in SetSysClock(), and the settings were partly overriden later by
// stuff in SystemClock_Config()!

volatile uint32_t StartUpCounter = 0, HSEStatus = 0;

/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);

/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}

/* Enable high performance mode, System frequency up to 168 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_PMODE;

// *** THIS CLOCK CONFIG GETS OVERRIDEN below ***
/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;

/* PCLK2 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE2_DIV4;

/* PCLK1 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

/************************* PLL Parameters *************************************/
// These produce a 168MHz CPU clock (336/2) and a 48MHz USB clock (336/7)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      25
#define PLL_N      336

/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7

/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
               (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;

/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0) {}

/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
// This stuff is also partly repeated further below. What is not being done here, for
// no obvious reason, is FLASH_ACR_PRFTEN. So this line is partly pointless.
// But maybe there are timing reasons for this...
FLASH->ACR = FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;

/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;

/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL) {}

/* Configure the Vector Table location add offset address ------------------*/
#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

// Copy of HAL_Init from stm32f4xx_hal.c
// Stripped down to NOT enable interrupts!

/* Configure Flash prefetch, Instruction cache, Data cache. These are according to the config
* in stm32f4xx_hal_conf.h which currently is:
* #define  PREFETCH_ENABLE              1  The prefetch will be enabled in SystemClock_Config(), depending
* on the used STM32F405/415/07/417 device: RevA (prefetch must be
* off) or RevZ (prefetch can be on/off)
* #define  INSTRUCTION_CACHE_ENABLE     1
* #define  DATA_CACHE_ENABLE            1
*/

// This overrides FLASH_ACR_ICEN above
#if (INSTRUCTION_CACHE_ENABLE != 0U)
__HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
#endif /* INSTRUCTION_CACHE_ENABLE */

// This overrides FLASH_ACR_DCEN above
#if (DATA_CACHE_ENABLE != 0U)
__HAL_FLASH_DATA_CACHE_ENABLE();
#endif /* DATA_CACHE_ENABLE */

// This setting is controlled from stm32f4xx_hal_conf.h which was edited to enable this 5/8/2021
#if (PREFETCH_ENABLE != 0U)
__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
#endif /* PREFETCH_ENABLE */

/* Set Interrupt Group Priority */
//HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
//HAL_InitTick(TICK_INT_PRIORITY);
/* Init the low level hardware */
//HAL_MspInit();

// This was in SystemClock_Config()
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

/* Configure the main internal regulator output voltage */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/* Initialise the CPU, AHB and APB busses clocks */
// This is a duplicate of stuff further above
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

/** Initializes the CPU, AHB and APB busses clocks
* These settings override stuff set earlier */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 42MHz - SPI2,SPI3,UART2,UART3,TIM2,3,4,5,6,7,12,13,15 etc
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; // 42MHz - UART1,UART6
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

// Stop IWDG if single stepping
__HAL_DBGMCU_FREEZE_IWDG();

// Initialise clocks. Without this one cannot set up any I/O pins etc.
B_HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_HSE, RCC_MCODIV_1);

/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #110 on: August 05, 2021, 05:13:41 pm »
It gets better.

Code: [Select]
/* Initialise the CPU, AHB and APB busses clocks */
/*
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
*/



The function called, HAL_RCC_OscConfig(), is:

Code: [Select]
/**
  * @brief  Initializes the RCC Oscillators according to the specified parameters in the
  *         RCC_OscInitTypeDef.
  * @param  RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
  *         contains the configuration information for the RCC Oscillators.
  * @note   The PLL is not disabled when used as system clock.
  * @note   Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
  *         supported by this API. User should request a transition to LSE Off
  *         first and then LSE On or LSE Bypass.
  * @note   Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
  *         supported by this API. User should request a transition to HSE Off
  *         first and then HSE On or HSE Bypass.
  * @retval HAL status
  */
__weak HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
{
  uint32_t tickstart;

  /* Check Null pointer */
  if(RCC_OscInitStruct == NULL)
  {
    return HAL_ERROR;
  }

  /* Check the parameters */
  assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
  /*------------------------------- HSE Configuration ------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
    /* When the HSE is used as system clock or clock source for PLL in these cases HSE will not disabled */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSE) ||\
      ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSE)))
    {
      if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
      {
        return HAL_ERROR;
      }
    }
    else
    {
      /* Set the new HSE configuration ---------------------------------------*/
      __HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);

      /* Check the HSE State */
      if((RCC_OscInitStruct->HSEState) != RCC_HSE_OFF)
      {
        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till HSE is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      else
      {
        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till HSE is bypassed or disabled */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
        {
          if((HAL_GetTick() - tickstart ) > HSE_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
  }
  /*----------------------------- HSI Configuration --------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
  {
    /* Check the parameters */
    assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
    assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));

    /* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
    if((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_HSI) ||\
      ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_CFGR_SWS_PLL) && ((RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) == RCC_PLLCFGR_PLLSRC_HSI)))
    {
      /* When HSI is used as system clock it will not disabled */
      if((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
      {
        return HAL_ERROR;
      }
      /* Otherwise, just the calibration is allowed */
      else
      {
        /* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
      }
    }
    else
    {
      /* Check the HSI State */
      if((RCC_OscInitStruct->HSIState)!= RCC_HSI_OFF)
      {
        /* Enable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_ENABLE();

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till HSI is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Adjusts the Internal High Speed oscillator (HSI) calibration value. */
        __HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
      }
      else
      {
        /* Disable the Internal High Speed oscillator (HSI). */
        __HAL_RCC_HSI_DISABLE();

        /* Get Start Tick*/
        tickstart = HAL_GetTick();

        /* Wait till HSI is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET)
        {
          if((HAL_GetTick() - tickstart ) > HSI_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
  }
  /*------------------------------ LSI Configuration -------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
  {
    /* Check the parameters */
    assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));

    /* Check the LSI State */
    if((RCC_OscInitStruct->LSIState)!= RCC_LSI_OFF)
    {
      /* Enable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_ENABLE();

      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSI is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET)
      {
        if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else
    {
      /* Disable the Internal Low Speed oscillator (LSI). */
      __HAL_RCC_LSI_DISABLE();

      /* Get Start Tick */
      tickstart = HAL_GetTick();

      /* Wait till LSI is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
      {
        if((HAL_GetTick() - tickstart ) > LSI_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
  }
  /*------------------------------ LSE Configuration -------------------------*/
  if(((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
  {
    FlagStatus       pwrclkchanged = RESET;

    /* Check the parameters */
    assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));

    /* Update LSE configuration in Backup Domain control register    */
    /* Requires to enable write access to Backup Domain of necessary */
    if(__HAL_RCC_PWR_IS_CLK_DISABLED())
    {
      __HAL_RCC_PWR_CLK_ENABLE();
      pwrclkchanged = SET;
    }

    if(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
    {
      /* Enable write access to Backup domain */
      SET_BIT(PWR->CR, PWR_CR_DBP);

      /* Wait for Backup domain Write protection disable */
      tickstart = HAL_GetTick();

      while(HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
      {
        if((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }

    /* Set the new LSE configuration -----------------------------------------*/
    __HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
    /* Check the LSE State */
    if((RCC_OscInitStruct->LSEState) != RCC_LSE_OFF)
    {
      /* Get Start Tick*/
      tickstart = HAL_GetTick();

      /* Wait till LSE is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
      {
        if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }
    else
    {
      /* Get Start Tick */
      tickstart = HAL_GetTick();

      /* Wait till LSE is ready */
      while(__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
      {
        if((HAL_GetTick() - tickstart ) > RCC_LSE_TIMEOUT_VALUE)
        {
          return HAL_TIMEOUT;
        }
      }
    }

    /* Restore clock configuration if changed */
    if(pwrclkchanged == SET)
    {
      __HAL_RCC_PWR_CLK_DISABLE();
    }
  }
  /*-------------------------------- PLL Configuration -----------------------*/
  /* Check the parameters */
  assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
  if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
  {
    /* Check if the PLL is used as system clock or not */
    if(__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL)
    {
      if((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
      {
        /* Check the parameters */
        assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
        assert_param(IS_RCC_PLLM_VALUE(RCC_OscInitStruct->PLL.PLLM));
        assert_param(IS_RCC_PLLN_VALUE(RCC_OscInitStruct->PLL.PLLN));
        assert_param(IS_RCC_PLLP_VALUE(RCC_OscInitStruct->PLL.PLLP));
        assert_param(IS_RCC_PLLQ_VALUE(RCC_OscInitStruct->PLL.PLLQ));

        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();

        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }

        /* Configure the main PLL clock source, multiplication and division factors. */
        WRITE_REG(RCC->PLLCFGR, (RCC_OscInitStruct->PLL.PLLSource                                            | \
                                 RCC_OscInitStruct->PLL.PLLM                                                 | \
                                 (RCC_OscInitStruct->PLL.PLLN << RCC_PLLCFGR_PLLN_Pos)             | \
                                 (((RCC_OscInitStruct->PLL.PLLP >> 1U) - 1U) << RCC_PLLCFGR_PLLP_Pos) | \
                                 (RCC_OscInitStruct->PLL.PLLQ << RCC_PLLCFGR_PLLQ_Pos)));
        /* Enable the main PLL. */
        __HAL_RCC_PLL_ENABLE();

        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
      else
      {
        /* Disable the main PLL. */
        __HAL_RCC_PLL_DISABLE();

        /* Get Start Tick */
        tickstart = HAL_GetTick();

        /* Wait till PLL is ready */
        while(__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
        {
          if((HAL_GetTick() - tickstart ) > PLL_TIMEOUT_VALUE)
          {
            return HAL_TIMEOUT;
          }
        }
      }
    }
    else
    {
      return HAL_ERROR;
    }
  }
  return HAL_OK;
}


which you can immediately see isn't going to work unless the 1kHz tick is running - for the timeouts.

So they are messing with PLL config and then using a function to set that up, which relies on interrupts already enabled!

Actually it evidently does work - because with the tick not running, none of the timeouts are implemented. The code still works but would not do anything useful (it would hang) if there really was an error.

But any error here is not going to produce anything which can output a useful error message, is it?
« Last Edit: August 05, 2021, 05:15:51 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline dkonigs

  • Regular Contributor
  • *
  • Posts: 107
  • Country: us
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #111 on: August 05, 2021, 06:34:47 pm »
When i open the last link, i see a red warning "cube will trash your code". It happened to me once. Then i discovered that the generated code contains markup for "user code" that stays protected from code generation.

As someone who loathes being forced to code within someone else's "guardrails," I've come up with an approach that lets me track and review what various CubeMX options do without trashing any code I actually care about:
  • Use CubeMX to generate a template project
  • Check that template project into its own private/local Git repository
  • Use that generated project as a basis for my own project, but organize the code in a way that actually makes sense to me and rewrite all the "generated" code so its structure doesn't make me want to gouge my eyes out. Don't put it in the same place.
  • Develop as normal off my project's source tree
  • Whenever I want to change something configured in Cube-land, make the change, regenerate the output, and use the power of Git to see what actually changed on the pristine generated dump. Migrate any of these changes into my own code when/if they make sense.

This way I can keep a revision history of CubeMX-driven changes, which is independent from (and does not directly affect) my main project.

The ability to turn any random directory on your computer into a "version controlled repository" is a huge benefit of systems like Git that I use quite frequently.
 
The following users thanked this post: thm_w, newbrain, harerod

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26906
  • Country: nl
    • NCT Developments
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #112 on: August 05, 2021, 06:49:59 pm »
When i open the last link, i see a red warning "cube will trash your code". It happened to me once. Then i discovered that the generated code contains markup for "user code" that stays protected from code generation.

As someone who loathes being forced to code within someone else's "guardrails," I've come up with an approach that lets me track and review what various CubeMX options do without trashing any code I actually care about:
  • Use CubeMX to generate a template project
  • Check that template project into its own private/local Git repository
  • Use that generated project as a basis for my own project, but organize the code in a way that actually makes sense to me and rewrite all the "generated" code so its structure doesn't make me want to gouge my eyes out. Don't put it in the same place.
  • Develop as normal off my project's source tree
  • Whenever I want to change something configured in Cube-land, make the change, regenerate the output, and use the power of Git to see what actually changed on the pristine generated dump. Migrate any of these changes into my own code when/if they make sense.

This way I can keep a revision history of CubeMX-driven changes, which is independent from (and does not directly affect) my main project.

The ability to turn any random directory on your computer into a "version controlled repository" is a huge benefit of systems like Git that I use quite frequently.
I agree with this. I haven't used code generating tools for a very long time but when I did, this was my approach as well. Just use the generated code as a template and go from there.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #113 on: August 05, 2021, 08:47:36 pm »
Yes; clearly this is the way to use that tool. Generate the code and then clean it up. I have just spent a few hours condensing the above garbage into about 5% of the amount of code. Takes a while to step through it and verify the register bits though, to make sure nothing got broken.

I think two different people worked in the config code. One of them wrote in this style

Code: [Select]
/* Enable high performance mode, System frequency up to 168 MHz */
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
PWR->CR |= PWR_CR_PMODE;

/* HCLK = SYSCLK / 1*/
RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE2_DIV4;
/* PCLK1 = HCLK / 4 i.e. 42MHz */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;

// PLL Parameters
// These produce a 168MHz CPU clock (336/2) and a 48MHz USB clock (336/7)
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      25
#define PLL_N      336
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2
/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7

/* Configure the main PLL */
RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
               (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);
/* Enable the main PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till the main PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0) {}

/* Configure Flash prefetch, Instruction cache, Data cache and wait state */
FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;

/* Select the main PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= RCC_CFGR_SW_PLL;

/* Wait till the main PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL) {}

and the other one (the auto generated code I think; I sort of inherited this project) in this style

Code: [Select]
/* Initialise the CPU, AHB and APB busses clocks */
/*
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
// This function requires interrupts (tick) running for the various timeouts, which is
// nonsense for something setting up the basic clocks!
HAL_RCC_OscConfig(&RCC_OscInitStruct);
*/

/** Initializes the CPU, AHB and APB busses clocks
/*
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; // 42MHz - SPI2,SPI3,UART2,UART3,TIM2,3,4,5,6,7,12,13,15 etc
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4; // 42MHz - UART1,UART6
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
*/


and the second lot (HAL_RCC_OscConfig()) is a massive long function which must have been written by a complete numpty (but one who has just come off a C course, because he is heavily into structs) who doesn't "get" that there isn't going to be a nice 1kHz timer tick even before you have started configuring the PLL and the various clocks!

I had a load of fun at one point, with all the ticks running about 10x too fast. I found that there is a global variable, SystemCoreClock, which is the CPU clock in Hz (168000000). It is referenced for timers all over the place in the HAL code. It is calculated using a convoluted procedure which obviously requires the xtal freq to be given somewhere, and from that it reads various registers to get the division values and work out the CPU clock backwards. So now I just have SystemCoreClock=168000000; :)
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #114 on: August 05, 2021, 08:49:26 pm »
Yes same here and replace many utils with my own code as well as extend some of the strange fixed size protocol handling functions with my own variable size ones.
 

Offline typematrix

  • Contributor
  • Posts: 24
  • Country: ie
    • Github
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #115 on: August 06, 2021, 01:49:22 am »
Just started using it [STM32cube IDE] , I don't know if its a bug or a feature but it why does make a main.c file instead of a main.cpp for a C++ project Every time you click "generate code". Is this a bug? If you rename it it will rename it back when you regenerate.
Is there a setting somewhere to change this behaviour?
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #116 on: August 06, 2021, 07:16:16 am »
Don't know, never had a use for C++ for embedded work, and never will in my lifetime.
 

Offline AaronLee

  • Regular Contributor
  • *
  • Posts: 229
  • Country: kr
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #117 on: August 06, 2021, 08:04:14 am »
Don't know, never had a use for C++ for embedded work, and never will in my lifetime.

Ditto. With the exception of C++ style comments, which is pretty much standard these days on all C compilers, I have zero use for C++ for embedded use. And if I ever had to take over anyone's project and it used C++, the first thing I'd do is convert it to C. Way too many chances for the C++ code to eat up memory unnecessarily and waste my time modifying the code so that it doesn't.
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #118 on: August 06, 2021, 08:10:39 am »
The auto generated startup .s file has some initialisation for constructors etc. It seems to generate this stuff anyway.
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5898
  • Country: es
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #119 on: August 06, 2021, 11:13:02 am »
For IDE-specific questions better ask here, they usually help a lot.:
https://community.st.com/

About the matter of this thread. Do you really love setting a specific editor, debugger, linker, compiler, making the makefile from scratch and glueing everything together? My head hurts just thinking on it.
While a new project will take to youa while, it takes seconds in Cube IDE. Not to mention if you have to install and configure everything from zero.
Not that many bugs, really.
The're a few with the code builder, ex. syscalls.c, sysmem.c, startup_xxx.s won't be regenerated if deleted, neither the linker script.
Not really a bug, just don't delete your files  :-DD
A very annoying one is the SWV data plot, when you set all the 4 data traces usually one of them is not updated corrrectly.
After running it for more than 30s it will slow down to the point it's unusable, requiring erasing the data plot history.
A true bug happened when you copied the project, renamed the .ioc file and regenerated the code. CubeMx would wipe the Src contents of the original project you copied it from.

Other than that, I find it to be pretty solid. Most bugs were my fault due unawareness or making mistakes.
And due their really bad documentaion.

« Last Edit: August 06, 2021, 11:17:10 am by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 
The following users thanked this post: boB

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8169
  • Country: fi
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #120 on: August 06, 2021, 12:21:21 pm »
I have no idea what "setting a specific linker and compiler" even means. Maybe it's the glue you mentioned, too much and I'm not surprised your head is hurting?

What configuration? I have never configured any of the GNU tools, just installed.

It seems you have some very weird assumptions how a normal firmware build environment works as you have never used one, and assume it must be colossally difficult.
« Last Edit: August 06, 2021, 12:23:25 pm by Siwastaja »
 

Offline harerod

  • Frequent Contributor
  • **
  • Posts: 449
  • Country: de
  • ee - digital & analog
    • My services:
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #121 on: August 06, 2021, 01:07:01 pm »
...
As someone who loathes being forced to code within someone else's "guardrails," I've come up with an approach that lets me track and review what various CubeMX options do without trashing any code I actually care about:

    Use CubeMX to generate a template project
    Check that template project into its own private/local Git repository
    Use that generated project as a basis for my own project, but organize the code in a way that actually makes sense to me and rewrite all the "generated" code so its structure doesn't make me want to gouge my eyes out. Don't put it in the same place.
    Develop as normal off my project's source tree
    Whenever I want to change something configured in Cube-land, make the change, regenerate the output, and use the power of Git to see what actually changed on the pristine generated dump. Migrate any of these changes into my own code when/if they make sense.


This way I can keep a revision history of CubeMX-driven changes, which is independent from (and does not directly affect) my main project.

The ability to turn any random directory on your computer into a "version controlled repository" is a huge benefit of systems like Git that I use quite frequently.

dkonigs, thanks for sharing your work-around. After ST-support confirmed that the "user-code-section" are hardcoded into CubeIDE, I devised a similar scheme. Before entering the codegenerator, which happens rarely after initially setting up the project, I do a check-in to GIT. After the code-generator run, I do a diff and re-apply my patches to the libraries. Annoying, but feasible.


Although I have heard bad things about ST-support, I can only share my most recent experience, when I filed a bug report with ST "online.support@st.com" last week:

Hi,
I just spent several hours debugging an issue with HAL-DeInit.

STM32Cube STM32F1 1.8.3 / 1.8.2

It turned out that stm32f1xx_hal_rcc.h has a typo in
/** @defgroup RCC_APB1_Force_Release_Reset APB1 Force Release Reset * @brief Force or release APB1 peripheral reset. * @{ */
//#define __HAL_RCC_APB1_FORCE_RESET() (RCC->APB2RSTR = 0xFFFFFFFFU) // <- original
#define __HAL_RCC_APB1_FORCE_RESET() (RCC->APB1RSTR = 0xFFFFFFFFU) // MAH2107281301 BUGFIX

I would appreciate it if you could fix that ASAP. If that patch is present in 1.8.4, my apologies, but I can't switch libraries for that project.

Much obliged,
 harerod
 
 
First response, within a day:

Dear Harerod,
Below case has been updated by ST Support.

Case#: 00137742
Subject: Bug in HAL - stm32f1xx_hal_rcc.h
Status: Working

Description:
We have escalated your inquiry to our applications team for further support.
 
Regards,
...


Five days later:

Dear Harerod,
Below case has been updated by ST Support.

Case#: 00137742
Subject: Bug in HAL - stm32f1xx_hal_rcc.h
Status: Solution Proposed

Description: Dear customer, Thank You for notifying us. I reported this typo and it should be fixed as soon as possible. We apologize for any inconvenience. Best regards, ST MCU Support Team

Please visit ST Customer Support Portal for further information.
Link to access the case:
...

Best regards,
ST Customer Support
 

Offline peter-hTopic starter

  • Super Contributor
  • ***
  • Posts: 3694
  • Country: gb
  • Doing electronics since the 1960s...
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #122 on: August 06, 2021, 01:48:46 pm »
"For IDE-specific questions better ask here, they usually help a lot.:
https://community.st.com/"

I think everybody does that, which is why most questions posted there attract zero answers :)

Yes; ST do seem to prefer dealing with support tickets, and in my limited experience they do respond. I got a response out of them to my PCLK2 divider / ethernet bug thing, which needed somebody pretty good to have a dig around.

Incidentally, does anyone know what exactly this does:

In linkfile:

Code: [Select]

.preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array*))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH


Note the above ends up in FLASH, not DATA or BSS.

In startup:

Code: [Select]
LoopCopyDataInit:
  ldr  r0, =_sdata
  ldr  r3, =_edata
  adds  r2, r0, r1
  cmp  r2, r3
  bcc  CopyDataInit
  ldr  r2, =_sbss
  b  LoopFillZerobss
/* Zero fill the bss segment. */ 
FillZerobss:
  movs  r3, #0
  str  r3, [r2], #4
   
LoopFillZerobss:
  ldr  r3, = _ebss
  cmp  r2, r3
  bcc  FillZerobss

/* Call the clock system intitialization function.*/
  bl  SystemInit   
/* Call static constructors */
 bl __libc_init_array
/* Call the application's entry point.*/
  bl  main
  bx  lr   

A large number of people have been asking what __libc_init_array does and there are countless threads on it, but nobody knows whether any ST libs need it. I took it out quite early on in the belief that this stuff is for C++ only, and everything seems to have worked. I am told it may do some initialisation for stuff like memset, printf, etc. Does anyone know, in the ST 32F context?

Also SystemInit() is a function in main.c which sets up various things like the PLL, but then other code later on overrides that setting. None of this has any obvious point; it looks like different people were working on this stuff and didn't talk to each other. But it could be that they wanted some initialisation before __libc_init_array()...
« Last Edit: August 06, 2021, 01:51:33 pm by peter-h »
Z80 Z180 Z280 Z8 S8 8031 8051 H8/300 H8/500 80x86 90S1200 32F417
 

Offline harerod

  • Frequent Contributor
  • **
  • Posts: 449
  • Country: de
  • ee - digital & analog
    • My services:
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #123 on: August 06, 2021, 01:53:33 pm »
...
The're a few with the code builder, ex. syscalls.c, sysmem.c, startup_xxx.s won't be regenerated if deleted, neither the linker script.
...

I would call that a feature, especially when it comes to the linker scripts. A standard production project might have several different build configurations and memory layouts.
Three sets for Debug and Release each:
- linker file for standalone application, starting at FLASH begin
- linker file for bootloader, starting at FLASH begin
- linker file for application, starting at application base address FLASH, being called by the bootloader

In that case, the memory layout for the application looks like this:
MEMORY
{
  CCMRAM    (rw)    : ORIGIN = 0x10000000,   LENGTH =  64K     /* CCM File System          */
  RAM       (xrw)   : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASHBL   (rx)    : ORIGIN = 0x8000000,    LENGTH = 128K     /* bootloader flash memory  */
  FLASHAPP  (rx)    : ORIGIN = 0x8020000,    LENGTH = 256K     /* application flash memory */
  FLASHDATA (rx)    : ORIGIN = 0x8060000,    LENGTH = 640K     /* Flash File System        */
}
 

Offline DavidAlfa

  • Super Contributor
  • ***
  • Posts: 5898
  • Country: es
Re: Is ST Cube IDE a piece of buggy crap?
« Reply #124 on: August 06, 2021, 02:27:57 pm »
Sure, but in that case you copy/rename the linker script and adjust the linker settings in the build profile.
Otherwise, a code generator should do exactly that. You should be able to mess everything up (except user code) and let it rebuild the project into fully working state.

In fact you can adjust the heap and stack sizes, and it'll change the linker script.
Although it fails sometimes and doesn't edit it.

Time ago sysmem.c and syscalls.c dissapeared from my project, and I didn't notice until months later (The files were already gone when I started using git).
After adding some new mallocs the system started to crash in very random ways. I realized I could malloc 4 petaBytes if I wanted on the 16KB RAM device.
Took me days to find out the cause. Looking at the sbrk function assembly, no checks were made!
It seems the sbrk function in sysmem.c overrides the generic one, so if you delete it there won't be any errors at compile time.
These things you learn at the beginning and never forget!  :D

Maybe it's the glue you mentioned, too much

Wtf are you saying? I was the solvent I used to clean the boards :-DD
Sure, there's a lot I'm unaware of.
I coded some C in Linux, but it's a PITA when there's no code assist.
I ended using the same thing: Eclipse ide.
Making a Makefile is an out-of-the-world thing for me.
For 5 files it's ok, but when you have 20 folders, subfolders... it's a problem.
For sure, I might be missing something, doing it in the wrong, hardest way :D
« Last Edit: August 06, 2021, 02:43:15 pm by DavidAlfa »
Hantek DSO2x1x            Drive        FAQ          DON'T BUY HANTEK! (Aka HALF-MADE)
Stm32 Soldering FW      Forum      Github      Donate
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf