2014-10-18 05:03 AM
Hi all,
I need to prepare a migration from existing fully functional code on STM32F103 (custom low level drivers, relatively complex interrupts and DMA schem, USB MSC with FatFS to drive uSD card : Nemuisan version) to STM32F215 architecture. I already verified the DMA changes won't affect functionality in theory. I plan to use EMBLOCKS gcc to build new STM32F215 version (I was using CoIDE for STM32f103, but this IDE does not support F2). So I understand fromhttp://www.st.com/web/en/resource/technical/document/application_note/DM00033pdf
the migration won't be too difficult by just switching Std_Periph_Lib and updating low level drivers, especially DMA schem. Code will probably be highly portable, do you confirm ? Do you have any experience advises regarding that migration ? But with the Cube support of the F2 architecture (especially concerning USB MSC + FatFs) by doing this simple code migration, I will loose all the perf upgrades done on Cube ? How much faster the new MSC is compared to last STM32 USB driver please ? What would you do in stead of me ? About the needed .ld script : can I use the stm32_flash.ld of the STM322xG_EVAL and just change with appropriate f215RE values in the first part of the file :/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of 128K SRAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0; /* required amount of heap */
_Min_Stack_Size = 0x200; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
}
Thank you in advance for your help !
#stm32f2-linker-script-.ld
2014-10-18 05:41 AM
I've ported a couple of projects from F1 to F2/F4, as well a various iterations of the Standard Library. The most time consuming part is dealing with the pin configuration, the pin muxing scheme is totally different.
I'd forget portability, if you fork the design you're probably looking at a man-day or so to get the bulk of the design/functionality into a new project. I built a new F2 project framework, and then copied/merged in the functions. I had a pretty good level of abstraction/partitioning with the hardware specific stuff relatively well contained. Linker scripts should be relatively easy to manage, I use GNU/GCC and the main things I focus on are the memory sections, and the vector tables. I can share some .LD, but my target is Yagarto/Make I'm not sure that MSC designs are going to be significantly faster, the bandwidth is constrained by two things, the memory (SDIO) and the USB (12 Mbps), if you can get to 800 KBps now this isn't going to change much unless you use an USB-HS PHY. HAL/CUBE is a bigger hurdle to migrate too, I see the benefits and weaknesses there, currently it's not sufficiently robust/mature to commit resources too, but ST seems to think it's the path to the promised land, and is throwing a lot of engineering/support resources at it. I determined long ago that the world is round, flattening it for maps while convenient tends to result in distorted projections.2014-10-18 06:24 AM
Thanks a lot Clive.
I appreciate a lot your feedback on that point. So I will wait stable version of Cube, and perhaps think about a complete new version ''some day''... I don't appreciate too high level code and RTOS : you loose a lot of performance, and portability is not always needed. But well it depends on your project requirements, depending on your point of view the earth can be flat... Sometimes...The cons of low level optimization is that today, I will spend a fews days to translate my code ;) !About linker script, as you understood I am new too their customization... I would appreciate a lot you can describe the ''vector'' (I understand isr_vector ?) customization. If you can share some examples it will probably help me a lot.Why would Yagarto based .ld be not compatible with EMBLOCKS ?Tx again2014-10-18 07:00 AM
Well linker scripts tend to be tailored to specific packages/libraries, Atollic and Ride have markedly different implementations. These difference often revolve around how the stack is defined, and how statics/constructors are handled, and how the sizes of linked sections is communicated to the start up code.
The .LD model I use has the weak IRQHandler entries, and this tends to be chip (Value, Connectivity, Medium, High Density) specific. stm32f217ig.ld/*
Linker script for STM3221G-EVAL - STM32F217IGH6 - sourcer32@gmail.com
*/
/* include the common STM32F2 sub-script */
INCLUDE ''STM32F2_COMMON.ld''
/* Memory Spaces Definitions */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1M
}
/* highest address of the user mode stack */
_estack = 0x20020000;
/* Sections Definitions */
SECTIONS
{
/* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* for some STRx devices, the beginning of the startup code is stored in the .flashtext section, which goes to FLASH */
.flashtext :
{
. = ALIGN(4);
*(.flashtext) /* Startup code */
. = ALIGN(4);
} >FLASH
/* the program code is stored in the .text section, which goes to Flash */
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
_etext = .;
/* This is used by the startup in order to initialize the .data secion */
_sidata = _etext;
} >FLASH
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM. */
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_sdata = . ;
*(.data)
*(.data.*)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
_edata = . ;
} >RAM
/* This is the uninitialized data section */
.bss :
{
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .;
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
/* This is used by the startup in order to initialize the .bss secion */
_ebss = . ;
} >RAM
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
/* This is the user stack section
This is just to check that there is enough RAM left for the User mode stack
It should generate an error if it's full.
*/
._usrstack :
{
. = ALIGN(4);
_susrstack = . ;
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
_eusrstack = . ;
} >RAM
__exidx_start = .;
__exidx_end = .;
/* after that it's only debugging information. */
/* remove the debugging information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
STM32F2_COMMON.ld
/*
Linker script for STM32F2 Common - sourcer32@gmail.com
*/
/* default stack sizes.
These are used by the startup in order to allocate stacks for the different modes.
*/
__Stack_Size = 8192 ;
PROVIDE ( _Stack_Size = __Stack_Size ) ;
__Stack_Init = _estack - __Stack_Size ;
/*''PROVIDE'' allows to easily override these values from an object file or the commmand line.*/
PROVIDE ( _Stack_Init = __Stack_Init ) ;
/*
There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 0x100 ;
/*
this sends all unreferenced IRQHandlers to reset
*/
PROVIDE ( Undefined_Handler = 0 ) ;
PROVIDE ( SWI_Handler = 0 ) ;
PROVIDE ( IRQ_Handler = 0 ) ;
PROVIDE ( Prefetch_Handler = 0 ) ;
PROVIDE ( Abort_Handler = 0 ) ;
PROVIDE ( FIQ_Handler = 0 ) ;
PROVIDE ( NMIException = 0 ) ;
PROVIDE ( HardFaultException = 0 ) ;
PROVIDE ( MemManageException = 0 ) ;
PROVIDE ( BusFaultException = 0 ) ;
PROVIDE ( UsageFaultException = 0 ) ;
PROVIDE ( SVCHandler = 0 ) ;
PROVIDE ( DebugMonitor = 0 ) ;
PROVIDE ( PendSVC = 0 ) ;
PROVIDE ( SysTickHandler = 0 ) ;
PROVIDE ( WWDG_IRQHandler = 0 ) ;
PROVIDE ( PVD_IRQHandler = 0 ) ;
PROVIDE ( TAMP_STAMP_IRQHandler = 0 ) ;
PROVIDE ( RTC_WKUP_IRQHandler = 0 ) ;
PROVIDE ( FLASH_IRQHandler = 0 ) ;
PROVIDE ( RCC_IRQHandler = 0 ) ;
PROVIDE ( EXTI0_IRQHandler = 0 ) ;
PROVIDE ( EXTI1_IRQHandler = 0 ) ;
PROVIDE ( EXTI2_IRQHandler = 0 ) ;
PROVIDE ( EXTI3_IRQHandler = 0 ) ;
PROVIDE ( EXTI4_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream0_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream1_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream2_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream3_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream4_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream5_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream6_IRQHandler = 0 ) ;
PROVIDE ( ADC_IRQHandler = 0 ) ;
PROVIDE ( CAN1_TX_IRQHandler = 0 ) ;
PROVIDE ( CAN1_RX0_IRQHandler = 0 ) ;
PROVIDE ( CAN1_RX1_IRQHandler = 0 ) ;
PROVIDE ( CAN1_SCE_IRQHandler = 0 ) ;
PROVIDE ( EXTI9_5_IRQHandler = 0 ) ;
PROVIDE ( TIM1_BRK_TIM9_IRQHandler = 0 ) ;
PROVIDE ( TIM1_UP_TIM10_IRQHandler = 0 ) ;
PROVIDE ( TIM1_TRG_COM_TIM11_IRQHandler = 0 ) ;
PROVIDE ( TIM1_CC_IRQHandler = 0 ) ;
PROVIDE ( TIM2_IRQHandler = 0 ) ;
PROVIDE ( TIM3_IRQHandler = 0 ) ;
PROVIDE ( TIM4_IRQHandler = 0 ) ;
PROVIDE ( I2C1_EV_IRQHandler = 0 ) ;
PROVIDE ( I2C1_ER_IRQHandler = 0 ) ;
PROVIDE ( I2C2_EV_IRQHandler = 0 ) ;
PROVIDE ( I2C2_ER_IRQHandler = 0 ) ;
PROVIDE ( SPI1_IRQHandler = 0 ) ;
PROVIDE ( SPI2_IRQHandler = 0 ) ;
PROVIDE ( USART1_IRQHandler = 0 ) ;
PROVIDE ( USART2_IRQHandler = 0 ) ;
PROVIDE ( USART3_IRQHandler = 0 ) ;
PROVIDE ( EXTI15_10_IRQHandler = 0 ) ;
PROVIDE ( RTC_Alarm_IRQHandler = 0 ) ;
PROVIDE ( OTG_FS_WKUP_IRQHandler = 0 ) ;
PROVIDE ( TIM8_BRK_TIM12_IRQHandler = 0 ) ;
PROVIDE ( TIM8_UP_TIM13_IRQHandler = 0 ) ;
PROVIDE ( TIM8_TRG_COM_TIM14_IRQHandler = 0 ) ;
PROVIDE ( TIM8_CC_IRQHandler = 0 ) ;
PROVIDE ( DMA1_Stream7_IRQHandler = 0 ) ;
PROVIDE ( FSMC_IRQHandler = 0 ) ;
PROVIDE ( SDIO_IRQHandler = 0 ) ;
PROVIDE ( TIM5_IRQHandler = 0 ) ;
PROVIDE ( SPI3_IRQHandler = 0 ) ;
PROVIDE ( UART4_IRQHandler = 0 ) ;
PROVIDE ( UART5_IRQHandler = 0 ) ;
PROVIDE ( TIM6_DAC_IRQHandler = 0 ) ;
PROVIDE ( TIM7_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream0_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream1_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream2_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream3_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream4_IRQHandler = 0 ) ;
PROVIDE ( ETH_IRQHandler = 0 ) ;
PROVIDE ( ETH_WKUP_IRQHandler = 0 ) ;
PROVIDE ( CAN2_TX_IRQHandler = 0 ) ;
PROVIDE ( CAN2_RX0_IRQHandler = 0 ) ;
PROVIDE ( CAN2_RX1_IRQHandler = 0 ) ;
PROVIDE ( CAN2_SCE_IRQHandler = 0 ) ;
PROVIDE ( OTG_FS_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream5_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream6_IRQHandler = 0 ) ;
PROVIDE ( DMA2_Stream7_IRQHandler = 0 ) ;
PROVIDE ( USART6_IRQHandler = 0 ) ;
PROVIDE ( I2C3_EV_IRQHandler = 0 ) ;
PROVIDE ( I2C3_ER_IRQHandler = 0 ) ;
PROVIDE ( OTG_HS_EP1_OUT_IRQHandler = 0 ) ;
PROVIDE ( OTG_HS_EP1_IN_IRQHandler = 0 ) ;
PROVIDE ( OTG_HS_WKUP_IRQHandler = 0 ) ;
PROVIDE ( OTG_HS_IRQHandler = 0 ) ;
PROVIDE ( DCMI_IRQHandler = 0 ) ;
PROVIDE ( CRYP_IRQHandler = 0 ) ;
PROVIDE ( HASH_RNG_IRQHandler = 0 ) ;
2014-10-18 07:12 AM
Another thread where I attached a complete GNU/GCC project
https://community.st.com/0D50X00009XkhqlSAB
Edit: Fixed DEADLINK, original post from 18-Oct-2014
2014-10-18 07:18 AM
Thank you Clive,
Now I will try to set a new framework and translate my code for F215RE based on your .ld examples. I will let you know... ;)2014-10-19 08:49 AM
Hi Clive,
I am on my way... But I am not sure according tohttp://www.st.com/web/en/resource/technical/document/application_note/DM00033pdf
: On STM32F103 we haveUSB_HP_CAN1_TX_IRQn = 19, /*!< USB High Priority or CAN1 TX Interrupts */
USB_LP_CAN1_RX0_IRQn = 20, /*!< USB Low Priority or CAN1 RX0 Interrupts */
And on STM32F215 it may be :
OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */
OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */
With
USB_HP_CAN1_TX_IRQn ->
OTG_HS_EP1_OUT_IRQn
andUSB_LP_CAN1_RX0_IRQn ->
OTG_HS_EP1_IN_IRQn Is that correct ?2014-10-19 09:08 AM
Probably using the Full-Speed, High-Speed suggests you're using another interface with an external PHY
OTG_FS_IRQHandler ? Suggest you look at the USB V2.1 Firmware Library2014-10-27 08:49 AM
Ok I succeed to compile for STM32F215.
It's not that bad, after all.But you were true : the USB is completely different and has to be rewritten based on the ST driver.But it's a bit hard to find a way to compile an USB device MSC with SD card support base on the STM32_USB_OTG_Driver. Because this is deeply dependent to STM32_EVAL board and headers.Is there any example or existing code that could be easily integrated ?Tx2014-10-27 09:27 AM
I ported from the EVAL board to an STM32F4-DISCO with an MicroSD socket attached to it (also the STM32F4-DIS-BB) and to some of my own STM32F2x5 boards with a MicroSD, accessing in Windows via USB MSC (USBSTOR)