Porting to STM32L476Discovery/LimiFrog

Discussion and questions about boards that can run MicroPython but don't have a dedicated forum.
Target audience: Everyone interested in running MicroPython on other hardware.
User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Porting to STM32L476Discovery/LimiFrog

Post by badi » Sun Jan 24, 2016 1:47 pm

Hello

I supported the LimiFrog Kickstarter a while ago:
https://www.kickstarter.com/projects/76 ... ot-and-muc
http://www.limifrog.io/
http://forum.micropython.org/viewtopic.php?f=12&t=913
As Xavier, who runs this project, ask for help porting Micropython to this HW, I answered him, that I'll have a look at it.

As the HW is not yet available (coming end of February) I use a STM32L476 Discovery kit for development in a first step:
http://www.st.com/web/en/catalog/tools/PF261635

As this projects uses an other MCU Series of STM (STM32F4->STM32L4) which is optimized for low power consumption, there is a difference in the periphery of the Cortex M4. To port the application code (STM32F4->STM32L4) STM wrote an Application note (DM00144612):
http://www.st.com/st-web-ui/static/acti ... pe=keyword
so there will be some effort for porting the SW to this new platform (see Table 4 of the mentioned document). For example the dma/I2C/Flash is not compatible between the two series of MCU HAL.

(STMicro produced as well a youtube video (mainly for PR purpose which shows no problem, but mentions what must be changed):
https://www.youtube.com/watch?v=YU4jivUZJm8)

For the port, I propose following proceeding:
  1. Introduce "l4" Hal in

    Code: Select all

    stmhal/hal/
  2. Add board support files in

    Code: Select all

    stmhal/boards/STM32L476DISC
  3. Add processor descriptions in

    Code: Select all

    stmhal/cmsis/devinc
  4. Added linkerscript and alternate function pin definitions for STM32L476 in

    Code: Select all

    stmhal/boards
  5. Adapt code in

    Code: Select all

    stmhal
    to match the difference in HAL access as mentioned above.
  6. Add board support files for LimiFrog in

    Code: Select all

    stmhal/boards/LIMIFROG
    when there is HW available.
The Realization will take place at my repo (https://github.com/tobbad/micropython/t ... ntegration).

Step 5 needs some work (Who else is interested in supporting?).

For the support of the L4 series I see different ways to go:
  • Rename code files in stmhal to MCU specific name (eg. dma.c - dmaf4.c) and modify makefile to include the MCU series specific code. The cons is that there will be duplicated code in the two dma??.c files which I dislike!
  • Working with #defines in the existing code (eg. dma.c) which will not look nice in the source, but is maybe a quick solution. But this code must later be refactored as described in the next point.
  • Refactor related code (eg. dma.c) to MCU series specific code (eg. dmaf/l4.c) and common code (eg. dma.c) and make an abstract interface to the other modules. (probably the best solution but probably needs more involvement of core developers)
Xavier told, that the guy did a minimal port up to now will cleanup his stuff in near future. Xavier offered to send me a zip with this code which I will probably put in an other branch of my repo (limifrog_minimal) and include in my branch (stm32l476discovery_integration).

I am setting up this topic to get guidelines/ideas (beside the general ones at https://github.com/micropython/micropyt ... Guidelines) how this new series code should be introduced into the micropython repo. I am looking forward to get some feedback. Further I would like to collect the information of that port in this thread.
Last edited by badi on Thu Mar 03, 2016 8:15 am, edited 1 time in total.
badi

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Porting to STM32L476Discovery/LimiFrog

Post by dhylands » Sun Jan 24, 2016 7:04 pm

badi wrote:
  1. Introduce "l4" Hal in

    Code: Select all

    stmhal/hal/
  2. Add board support files in

    Code: Select all

    stmhal/boards/STM32L476DISC
  3. Add processor descriptions in

    Code: Select all

    stmhal/cmsis/devinc
  4. Added linkerscript and alternate function pin definitions for STM32L476 in

    Code: Select all

    stmhal/boards
  5. Adapt code in

    Code: Select all

    stmhal
    to match the difference in HAL access as mentioned above.
  6. Add board support files for LimiFrog in

    Code: Select all

    stmhal/boards/LIMIFROG
    when there is HW available.
Steps 1-4 are realized in https://github.com/tobbad/micropython/t ... ntegration.
We should only need a new linkerscript and af file if they'll actually be different from one of the existing ones.
  • Rename code files in stmhal to MCU specific name (eg. dma.c - dmaf4.c) and modify makefile to include the MCU series specific code. The cons is that there will be duplicated code in the two dma??.c files which I dislike!
  • Working with #defines in the existing code (eg. dma.c) which will not look nice in the source, but is maybe a quick solution. But this code must later be refactored as described in the next point.
  • Refactor related code (eg. dma.c) to MCU series specific code (eg. dmaf/l4.c) and common code (eg. dma.c) and make an abstract interface to the other modules. (probably the best solution but probably needs more involvement of core developers)
I understand that the underlying peripherals might be different. Is the HAL API different too? The stuff thats in dma.c now looks pretty generic.

User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Re: Porting to STM32L476Discovery/LimiFrog

Post by badi » Mon Jan 25, 2016 9:49 am

We should only need a new linkerscript and af file if they'll actually be different from one of the existing ones.
  1. ld-script: I diff-ed the ld-files and there is no other processor with 1M Flash@0x08000000, no SDRAM, 96kByte@0x20000000 no CCMRAM (Closest is probably STM32F405.
  2. af-File (eg. stm32l476 has no timer 9,10,11,12,13,14 but they introduced TIM15, TIM16 and TIM17.
Of course LimiFrog will reuse the newly introduced ld/af files.
I understand that the underlying peripherals might be different. Is the HAL API different too? The stuff thats in dma.c now looks pretty generic.
Have a look at table 4 of http://www.st.com/st-web-ui/static/acti ... pe=keyword and dma related table 6 in the mentioned document. They renamed Streams to channel and Channel to Request which as well must be reflected in the call to the function dma_init:

Code: Select all

void dma_init(DMA_HandleTypeDef *dma, DMA_Stream_TypeDef *dma_stream, const DMA_InitTypeDef *dma_init, uint32_t dma_channel, uint32_t direction, void *data);
must be changed to

Code: Select all

void dma_init(DMA_HandleTypeDef *dma, DMA_Channel_TypeDef *dma_channel, const DMA_InitTypeDef *dma_init, uint32_t dma_request, uint32_t direction, void *data);
The interrupt are as well different mapped. For example in timer.c i had to adapt pyb_timer_make_new:

Code: Select all

    switch (tim->tim_id) {
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
        case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM10_IRQn; break;
#elif defined(MCU_SERIES_L4)
        case 1: tim->tim.Instance = TIM1; tim->irqn = TIM1_UP_TIM16_IRQn; break;
#endif
as the IRQs are different mapped. The ugliness of the STM-hal library can be seen by the fact that I had to change in mphalport.c

Code: Select all

    #ifdef __GPIOK_CLK_ENABLE
    } else if (gpio == GPIOK) {
        __GPIOK_CLK_ENABLE();
    #endif
to

Code: Select all

    #ifdef GPIOK
    } else if (gpio == GPIOK) {
        __GPIOK_CLK_ENABLE();
    #endif
as __GPIOK_CLK_ENABLE is defined the stm32_hal_legacy.h, but the stm32l476 has no GPIOK...

Of course, some (but not all) of the incompatibility may arise because I use the latest STM32L4 HAL, but I found no way to download older versions.
badi

User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Re: Porting to STM32L476Discovery/LimiFrog

Post by badi » Fri Feb 12, 2016 5:55 pm

The code now nearly compiles for the L4 discovery platform. There is only on little issue: At the final linking I get an error :

Code: Select all

build-STM32L476DISC/hal/l4/src/stm32l4xx_hal_uart.o: In function `UART_SetConfig':
/home/badi/projekte/sw/embedded/application/micropython/stmhal//hal/l4/src/stm32l4xx_hal_uart.c:1595: undefined reference to `__aeabi_uldivmod'
/home/badi/projekte/sw/embedded/application/micropython/stmhal//hal/l4/src/stm32l4xx_hal_uart.c:1601: undefined reference to `__aeabi_uldivmod'

as this function uses a 64bit by 64 bit division which is not defined in micropython. If this is fixed I can start debuging the port.

Can anyone tell me how I should resolve this issue in a micropythonic way?
badi

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Porting to STM32L476Discovery/LimiFrog

Post by dhylands » Sat Feb 13, 2016 7:03 am

The function __aeabi_uldivmod is part of libgcc

Normally, you can so something like this to get the name of the libgcc library to use:

Code: Select all

LIBGCC = LIBGCC = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
But the only libgcc that is included with the compiler that has FPU support, also uses vairable sized enums.

The -mabi=aapcs-linux option is what causes fixed sized enums to be used. If you change it to -mabi=aapcs then everything will be compiled to use variable sized enums, and you can use:

Code: Select all

LIBS += $(LIBGCC)
to get libgcc linked in.

I verified that causes micropython to link properly, but didn't verify that it actually runs all of the tests fine.

I think that this type of change would require an OK from Damien.

Another option is to modify the appropriate HAL file to not need to perform a 64 by 64 divide.

User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Re: Porting to STM32L476Discovery/LimiFrog

Post by badi » Sun Feb 14, 2016 5:40 pm

Thank you very much. I'll finish the port (add Flash support, I2C Baudrate calculation , Clk enable for SRMA2 and examine TIM_ADAVANCE behaviour of timer) and start to debug.

Some changes are quite large (see for example dma where I had to change the API. Shall I make ONE BIG PR with all the changes? or several small ones?
badi

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Porting to STM32L476Discovery/LimiFrog

Post by dhylands » Sun Feb 14, 2016 5:53 pm

I would probably break things up like this:
1 - commit to add new cmsis files
2 - commit to add new hal files (make one commit to checkin virgin files)
3 - commit to modify any of the new hal files (if needed)
4 - commit to add new board definitions
5 - smaller commits for any changes to existing codebase (i.e. DMA change probably needs to be in a commit of its own)

User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Re: Porting to STM32L476Discovery/LimiFrog

Post by badi » Mon Feb 15, 2016 1:50 pm

Thanks, I will start to proceed that way when I have a working port.
badi

danielm
Posts: 167
Joined: Mon Oct 05, 2015 12:24 pm

Re: Porting to STM32L476Discovery/LimiFrog

Post by danielm » Mon Feb 22, 2016 6:39 pm

Are you having any success with your MicroPython port for STM32L476 platform?

User avatar
badi
Posts: 51
Joined: Mon Aug 10, 2015 2:18 pm
Location: Bern, Switzerland

Re: Porting to STM32L476Discovery/LimiFrog

Post by badi » Tue Feb 23, 2016 2:26 pm

The project compiles with some components which use DMA (DAC) switched off. The adaption of the DAC DMA to make it independent of the underling HAL is tricky and makes me Headache.

At the moment I see an USB CDC/MSC device coming up, but I was not able yet to make connection over REPL or mount the files system. Probably there is a bug in the storage/flash modification I did.
badi

Post Reply