0

Background Info

I am attempting to write a few bare metal programs and in theory I would eventually write a kernel. To get used to the environment, I found a tutorial that was known to work to could play around with later. I have installed the necessary toolchain as required on a Raspberry Pi 3 running jessie and use that for compilation. I installed jessie lite on my SD card and removed all files except for bootcode.bin, fixup.dat, and start.elf.

To compile, I followed the instructions in the tutorial and ran make on their solution code which generated a kernel.img which I then transferred to the SD card and inserted into my Pi 2. The green light came on initially and then went out and a large rainbow square (not the low power square) appeared on the screen where it appeared to hang and not proceed. As per this guide, a colored screen means that the kernel could not be executed. Is the tutorial up to date? did I include enough files?

Code

The solution code to ok2:

/******************************************************************************
*   main.s
*    by Alex Chadwick
*
*   A sample assembly code implementation of the ok02 operating system, that 
*   simply turns the OK LED on and off repeatedly.
*   Changes since OK01 are marked with NEW.
******************************************************************************/

/*
* .section is a directive to our assembler telling it to place this code first.
* .globl is a directive to our assembler, that tells it to export this symbol
* to the elf file. Convention dictates that the symbol _start is used for the 
* entry point, so this all has the net effect of setting the entry point here.
* Ultimately, this is useless as the elf itself is not used in the final 
* result, and so the entry point really doesn't matter, but it aids clarity,
* allows simulators to run the elf, and also stops us getting a linker warning
* about having no entry point. 
*/
.section .init
.globl _start
_start:

/* 
* This command loads the physical address of the GPIO region into r0.
*/
ldr r0,=0x20200000

/*
* Our register use is as follows:
* r0=0x20200000 the address of the GPIO region.
* r1=0x00040000 a number with bits 18-20 set to 001 to put into the GPIO
*               function select to enable output to GPIO 16. 
* then
* r1=0x00010000 a number with bit 16 high, so we can communicate with GPIO 16.
* r2=0x003F0000 a number that will take a noticeable duration for the processor 
*               to decrement to 0, allowing us to create a delay.
*/
mov r1,#1
lsl r1,#18

/*
* Set the GPIO function select.
*/
str r1,[r0,#4]

/* 
* Set the 16th bit of r1.
*/
mov r1,#1
lsl r1,#16

/* NEW
* Label the next line loop$ for the infinite looping
*/
loop$: 

/*
* Set GPIO 16 to low, causing the LED to turn on.
*/
str r1,[r0,#40]

/* NEW
* Now, to create a delay, we busy the processor on a pointless quest to 
* decrement the number 0x3F0000 to 0!
*/
mov r2,#0x3F0000
wait1$:
    sub r2,#1
    cmp r2,#0
    bne wait1$

/* NEW
* Set GPIO 16 to high, causing the LED to turn off.
*/
str r1,[r0,#28]

/* NEW
* Wait once more.
*/
mov r2,#0x3F0000
wait2$:
    sub r2,#1
    cmp r2,#0
    bne wait2$

/*
* Loop over this process forevermore
*/
b loop$
  • 2
    What custom kernel? All you have is an assembler program intended to toggle LEDs on early model Pis. – joan Apr 9 '17 at 19:42
  • 2
    You need to identify the changes between early model Pis and models 2 and 3. Anyone reading the question title would assume you are trying to build a custom kernel. – joan Apr 9 '17 at 19:46
  • 3
    You have two issues to resolve. 1) The Pi3 has no writeable LEDs so you will need to add your own LED plus resistor to the expansion header. 2) The Pi2/Pi3 GPIO peripheral are at a different memory address compared with the other Pi models. As a matter of fact I'm fairly sure your particular question (bare metal LED example program for Pi2/Pi3) has already been asked and answered on this site. It certainly has been on raspberrypi.org. – joan Apr 9 '17 at 19:58
  • 2
    You would ensure you ask the right question and use the correct search terms. – joan Apr 9 '17 at 19:59
  • 3
    For some more recent information (I actually got the link from this site), try http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/. – anonymoose Apr 9 '17 at 21:04
2

Your question includes this

and inserted into my Pi 2

At the very top of the tutorial page, you linked to in red is the following:

This course has not yet been updated to work with the Raspberry Pi models B+ and A+. Some elements may not work, in particular the first few lessons about the LED. It has also not been updated for Raspberry Pi v2.

In particular, I draw your attention to the last sentence. So no the tutorial has not been updated and is not expected to work on a Pi 2.

  • yes, but the same basic principle applies – dalearn Apr 9 '17 at 19:36
  • 1
    @dalearn: Yes, the code will be similar. But it will not be the same. Quite a few things changed. For example, the GPIO is accessed in a different way - and I believe the built-in LED is on a different pin. Also, the tutorial I linked to in a comment on the question itself lists very different commands just to compile code for the different models. – anonymoose Apr 9 '17 at 21:08
-2

I guess the following code works for RPi2B

/******************************************************************************
*   main.s
*    by Alex Chadwick
*           
*   A sample assembly code implementation of the ok02 operating system, that 
*   simply turns the OK LED on and off repeatedly.
*   Changes since OK01 are marked with NEW.
*
*       -- RPI2 version
******************************************************************************/

/*
* .section is a directive to our assembler telling it to place this code first.
* .globl is a directive to our assembler, that tells it to export this symbol
* to the elf file. Convention dictates that the symbol _start is used for the 
* entry point, so this all has the net effect of setting the entry point here.
* Ultimately, this is useless as the elf itself is not used in the final 
* result, and so the entry point really doesn't matter, but it aids clarity,
* allows simulators to run the elf, and also stops us getting a linker warning
* about having no entry point. 
*/
.section .init
.globl _start
_start:

/* 
* This command loads the physical address of the GPIO region into r0.
*/
ldr r0,=0x3f200000

/*
* Our register use is as follows:
* r0=0x3f200000 the address of the GPIO region.
* r1=0x00200000 a number with bits 21-23 set to 001 to put into the GPIO
*               function select to enable output to GPIO 47. 
* then
* r1=0x00010000 a number with bit 15 high, so we can communicate with GPIO 47.
* r2=0x003F0000 a number that will take a noticeable duration for the processor 
*               to decrement to 0, allowing us to create a delay.
*/
mov r1,#1
lsl r1,#21

/*
* Set the GPIO function select.
*/
str r1,[r0,#24]

/* 
* Set the 15th bit of r1.
*/
mov r1,#1
lsl r1,#15

/* NEW
* Label the next line loop$ for the infinite looping
*/
loop$: 

/*
* Set GPIO 47 to low, causing the LED to turn on.
*/
str r1,[r0,#44]

/* NEW
* Now, to create a delay, we busy the processor on a pointless quest to 
* decrement the number 0x3F0000 to 0!
*/
mov r2,#0x3F0000
wait1$:
    sub r2,#1
    cmp r2,#0
    bne wait1$

/* NEW
* Set GPIO 47 to high, causing the LED to turn off.
*/
str r1,[r0,#32]

/* NEW
* Wait once more.
*/
mov r2,#0x3F0000
wait2$:
    sub r2,#1
    cmp r2,#0
    bne wait2$

/*
* Loop over this process forevermore
*/
b loop$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.