cancel
Showing results for 
Search instead for 
Did you mean: 

Move application FW into library (*.lib) for outsourcing

Nix Wayne
Associate III

Posted on June 14, 2018 at 14:53

I developed firmware for STM32F072 and it implements composite USB and uses some peripherals such as ADC and DMA, TIM1 and I2C. I can generate HEX and load it into MCU and device is ready for the client. All fine.

Well my client expressed wish to do some manual development on their own in just particular part of my device. Some customised filtering of ADC data to be more specific.

I don't really want to expose my code although it's not really a rocket science but it's my intelectual property and I put effort, time and resources into it. So I got two ideas.

1. Create library (*.lib) for them so they can use library and add some of their functionality without touching/seeing my code. I did that and I succesfully created *.lib.

I exported two main functions to use... one is Init() other is Processing(). So the client can put into their project into their main() something like this...

int main(void)
{
 Init(Callback1, Callback2);
 while (1)
 {
 Processing();
 }
}
int Callback1(uint8_t * data, uint32_t length)
{
 // client do some stuff here
}
int Callback2(uint8_t * data, uint32_t length)
{
 // client do some stuff here
}
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

I tried it and at first it didn't work so I found out that there are missing _IRQ handlers... so I made a wrapper that redirects IRQ handlers called from user code into handlers in my library.

Well this works... almost... USB device is enumerating and descriptors are transfered ok except string descriptors. I used Thesycon USB descriptor dumper and I can see there is error code for string descriptors. All other descriptors (Device, Interface, Configuration etc... are fine and properly set)

String Descriptor Table
--------------------------------
Index LANGID String
0x00 0x0000 
0x01 0x0000 Request failed with 0x0000001F
0x02 0x0000 Request failed with 0x0000001F
0x03 0x0000 Request failed with 0x0000001F
0x04 0x0000 Request failed with 0x0000001F
0x05 0x0000 Request failed with 0x0000001F
0x06 0x0000 Request failed with 0x0000001F
0x07 0x0000 Request failed with 0x0000001F�?�?�?�?�?�?�?�?�?�?�?

To sumarize... Client calls SystemInit in Clients project to setup clocks, then Init from library to setup peripheral. I also made wrappers for ADC, USB and DMA IRQ handlers so client handlers call code from handlers in my lib. So my question is if is there something else I am missing? I just don't understand why USB enumerates fine but it's unable to get string descriptors. I

2. HEX file - similar to Nordic's softdevice - I haven't tried this yet but it looks a little bit more complex to make. The ideaa is that I provide hex file of my firmware and client creates their own project which is then loaded into specified region of flash and uses specified region of ram. However there needs to be done some kind of communication between both using __SVC calls or similar etc... Does anybody has an experiences with this? Well I already have two hexes on device... one is custom bootloader and second one is application FW... so I have some experiences with loading addresses from memory and executing code from application FW.... but not in a way that softdevice use...

Thank you for the answers and any help is much appreciated!

p.s. I am using HAL drivers.

3 REPLIES 3
Posted on June 14, 2018 at 15:11

Does it work outside the library construct?

SystemInit() fiddling with HSE?

If you have something that works already/previously, supply customer with working system_stm32f0xx.c / startup_stm32f0xx.s templates

I prefer that SystemInit() and primary clocks/PLL be set up according to CMSIS model *before* main() is entered, and not fiddled with again. Not a fan of the HAL/CubeMX tendency to use SystemClock_Config()

Have client just set up ADC clocks and pins, and not interfere with other clocks and functionality.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Nix Wayne
Associate III
Posted on June 14, 2018 at 15:28

Yes if I build HEX from sources and I load it into flashit works perfectly.

So my customers project (I am preparing for him) file structure looks like:

ProjectLibrary.lib
ProjectLibrary.h
main.c
startup_stm32f072xb.s
system_stm32f0xx.c
stm32f0xx_it.c�?�?�?�?�?�?�?�?�?�?�?�?

So ProjectLibrary.lib is my library (it has all the stuff/functionality I explained in a post above) acompanied with H file with function prototypes Init and Processing.

main.c is customers entry point function main.

startup_stm32f072xb.s is standard startup file, no modifications... it calls SystemInit() in system_stm32f0xx.c to setup clocks. And after that it calls main().

In stm32f0xx_it.c are IRQ handlers which in client's case are redirected to ones in my ProjectLibrary.

I am preparing this for the client... so he hasn't been doing any development yet.

Posted on June 14, 2018 at 16:09

I solved it.

I forgot to include stm32f0xx_hal_msp.c into client's project. This file includes implementation of HAL_MspInit which enables syscfg clock. And clocks for ADC.... clocks... yes... clocks... as long as there is clock everybody is happy.

Additionaly .... So my understanding is that if there is function callback defined as [WEAK] it should have implementation outside the library otherwise it won't be called. There is function inside library which is calling another function which is [WEAK] and although it's implementation is present in library it won't be called. Called will be implementation outside the library.

Is this correct?

It's working now so my advice to anyone else doing similar thing would be to go through these steps when putting their application into library:

1. Make API calls for different routines needed to run application in library. Such as in my case Init(callback1, callback2) and Processing for the while loop. (if neccessary)

2. Make a wrapper for IRQ handlers that redirects them to handlers in a library.

3. Make implementation of [WEAK] callbacks/functions in user code not in library.

4. Add standard files (non-modified) to project: startup_stm32f072xb.s, system_stm32f0xx.c

5. Number 2 and 3 can be more or less solved by adding proper files to the applications such as stm32f0xx_hal_msp.c. That file includes implementation of [WEAK] functions. It's also non-modified.

6. Add stm_32f0xx_it.cwhich has redirects for IRQHandlers. It's a wrapper just to redirect calls to handlers in library. In my case I juse exported functions such as MyLib_USBIrqHandler()... and inside that file I make call to that function.

Thanks

Turvey.Clive.002

for clocks idea... as soon as I started following the call stack of clock configuration I noticed '[WEAK] issue'.