Barri
Posts: 6
Joined: Sun Dec 06, 2015 12:26 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Fri Dec 25, 2015 11:45 am

For learning I used very well raspberry PI 1 B model + dwelch armjtag + openocd with ulink 1 (keil).

Now I inserted in 21-webserver a reset button which calls the circle reboot() function (using the watchdog).

But there are some issues. The reboot command is not working in this combination. It seems that the raspberry and/or the peripherials (usb, network, gpu) makes not a complete reset/reboot.

Also if I make: an halt commando in openocd + reload a new build of 21-webserver + resume 0x8000
the webserver is not starting again.

Only after a complete power cycle + downloading I can start the 21-webserver application again.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sun Dec 27, 2015 10:51 am

I haven't used JTAG-based debugging so I cannot talk about it. What I can say is that a Circle image cannot be restarted without reload because there is static data inside which is not reset before reboot. Some Circle drivers may expect the controlled device in reset state to initialise it successfully. The watchdog reset should normally be sufficient to reboot successfully (without JTAG).

Barri
Posts: 6
Joined: Sun Dec 06, 2015 12:26 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sun Dec 27, 2015 4:23 pm

Thank you, after I added a:
m_pActLED->Blink (3); // show we understand reboot request
reboot();
and correct my errors on the index.html page I can reboot the raspberry from
the webpage (started then the dwelch armjtag code from the sd-card, slow blinking).

In openocd telnet a simple:
halt
load_image kernel.elf
resume 0x8000
starts the webserver again.

Barri
Posts: 6
Joined: Sun Dec 06, 2015 12:26 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sat Jan 02, 2016 5:43 pm

Looking for a hdmi ready display points me to the Motorola Lapdock.

http://www.ebay.de/itm/MOTOROLA-LAPDOCK ... SwxH1UHlVE

sorry for german websites:

http://www.stefanjunger.de/2013/08/04/r ... a-lapdock/
https://komputermitk.wordpress.com/2014 ... denamenyx/

Has somebody check this (hdmi, keyboard, usb hub) with the the circle usb library ?

Curbfeeler
Posts: 3
Joined: Fri Jan 08, 2016 4:34 pm

Re: Circle - C++ bare metal environment (with USB)

Fri Jan 08, 2016 5:40 pm

Hello. First I want to say thanks for these tutorials. They are just exactly what I needed. I am an Rpi2 user.

I had previously completed the Cambridge Baking Pi tutorials (which were converted to Rpi2) and got them all to run with pretty good results. Next I moved to the Valvers tutorials, as assembly is not my thing. These ran until the screen output and then I got a blank screen.

So then I switched to your tutorials and have to say I am very impressed. I'm now drawing to the screen and having a blast!

The only problem I ran into so far is when I try to switch over to 16 or 32 bit colors in screen.h I am getting an error on the calls to SetPixel where the 3rd parameter causes an undefined reference. Wondering if that code is not fleshed out quite yet maybe.

Thanks again!

Dan

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sat Jan 09, 2016 11:26 am

Thanks for using Circle. I wouldn't call it a tutorial because the provided explanations are not enough but if you can learn from it it's good.

Can you please tell exactly which error you get where (file/line) when you build which sample with which toolchain?

I can build all samples from the head revision of the repo with DEPTH 16 and 32 successfully except sample/17-fractal which does not build by intention with DEPTH 32 because with more than 65536 colors one does not get a better picture.

Curbfeeler
Posts: 3
Joined: Fri Jan 08, 2016 4:34 pm

Re: Circle - C++ bare metal environment (with USB)

Sat Jan 09, 2016 5:49 pm

Hi Rene thanks for writing me back. I went ahead and copied #2 and pasted as #24 so it would be the biggest number, then the only change I made is in screen.h to change the depth to 16.

I wonder if the fact that I am building on a Pi2 is the issue. I don't have a machine set up with linux currently. I could build one out and see.

Code: Select all

pi@raspberrypi:~ $ cd circletuts/circle-master/
pi@raspberrypi:~/circletuts/circle-master $ ./makeall
make: Nothing to be done for 'all'.
make: 'libusb.a' is up to date.
make: 'libinput.a' is up to date.
make: 'libfs.a' is up to date.
make: 'libfatfs.a' is up to date.
make: 'libsched.a' is up to date.
make: 'libnet.a' is up to date.
make: 'libbluetooth.a' is up to date.
arm-linux-gnueabihf-g++ -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -Wall -Wno-psabi -fsigned-char -fno-builtin -nostdinc -nostdlib -D__circle__ -DRASPPI=2 -I ../../include -I ../../addon -O -g  -fno-exceptions -fno-rtti -std=c++0x -c -o main.o main.cpp
arm-linux-gnueabihf-g++ -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard -Wall -Wno-psabi -fsigned-char -fno-builtin -nostdinc -nostdlib -D__circle__ -DRASPPI=2 -I ../../include -I ../../addon -O -g  -fno-exceptions -fno-rtti -std=c++0x -c -o kernel.o kernel.cpp
arm-linux-gnueabihf-ld -o kernel.elf -Map kernel.map -T ../../circle.ld ../../lib/startup.o main.o kernel.o ../../lib/libcircle.a
kernel.o: In function `CKernel::Run()':
/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:42: undefined reference to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)'
/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:43: undefined reference to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)'
/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:47: undefined reference to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)'
/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:48: undefined reference to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)'
/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:56: undefined reference to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)'
kernel.o:/home/pi/circletuts/circle-master/sample/24-screenpixel/kernel.cpp:57: more undefined references to `CScreenDevice::SetPixel(unsigned int, unsigned int, unsigned short)' follow
../Rules.mk:30: recipe for target 'kernel.img' failed
make: *** [kernel.img] Error 1
pi@raspberrypi:~/circletuts/circle-master $ 

Dan

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sat Jan 09, 2016 8:02 pm

Hi Dan,

please call "./makeall clean" before "./makeall" when you made a change to some Circle header file.

Otherwise in this case the definition of CScreenDevice::SetPixel() in the object screen.o in libcircle.a does not match the definition in screen.h which will be detected by ld here.

This should also work when building on the RPi2 itself.

Rene

Curbfeeler
Posts: 3
Joined: Fri Jan 08, 2016 4:34 pm

Re: Circle - C++ bare metal environment (with USB)

Sat Jan 09, 2016 8:18 pm

Thanks you are a lifesaver!

Dan

Barri
Posts: 6
Joined: Sun Dec 06, 2015 12:26 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sun Jan 17, 2016 7:11 pm

My first tests using the motorola lapdock and circle are positiv.
HDMI and keyboard are working.

For the CLogger console working on the screen I checked different screen resolutions in the file cmdline.txt:

width=640 height=480 // ok
width=800 height=600 // ok, but I get no more screen line count as in the mode 640x480 (should this be ?)
width=1366 height=768 // not ok, CScreenDevice don't accept this resolution, m_Screen.Initialize () = false

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Mon Jan 18, 2016 12:12 pm

The possible display formats depend on the used HDMI display and can be requested calling

Code: Select all

/opt/vc/bin/tvservice -m DMT
/opt/vc/bin/tvservice -m CEA
on Raspbian.

Circle has further restrictions on that. "width" must be a multiple of 8 and the pitch value (size of one pixel line in the frame buffer in bytes) must be equal "width" * "size of one pixel in the frame buffer in bytes".

width=1366 is not a multiple of 8 and does not work but width=800/height=600 should normally work if the display supports it.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Tue Mar 22, 2016 9:51 pm

Circle has been updated to run on the Raspberry Pi 3 in 32-bit mode. You have to define

Code: Select all

RASPPI = 3
in Rules.mk or Config.mk to build this version.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Thu Mar 24, 2016 7:11 pm

Circle64 is a 64-bit port (AArch64) of Circle (32-bit) and is available on GitHub. Currently only the base library is available. It already supports the frame buffer, interrupts, timer and an exception handler. The MMU and data cache are not supported yet. The first four samples of the 32-bit version are included.

Sniper435
Posts: 24
Joined: Fri Nov 02, 2012 1:35 pm

Re: Circle - C++ bare metal environment (with USB)

Wed Apr 26, 2017 11:46 am

resurrecting an old thread here but...
I'm currently starting to port an application I've been running in raspbian to run on bare metal using circle..

one piece of functionality I'd like to try and support would be the ability to slow the PI down as much as possible (reduce power consumption) until some input is received on a GPIO pin - which could be a command from an IR remote. is this something that would be possible?

*Note: I don't do this currently in Raspbian but it would be nice to be able to

LdB
Posts: 525
Joined: Wed Dec 07, 2016 2:29 pm

Re: Circle - C++ bare metal environment (with USB)

Wed Apr 26, 2017 2:44 pm

All the power control is done via the mailbox
https://github.com/raspberrypi/firmware ... -interface
Command: 0x00030007 Id: 3 will get you the minimum CPU clock speed
Command: 0x00038002 Id:3 to set the ARM cpu speed with that value in Hz.

You can also turn off all the peripherals LAN/USB/HDMI etc via the mailbox

The circle code will already have code to operate the mailbox.
I am guessing "cputhrottle.cpp" in circle is probably what you are after.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Thu Apr 27, 2017 7:32 am

Sniper435 wrote:one piece of functionality I'd like to try and support would be the ability to slow the PI down as much as possible (reduce power consumption) until some input is received on a GPIO pin - which could be a command from an IR remote. is this something that would be possible?
Circle does not explicitly implement power management. Nevertheless you should be able to reduce the consumed power by letting the CPU execute a "wfi" (wait for interrupt) instruction and wake it up by a previously enabled GPIO interrupt. The system timer IRQ handler is still running 100 times per second in this case.

It should also be possible to disable all IRQs using DisableIRQs() and to use the CGPIOPinFIQ class for the IR GPIO pin. You can let the system timer IRQ handler sleep that way and wake up the CPU only triggered by the IR sensor via the FIQ. Of course you will not have a valid system time then any more and this is more difficult to set-up.

Unfortunately I have no idea how much gain of power consumption you will have that way. You may also power off some of the peripherals, but this will not work with USB if it is needed later, because it would require a re-enumeration of the USB, which is not supported by Circle.

By default the CPU is already running with the minimum clock speed at bare metal start-up. So there is no lowering possible using the CCPUThrottle class.

Sniper435
Posts: 24
Joined: Fri Nov 02, 2012 1:35 pm

Re: Circle - C++ bare metal environment (with USB)

Thu Apr 27, 2017 8:03 am

Thanks for the feedback, sounds like there's some things I can try - certainly powering off peripherals could work as currently I'm not using USB, ethernet or HDMI - just lots of GPIO/I2C and SPI

django013
Posts: 21
Joined: Wed Mar 29, 2017 10:11 am

Re: Circle - C++ bare metal environment (with USB)

Fri May 12, 2017 7:24 am

Hi,

I just discovered your work and after a quick look I have some questions. I'm mainly interested in the 64bit port :)
The raspi 3 runs a max frequency of 1.2GHz, so what is the fastest timer to setup?
You wrote that core 0 handles all interrupt responses ...
From linux kernel I read about "jiffies" - which is a 64bit counter on each core and it may be different on each core.
So I'd like to know, is this jiffies a linux item, or is it a hardware register, which could be accessible through your framework too?
Or is it possible to setup a timer interrupt for each core separately?
What is the fastest gpio clock and how is it related to the core clock?

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Fri May 12, 2017 7:12 pm

django013 wrote:I just discovered your work and after a quick look I have some questions. I'm mainly interested in the 64bit port :)
The main system timer in Circle runs with 100 Hz and you can start as many kernel timers as you want with this resolution. When a kernel timer elapses a timer handler gets called. It is executed in IRQ context on core 0.

There is a 64-bit system clock register in the BCM283[567] which is incremented by one each microsecond and which can be read from each core. Circle only uses the lower 32-bits of this register. Per-core-local-timers are currently not implemented in Circle.

At the time I programmed with jiffies for the last time, this was a single variable inside the Linux kernel which has been incremented with each timer tick (1000 Hz at this time). I don't know, if this is still the case. But it is a Linux thing.

Theoretically you can setup a GPIO clock using PLLD as clock source with 500 MHz frequency, but according to the BCM2835 ARM Peripherals document (pg. 106) the maximum operating frequency is about 125 MHz or less. The GPIO clock does not depend on the core clock with clock source PLLD.

django013
Posts: 21
Joined: Wed Mar 29, 2017 10:11 am

Re: Circle - C++ bare metal environment (with USB)

Sat May 13, 2017 6:02 am

Hi,

thank you for your fast reply and the link!
There is a 64-bit system clock register in the BCM283[567] which is incremented by one each microsecond and which can be read from each core. Circle only uses the lower 32-bits of this register.
Well, on 64bit systems reading a 64bit register should be a single instruction.
In the linked document they say, that the 64-bit free running counter is incremented by timer clock. Don't know, whether the timer-clock can be changed. If so, I'm interested in using the fastest possible timer clock.
Respect to GPIO they write, that if jitter is an issue, the fastest possible IO-clock should be used.
I'm interested in reducing jitter and looking for a single-instruction timebase. That timebase should be microsecond or shorter.
Could that be realized with circle64?
Per-core-local-timers are currently not implemented in Circle.
Isn't that counter-access just a register read?
The GPIO clock does not depend on the core clock with clock source PLLD.
In the linked document they write, that the GPIO clock is derived from the PLL clock. Same should be true for the timer clock base. If not, than every Pin-change would be wrapped in a synch-cycle. right?

What I didn't found yet: how can memory be distinguished, whether it is shared by all cores or used by a single core? May be I missed some information.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sat May 13, 2017 12:00 pm

django013 wrote:
rst wrote:There is a 64-bit system clock register in the BCM283[567] which is incremented by one each microsecond and which can be read from each core. Circle only uses the lower 32-bits of this register.
Well, on 64bit systems reading a 64bit register should be a single instruction.
Yes, but the address of this register is not 64-bit aligned. See page 172 of the referenced document. As I understand it, this means the memory system has to do two 32-bit accesses to get the 64-bit contents of the register. This can lead to invalid values read, when the lower part of the timer wraps.
In the linked document they say, that the 64-bit free running counter is incremented by timer clock. Don't know, whether the timer-clock can be changed. If so, I'm interested in using the fastest possible timer clock.
I don't think, it can be changed. I have never read about this.
Respect to GPIO they write, that if jitter is an issue, the fastest possible IO-clock should be used. I'm interested in reducing jitter and looking for a single-instruction timebase. That timebase should be microsecond or shorter. Could that be realized with circle64?
The GPIO clock is a clock signal which is generated inside the BCM283[567] and which is made available on some GPIO pin for external usage. As I wrote the PLLD clock source is running at 500 MHz. There may be clock sources with higher frequencies, but they change with CPU clock settings.
Per-core-local-timers are currently not implemented in Circle.
Isn't that counter-access just a register read?
Probably. There are several registers for the Generic Timer, which can be read with one instruction. But I am not familiar with that. It has not been requested so far.
In the linked document they write, that the GPIO clock is derived from the PLL clock. Same should be true for the timer clock base. If not, than every Pin-change would be wrapped in a synch-cycle. right?
See above. The GPIO clock is an internally generated clock with a programmable clock source. The GPIO clock signal can be made available on the 40 pin header of the RPi. As I understand it, this has nothing to do with an eventual clock an GPIO pin level is sampled with. I have no further information about this, only the referenced document.
What I didn't found yet: how can memory be distinguished, whether it is shared by all cores or used by a single core? May be I missed some information.
In Circle all normal memory is shareable between the cores.

django013
Posts: 21
Joined: Wed Mar 29, 2017 10:11 am

Re: Circle - C++ bare metal environment (with USB)

Sun May 14, 2017 7:09 am

Yes, but the address of this register is not 64-bit aligned. See page 172 of the referenced document. As I understand it, this means the memory system has to do two 32-bit accesses to get the 64-bit contents of the register.
Duh! What a mess! You're right!
What a stupid misconception from the processor designer :(

I found this https://www.element14.com/community/ser ... Manual.pdf
and on page 9 they say: "unaligned addresses are permitted for most loads and stores ..."

In section 3.5.2 they say: "all exclusive accesses must be naturally aligned, and the exclusive pair access must be aligned to twice the data size (16 bytes for 64bit pair"
Well, I don't really understand, what that means.
As I wrote the PLLD clock source is running at 500 MHz. There may be clock sources with higher frequencies, but they change with CPU clock settings.
Hm, I don't want to change CPU clock settings during runtime, just once on initialization time.
So I stil didn't get the frequency dependencies.
I have a raspberry Model 3 - and I read, that it runs at 1,2GHz ...
So what can I do with that 1,2GHz when the timers run at 500 MHz?

I guess, that linux will be able to serve a 100Hz timer with little jitter ...

From my point of view baremetal programming comes into play, when linux timings and jitter becomes inacceptable. So I guess any baremetal programmer is interested in highspeed timers.
Am I wrong?

So what is the fastest jitterfree timing interval that I can use to drive a 64bit counter, that could be read aligned by a single instruction - or even better: reserve a register that will always contain that counter?
In Circle all normal memory is shareable between the cores.
Well, but memory mapped register access will probabely be different for each core, won't it?

User avatar
Ultibo
Posts: 92
Joined: Wed Sep 30, 2015 10:29 am
Location: Australia

Re: Circle - C++ bare metal environment (with USB)

Sun May 14, 2017 10:22 am

django013 wrote:So what is the fastest jitterfree timing interval that I can use to drive a 64bit counter, that could be read aligned by a single instruction - or even better: reserve a register that will always contain that counter?
The Generic Timers (per core) in the Pi 2 and 3 can be read using a single MRRC instruction (loading 2 x 32-bit registers) to return a 64-bit counter. Have a look at the ARM Architecture Reference Manual for the details of the Generic Timer registers and the instructions for reading each of them.

On the Raspberry Pi 2 and 3 the Generic Timers are driven from the 19.2MHz oscillator clock, if you look at the Raspberry Pi QA7 document it provides details of the divider settings which by default reduce it to 1MHz but in bare metal you can easily change the divider to make the timers run at the full 19.2MHz clock (as Linux does).
Ultibo.org | Make something amazing
https://ultibo.org

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Sun May 14, 2017 11:08 am

django013 wrote:What a stupid misconception from the processor designer :(
This address map comes from the BCM2835 which contained a 32-bit CPU only. For my purpose it's enough to read the lower 32 bits of the 1-MHz counter. It wraps after over an hour. This should be enough.
and on page 9 they say: "unaligned addresses are permitted for most loads and stores ..."
Yes, unaligned accesses are permitted, but are split into multiple memory accesses on the bus.
In section 3.5.2 they say: "all exclusive accesses must be naturally aligned, and the exclusive pair access must be aligned to twice the data size (16 bytes for 64bit pair"
Exclusive accesses are executed by special instructions. This is different. These instructions are needed to implement locks etc. They do not permit unaligned accesses. AArch64 implements pair accesses, which read/write two registers from/to memory with one instruction (up to 128 bits at a time).
I have a raspberry Model 3 - and I read, that it runs at 1,2GHz ...
So what can I do with that 1,2GHz when the timers run at 500 MHz?
Again, the 500 MHz clock source is used to generate external clock signals. Unless you feed it back into some GPIO input pin, you will not see this generated clock signal inside the SoC. I think, GPIO clocks are not interesting for your timing purpose.
From my point of view baremetal programming comes into play, when linux timings and jitter becomes inacceptable.
This can be one reason to use bare metal programming.
So what is the fastest jitterfree timing interval that I can use to drive a 64bit counter, that could be read aligned by a single instruction
Has been answered by Ultibo. Thanks!
Well, but memory mapped register access will probabely be different for each core, won't it?
I defined the memory range used for device registers as "outer shareable" in Circle64. Of course device access has to be serialised using locks where this is required.

rst
Posts: 267
Joined: Sat Apr 20, 2013 6:42 pm
Location: Germany

Re: Circle - C++ bare metal environment (with USB)

Mon May 15, 2017 2:46 pm

This function returns the current count value of the 19.2 MHz physical count register of the RPi 3 in Circle64:

Code: Select all

u64 GetPhysicalCounter (void)
{
	u64 ulCNTPCT_EL0;
	asm volatile ("mrs %0, cntpct_el0" : "=r" (ulCNTPCT_EL0));

	return ulCNTPCT_EL0;
}

Return to “Bare metal”

Who is online

Users browsing this forum: No registered users and 6 guests