Fighting with build system.

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
LdB
Posts: 4
Joined: Wed Aug 30, 2017 2:32 am

Fighting with build system.

Post by LdB » Wed Aug 30, 2017 4:11 am

I have been porting MicroPython to the Pi1,2,3 in baremetal for a Pi forum user but the build system was doing my head in so I took it out onto my normal windows build chain. Few funny stories along the way like initially realizing why I was missing "mpversion.h" :D

Anyhow got it all working but I would like to put it back into your build system but the whole build system uses python scripts and is very linux centric. So if I could ask how to do a couple of specific things

First I need to be able to push my own set of flags to the assembler process. I can see I am supposed to add the assembler stubs into SRC_S list but I can't find where the assembler call is made and what flags are being passed. There actually doesn't seem to be any assembler flags defined anywhere.

Second the Pi is actually 3 different boards and CPU's and I would like to somehow select it. I don't want to do separate directories for each model because that means 3 copies of the C code which will inevitably get out of sync. My boot stub auto-detects the Pi model and corrects for it so the C code remains common to all 3 boards/cpu. All the switch really does is select what the base code is compiled for ARM6, ARM7 or ARM8. ARM6 code will run on Pi1,2 or 3 but is slower than ARM7 code which will run on Pi2 or 3 and ARM8 code is fastest but will only run on Pi3. As you guys know the build system better thoughts, my initial thought was something like "make V=1 ARM6" being required.

Third I need a post process on the ELF file via OBJCOPY to convert it to kernel.img, kernel7.img or kernel8-32.img depending on model as per the second point above.

Any thoughts or suggestions weclomed

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

Re: Fighting with build system.

Post by dhylands » Wed Aug 30, 2017 6:49 am

I'm not seeing any references to SRC_S in the current tree?

The assembler files get assembled using this rule:
https://github.com/micropython/micropyt ... mk#L23-L26
or this rule:
https://github.com/micropython/micropyt ... mk#L28-L31
depending on whether your file ends in a capital S or a small s

so its not calling the assembler directly, but rather calling gcc and letting gcc call the assembler,

The convention is that gcc will run .S files through the pre-processor, but won't run .s files through the pre-processor.

You should be able to create your own custom rules by doing something like this:

Code: Select all

$(MY_LIST_OF_ASM_FILES): $(BUILD)/%.o: %.s
	$(ECHO) "AS (custom) $<"
	$(Q)$(AS) $(CUSTOM_AS_FLAGS_HERE) -o $@ $<

LdB
Posts: 4
Joined: Wed Aug 30, 2017 2:32 am

Re: Fighting with build system.

Post by LdB » Wed Aug 30, 2017 7:12 am

Yeah I worked my way thru that one the problem is the space in directory name I had the compiler directory in.
My directory was G:\Pi\linaro compilers\linaro_7_1
I have to put it in quotes "G:\Pi\linaro compilers\linaro_7_1" to help windows and the scripts out

I still would like some comments on 2 & 3.

Now I moved on and this is just a question I know what the problem is but my familiarity with linux is limited.

So I am getting this
build/emb-stdio.o: In function `vsprintf':
emb-stdio.c:(.text+0x2f0): undefined reference to `__locale_ctype_ptr'
emb-stdio.c:(.text+0x49c): undefined reference to `__locale_ctype_ptr'
emb-stdio.c:(.text+0x4c8): undefined reference to `__locale_ctype_ptr'
emb-stdio.c:(.text+0x6cc): undefined reference to `strnlen'
emb-stdio.c:(.text+0x814): undefined reference to `__locale_ctype_ptr'
make: *** [build/firmware.elf] Error 1

Okay so it is because strnlen isn't part of posix standard in <string.h> and when I am using micropython build files I am in the linux fake enviroment of cygwin. When I compile from a native windows command line I won't get the problem because it will use the windows version of string.h which has it.

Now I thought they recently added strnlen to the posix standard and I would say I need to set a flag. Do any of you linux types know what the flag is?

I can hack around it by putting in my own implementation in a weak reference but I would prefer not to do that.

LdB
Posts: 4
Joined: Wed Aug 30, 2017 2:32 am

Re: Fighting with build system.

Post by LdB » Wed Aug 30, 2017 7:33 am

Oh I forgot to tell you where SRC_S is

So I started from the BARE_ARM directory as that was closest to what I needed. The makefile currently has this

SRC_S = \
# startup_stm32f40xx.s \
gchelper.s \

I would guess it is pretty much the same as I was doing startup_stm32f40xx.s will be there baremetal boot stub

[b]Update: [/b] There were issues with isdigit under posix as well and I weak referenced that strnlen and I got it up. 190K kernel which is tiny for Pi but probably quite large for a micro. Now the fun begins the stub is showing alignment issues and I want my speed back so I need to work the unaligned/aligned problem. I assume there is no existing patch or work done on this?

Other slight thing why do the forum like bold/underline tags not work?

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

Re: Fighting with build system.

Post by dhylands » Wed Aug 30, 2017 3:37 pm

Micropython currently avoids using the c runtime library, so functions that are needed from the C runtime are implemented within MicroPython, like: https://github.com/micropython/micropyt ... /string0.c

So the bare metal ports tend to use the -nostdlib option which prevents libc and libgcc from being pulled in.

As to points 2 & 3, it's all about make. There are many different ways to structure things, and how you structure them will determine how things work.

I'd probably recommend that you follow a structure similar to stmhal, which uses BOARD=BOARDNAME and inside stmhal there is a boards directory which contains definitions and stuff specific to each board. You should also have a different buikld directory for each board so that you can build for the different targets. I'd recommend that you use something like BOARD=PI2 rather than specifying the processor and requiring the user to know which processor the PI2 has. Let the PI2 board files set the processor.

As far as post-processing, that's really just about how you setup your Makefile targets.

Normally, you'd one set of targets will perform one transformation. You typically have a "final" target like deploy, and it would depend on the kernel.img file. There would then be a rule for say creating a .img from a .elf. In stmhal, the deploy target depends on the dfu file, which depends on some bin files which depend on the elf. In the stmhal Makefile, there is a rule which creates the .dfu from the .elf:
https://github.com/micropython/micropyt ... #L391-L395

In your case you could make the final target be board specific. It all boils down to what variables you setup and how you make the rules.

LdB
Posts: 4
Joined: Wed Aug 30, 2017 2:32 am

Re: Fighting with build system.

Post by LdB » Wed Aug 30, 2017 7:05 pm

So the bare metal ports tend to use the -nostdlib option which prevents libc and libgcc from being pulled in
Yeah I worked thru what you did in the libraries and even that wasn't enough as a couple of my compilers I was testing use newlib. So I ended up with a rather long command and provided all my own libs where needed.

-nostdlib -nostartfiles -ffreestanding -fno-asynchronous-unwind-tables -fomit-frame-pointer -fno-builtin

That works on Linaro, Arm official GCC and a the Raspbian(debian) versions of GCC.
I'd probably recommend that you follow a structure similar to stmhal, which uses BOARD=BOARDNAME
The board name in my case is pointless and I am not nominating the CPU so much as the opcode set. The baremetal stub basically does what a bios does on a PC and so I hide all the non common hardware under a mini API. So on a PC you might select to run 0x86, 0x386 or 0x486 code etc and I am doing the same. Strictly I am selecting the opcode set in use being ARM6, ARM7, ARM8 just like 0x86, 0x386, 0x486 on a PC. So typically on the Pi you put all 3 files kernel.img, kernel7.img and kernel8-32.img. The Pi bootloader will take the highest of them based on what CPU it detects at runtime. If you are only doing one you build ARM6 code which is like build 0x86 code for a PC a very reduced opcode set but will run on any of the range as processors but at a speed penalty on high CPU's. Most likely I will actually make a make file that generates all 3 one after another.

So this is my arm8 result on the official ARM GCC version 6.3 windows cross compiler obviously
https://ibb.co/dnuEGk

The two big issues now is getting the USB up so I can have a keyboard and sort out the emitter which looks like it has alignment issues I am having to run hard alignment. As luck would have it I recently baremetalled the USB for another forum user so at least I get payback on old efforts. So I have to merge this (https://github.com/LdB-ECM/Raspberry-Pi ... m32_64_USB) into something that python can use fun fun.

Once I got over that I need to work out how to engage the 3 other CPU cores sitting idle currently on the Pi2 and 3. Then to try an AARCH64 port on the Pi3 which should be fun.

I must thankyou for your prompt responses.

Post Reply