cancel
Showing results for 
Search instead for 
Did you mean: 

SPL to CubeF4 conversion issues

ariel2
Associate II
Posted on March 27, 2015 at 12:22

I need to integrate an old code written using the Standard Peripheral Library to a new (big)project that's using CubeF4.

As easy as it sounds I can't find any commonality between the libs..

1. Is there any documentation to help with migration?

2. Is there a way to access the ''old'' SPL function / easily make them live side by side?

3. I can find implementation to basic functions, like:

The following SPL function TIM_ARRPreloadConfig() configures TIM_CR1_ARPE bit in CR1 register.

Yet I was unable to find where ARR is configured in the new HAL lib.

What do you suggest, how should I attack this?

(Please ignore if it�s an inappropriate offer, but) I am willing to pay for the conversion assistance.

Below is the code, there is also SPI and DMA init calls.

///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    /// Init Timers for the DMA

    ///-----------------------------------------------------------------

    TIM_TimeBaseInitTypeDef timerInitStructure;

    TIM_BDTRInitTypeDef timer_BDTRInitStruct;

    ///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    /// Setup TIM4 Timer as master clock which is used as clock source

    /// for timers TIM1, TIM2, TIM3, TIM5 & TIM8. TIM4@84MHz. In this

    /// way all DMA<->SPI's are in sync

    /// All DMA and SPI TIM's must have same ARR register value in order

    /// for them to be in sync. 

    ///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);                // enable TIM3

    TIM_TimeBaseStructInit(&timerInitStructure);                        // fill structure with default values

    timerInitStructure.TIM_Prescaler = (TIM_PRESCALER) - 0x0001;        // set TIM1 counting prescaler to 1 (PSC register)

    timerInitStructure.TIM_Period = TIM4_PERIOD;                        // reload value set to 1 -> 21MHz clock (ARR register)

    TIM_TimeBaseInit(TIM4, &timerInitStructure);                        // Init timer with structure

    TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);            // set update request source to generate interupt or DMA request (CR1->URS bit)

    TIM_ARRPreloadConfig(TIM4,ENABLE);                                  // set auto-reload preload to enable (CR1->ARPE)

    TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);               // set master mode selection to update (CR2->MMS)

    TIM_GenerateEvent(TIM4, TIM_EventSource_Update);                    // set update generation (EGR->UG)

    TIM_Cmd(TIM4, ENABLE);                                             

    ///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    /// Setup TIM2 as slave timer clocked by TIM4. TIM2 triggers DMA

    /// which transfers channel selection data through SPI3.

    /// TIM2 CC4 with 4us is used for the CONV

    /// TIM2 CC4 with 4us is used as trigger for transmission of channel

    /// selection data with 50 us period

    ///wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);                // enable TIM2

    TIM_TimeBaseStructInit(&timerInitStructure);

    timerInitStructure.TIM_Prescaler = (TIM_PRESCALER) - 0x0001;        // set TIM2 counting prescaler to 1 (PSC register)

    timerInitStructure.TIM_Period = TIM2_PERIOD;                        // 42MHz/1 = 42MHz -> count each 1/42MHz (ARR register)

    TIM_TimeBaseInit(TIM2, &timerInitStructure);

    TIM_SelectSlaveMode(TIM2,TIM_SlaveMode_External1);                  // Set slave mode to external clock mode TIM4 (SMCR->SMS)

    TIM_SelectInputTrigger(TIM2,TIM_TS_ITR3);                           // Set internal triger to TIM4 (SMCR->TS)

    TIM_UpdateRequestConfig(TIM2, TIM_UpdateSource_Regular);            // set update request source to generate interupt or DMA request (CR1->URS bit)

    TIM_ARRPreloadConfig(TIM2,ENABLE);                                  // set auto-reload preload to enable (CR1->ARPE)

    TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_OC4Ref);               // trigger output (TRGO) on CC4 (CR2->MMS)

    TIM_SetCompare4(TIM2,0x00A8);                                       // duty cycle for the PWM set to 168 = 4us (CCR4 register)

    TIM_OC4PreloadConfig(TIM2,TIM_OCPreload_Enable);                    // enable OC4PE preload mode (CCMR2->OC4PE)

    TIM_ForcedOC4Config(TIM2,TIM_OCMode_PWM1);                          // set PWM1 mod (CCMR2->OC4M)

    TIM_OC4PolarityConfig(TIM2,TIM_OCPolarity_High);                    // set pulse polarity to active high (CCER->CC4P)

    TIM2->CCER |= (TIM_CCER_CC4E);                                      // enable capture compare mode

    TIM_DMACmd(TIM2,TIM_DMA_CC4,ENABLE);                                // enable DMA request on capture compare CC4 event DIER->CC4DE

    TIM_GenerateEvent(TIM2, TIM_EventSource_Update);

    TIM_Cmd(TIM2, ENABLE);

...

#cube #spl
4 REPLIES 4
Posted on March 27, 2015 at 12:38

As easy as it sounds I can't find any commonality between the libs..

 

1. Is there any documentation to help with migration?

They use a whole different paradigm, so it's about as easy/comfortable as rotating your head 90 degrees in the vertical plane.

Step 1 in your process is to throw away your original code, and rewrite it completely. So the document is pretty short and concise.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ariel2
Associate II
Posted on March 27, 2015 at 15:09

Thank you clive1!

Sadly, I had the feeling that would be the reply I'd get 😉

Any advice regarding 2 and 3?

May I ask what do you use? 

Posted on March 27, 2015 at 16:51

Using the Standard Peripheral Library, on several reasonably large projects, across a couple of STM32 families. Been using the parts since ~2006, and prior to that the STR7 and STR9 families, with similar library interfaces. The SPL is solid and stable, and I have zero plans to migrate any of my code base. I have and do use other chips from other vendors. I try to build platform agnostic code by abstracting the platform specific stuff into small modules.

There are certainly plenty of large STM32 customers, with large code bases, who also won't migrate, and there's been plenty of push back from a lot of the professional members here on the forum. Originally the SPL was marked as EOL, but that's been walked back since then. The SPL is solid as it is, you'd only need ''support'' to get into new chips. ST has never provided support for the SPL at the level it has for HAL/Cube, but it's not as if the library is going to get bit rot or be unfixable in the future if you do happen upon a bug.

If I were attacking (2), I'd probably look to partition the code at a library/object level, and then address any namespace/linkage issues with custom tools.

For (3) I think the suggested workarounds if you can't find equivalent functionality is to code register level equivalents either as macros, or inline functions. I believe there are HAL level development efforts to address these things.

You'll need to decide how compelling the features/function of HAL/Cube are compared to the level of commitment it will require to migrate to them. Where I'm at is that I could more readily take my code to a different vendor platform.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ariel2
Associate II
Posted on March 27, 2015 at 19:49

Thank you again Clive.

The reason I started the main project using the new HAL was due to the nice integration with RTOS and other libs which make it easy to run forward with the actual coding (or so I thought).

I'd probably go with option 2 for now, despite the overhead.

I'll write a small app that will simply add SPL_ to all functions, stucks, macros, .. rename everything! (under the original SPL)