How to port IAR compiler code "#pragma location=" and "__no_init" to GCC - Page 1
Forum section: electronics / general

author: jyrgen
author_rank: Contributor
timestamp: March 14, 2018, 08:30:42 am
content: I have a project which is originally written in IAR which I now need to port for GCC. I'm stuck at one perticular section:Code:extern UNSIGNED8 jumpcode;#pragma location=0x200027F0__no_init UNSIGNED8 jumpcode; /* placed on ram adress 0x200027F0*/As far as I understand the variable should be placed at the perticular memory address and not be initilized to 0.I have been trying to use the __attribute__ ((section(".noinit"))), but I also need to use that to place the variable at the specific memory address. Does anyone know how to do this?

author: Psi
author_rank: Super Contributor
timestamp: March 14, 2018, 08:38:42 am
content: This is for the AVR version of GCC, but the info is probably still valid.QuoteIt's from herehttps://www.microchip.com/webdoc/AVRLibcReferenceManual/mem_sections_1sec_dot_noinit.htmlIf you want more than one variable to be .noinit at its own unique address maybe you need a section for each so they can both be given an address ?dunno

author: poorchava
author_rank: Super Contributor
timestamp: March 14, 2018, 08:42:02 am
content: use a NOLOAD parameter in linker script. It will go something like this:that is how I declare stuff in battery backed SRAM in STM32 (the same case, I don't want any initialization so as to not overwrite the backed up data;Code:.backup(NOLOAD):{. = ALIGN(4);KEEP(*(.backup));KEEP(*(.backup*));. = ALIGN(4);} >BKPSRAMthen in code use something likeCode:__attribute__((section(".backup"))) u32 someVariable;

author: Psi
author_rank: Super Contributor
timestamp: March 14, 2018, 08:48:00 am
content: He needs to hard code the memory address for the variable.

author: jyrgen
author_rank: Contributor
timestamp: March 14, 2018, 08:57:18 am
content: I should add that this is for STM32 and I have multiple sections that look similar in the code.Code:extern UNSIGNED8 flashNodeId;#define FLASH_ADDRESS_NODEID 0x08007F00#pragma location=FLASH_ADDRESS_NODEID__no_init UNSIGNED8 flashNodeId; /* placed on flash adress 0x08007F00 */extern UNSIGNED8 bitrateIndex;#define FLASH_ADDRESS_BITRATE_INDEX 0x08007F08#pragma location=FLASH_ADDRESS_BITRATE_INDEX__no_init UNSIGNED8 bitrateIndex; /* placed on next possible flash adress 0x08007F04 */

author: Psi
author_rank: Super Contributor
timestamp: March 14, 2018, 09:02:27 am
content: I don't think you can do it in code like you can in IAR.I think it needs to be done in the stm32fxxxx_sram.ld file on a section by section basis.

author: poorchava
author_rank: Super Contributor
timestamp: March 14, 2018, 10:42:31 am
content: Quote from: Psi on March 14, 2018, 08:48:00 amno problem, instead of __attribute... stuff do this:Code:#define myVariable (*(u32*)0x12345678)myVariable = 3;or thatCode:u32 * const myVariable_p = (u32*)0x12345678;*myVariable_p = 3

author: andyturk
author_rank: Frequent Contributor
timestamp: March 14, 2018, 02:54:12 pm
content: Quote from: poorchava on March 14, 2018, 10:42:31 amor, for C++ fans:Code:u32 &myVariable = *reinterpret_cast<u32*>(0x12345678);myVariable = 3;

author: mikerj
author_rank: Super Contributor
timestamp: March 14, 2018, 04:59:36 pm
content: Quote from: poorchava on March 14, 2018, 10:42:31 amIf you do that you'll have a very big problem, since you've done nothing to stop the linker placing another variable at 0x12345678.This is pretty simple to do by defining a custom section in the linker filer, and then using __attribute__(((section(""))) to place variables into it. There is a simpletutorial here.

author: poorchava
author_rank: Super Contributor
timestamp: March 14, 2018, 08:35:44 pm
content: AFAIK linker won't place data into a custom RAM region, as there is no data or bss sections being specified to be placed there.

author: cv007
author_rank: Frequent Contributor
timestamp: March 14, 2018, 11:23:03 pm
content: Looking at the original post, 'BL_JUMPCODE_SIZE' seems to possibly indicate communicating with a bootloader. Maybe that's how IAR dealt with both accessing and avoiding these locations, by just creating a noinit chunk at a specific location which provides both access and avoidance.If that is the case, the access part is easy as nothing special needs to be done, as has been shown. But then you also need to make sure your linker is informed where the no-go zones are (what the bootloader uses). This would be done by modifying the linker script, adjusting the memory addresses/sizes.Maybe more info is needed about whether these locations originate from something like a bootloader (separate from the application), or are from the application only.

author: jyrgen
author_rank: Contributor
timestamp: March 15, 2018, 08:58:58 am
content: Thanks for all replies!Quote from: cv007 on March 14, 2018, 11:23:03 pmThis is indeed from a bootloader. It is used as "the shared RAM for data exchange between bootloader and application" (taken from the documentation of the bootloader).

author: mikeselectricstuff
author_rank: Super Contributor
timestamp: March 15, 2018, 10:49:13 am
content: Quote from: jyrgen on March 15, 2018, 08:58:58 amIf you just need to exchange a byte or two, it may be easier to just use an unused hardware register

author: cv007
author_rank: Frequent Contributor
timestamp: March 15, 2018, 03:51:25 pm
content: QuoteI assume he really doesn't want to touch the bootloader side.//bootloader ram array startuint8_t* const jumpcode = (uint8_t*)0x200027F0;//existing code can use as before//array access works fine- jumpcode = 0//not as perfect as before (4 extra bytes), but compiler may optimize since const)//bootloader flash variables#define flashNodeId *(uint8_t*)0x08007F00#define bitrateIndex *(uint8_t*)0x08007F08...You still will need to get at the linker script to make sure those areas are not used by you, unless you already have a custom linker script.

author: bson
author_rank: Unknown
timestamp: March 16, 2018, 11:07:25 pm
content: Symbols are normally put in the linker cmd script, e.g.:Code:/* ARM Core Cortex-M4 system control */CPUID = 0xe000ed00;ACTLR = 0xe000e008;ICSR = 0xe000ed04;VTOR = 0xe000ed08;AIRCR = 0xe000ed0c;SCR = 0xe000ed10;CCR = 0xe000ed14;SHPR1 = 0xe000ed18;SHPR2 = 0xe000ed1c;SHPR3 = 0xe000ed20;SHCRS = 0xe000ed24;CFSR = 0xe000ed28;MMFSR = 0xe000ed28;BFSR = 0xe000ed29;UFSR = 0xe000ed2a;HFSR = 0xe000ed2c;MMAR = 0xe000ed34;BFAR = 0xe000ed38;AFSR = 0xe000ed3c;Then in your C code declare them as externs, something along the lines of:Code:#include <stdint.h>#define DEV_CTL_REG_8(NAME) extern volatile uint8_t NAME#define DEV_CTL_REG_16(NAME) extern volatile uint16_t NAME#define DEV_CTL_REG(NAME) extern volatile uint32_t NAME#ifdef __cplusplusnamespace arm_cm4 {extern "C" {#endif// ARM Core Cortex-M4 system controlDEV_CTL_REG(CPUID);DEV_CTL_REG(ACTLR);DEV_CTL_REG(ICSR);DEV_CTL_REG(VTOR);DEV_CTL_REG(AIRCR);DEV_CTL_REG(SCR);DEV_CTL_REG(CCR);DEV_CTL_REG(SHPR1);DEV_CTL_REG(SHPR2);DEV_CTL_REG(SHPR3);DEV_CTL_REG(SHCRS);DEV_CTL_REG(CFSR);DEV_CTL_REG_8(MMFSR);DEV_CTL_REG_8(BFSR);DEV_CTL_REG_16(UFSR);DEV_CTL_REG(HFSR);DEV_CTL_REG(MMAR);DEV_CTL_REG(BFAR);DEV_CTL_REG(AFSR);#ifdef __cplusplus}; // extern "C"}; // ns arm_cm4#endifYou generally don't want to put all these symbols in a global #define namespace.

author: westfw
author_rank: Super Contributor
timestamp: March 17, 2018, 01:55:21 am
content: QuoteWhile that presumably works, I don't think I've seen it often enough come close to calling it "normal." Almost every microcontroller I've seen (mis)uses constant pointers in .h files for peripheral access, usually resulting in some huge "stm32f10x.h" file or similar.The only chips I've seen that definesthe peripherals in linker files are the PIC32 chips, and it causes them to miss some obvious optimizations (OTOH, they claim it permits libraries to be distributed in object form, which is a pretty big advantage.)In fact ARM specifically recommends .h-based peripheral definitions as part of their CMSIS specification:http://arm-software.github.io/CMSIS_5/Core/html/device_h_pg.html#device_h_sechttps://github.com/ARM-software/CMSIS/blob/master/CMSIS/Include/core_cm3.h(they also want to (ab)use structure references overlaid on the memory space, so even if linker files were used to define peripheral base addresses, they'd still need a huge .h presence to define the structures and bits that they recommend.)Using a separate namespace for the peripherals sounds like an excellent idea (for C++), but I've never seen it done.I'm curious as to where you've seen the scheme you say is "normal"? (Hmm. I bet it would work a lot better for other languages, as well.)

author: bson
author_rank: Unknown
timestamp: March 17, 2018, 02:49:02 am
content: Quote from: westfw on March 17, 2018, 01:55:21 amTI does it that way; they provide a linker script for each CPU. They've adapted a lot of gcc'isms though, like a significant portion of the attributes and their linker scripts look the same, but they don't use gnu ld for their own compiler. (They do provide a gcc build for all the ARM and MSP430 based processors they sell, but I don't know about all the others.)I forget who else I've seen doing that off-hand... but I know when I worked on gcc this was considered the intended way and hence there is no specific support for anything else. But that was almost 20 years ago.ARM has their own compiler though and don't use the gcc toolchain... or particularly seem to care about compatibility.