Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

What am i doing wrong when accessing and using a framebuffer

Thu Jun 01, 2017 11:22 pm

I have done some research and I have found that:

Using channel 8 works better than using channel 1, so that's the channel that I am using.
viewtopic.php?f=72&t=36619

The init structure for the framebuffer must have all tags, you cannot send the info one tag at a time (discovered by trial and error).

I assume I am initializing things correctly because I first get the coloured rectangle and after a delay (a delay I added on purpose) I get a black screen. However I am trying to draw white pixels to the screen and nothing of what I try seems to work. No matter what I do the screen remains black.

This is what I am trying to do:

Code: Select all

void init_display()
{
  write_to_mailbox((uint32_t) &t, PTAG_ARM_TO_VC);

  for(int i=0; i<t.fb_size; i++)
  {
    *(volatile uint32_t *)(t.fb_ptr + i) = 0xFFFF;
  }
}
If you want to look at the full code, this is the github:
https://github.com/Makogan/PiOS

Thank you in advance

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

Re: What am i doing wrong when accessing and using a framebu

Fri Jun 02, 2017 10:04 am

Makogan wrote:No matter what I do the screen remains black.
Normally the mailbox request will return t.fb_ptr as a bus address and you need to convert it to a physical address before using it. This is simply a matter of ANDing it with NOT(0xC0000000) like this:

Code: Select all

 physical_addres = bus_address AND NOT(0xC000000)
Sometimes things might seem to work without doing that but sooner or later it will break so it is best to get used to doing it for any address returned from the firmware.
Ultibo.org | Make something amazing
https://ultibo.org

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Fri Jun 02, 2017 8:40 pm

Ultibo wrote:
Makogan wrote:No matter what I do the screen remains black.
Normally the mailbox request will return t.fb_ptr as a bus address and you need to convert it to a physical address before using it. This is simply a matter of ANDing it with NOT(0xC0000000) like this:

Code: Select all

 physical_addres = bus_address AND NOT(0xC000000)
Sometimes things might seem to work without doing that but sooner or later it will break so it is best to get used to doing it for any address returned from the firmware.
As far as I know and according to the github mailbox firmware page: https://github.com/raspberrypi/firmware ... -mailboxes

This is not true for channel 8 (which is the one I am using). I'll nevertheless give it a try and see what happens.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 12:58 am

This doesn't seem to be working at all

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

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 1:14 am

Makogan wrote:This doesn't seem to be working at all
You'll probably need to do some debugging, what is the address returned in t.fb_ptr? Is the mailbox request actually succeeding (your code doesn't seem to check the result)?
Ultibo.org | Make something amazing
https://ultibo.org

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 2:11 am

If only I could. I discovered seggers does not support the cortex a53 yet and I am working on a pi 3, and I have been trying to find a way to use my jtag device to trace the registers, I even tried using openocd but I keep failing . SO far I am blind I cannot trace my code.

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

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 3:01 am

Your write to mailbox routine is wrong :-)

For the record the returned frame buffer is definitely a bus address as per what Ultibo told you.

Your struct values are dorked .... Try:

Code: Select all

  .tag4 = ALLOCATE,
  .buff_size4 = 8,
  .val_length4 = 4,    // response will be 4 bytes
  .fb_ptr = 16,           // Tell it align 16
.fb_size = 0,             //  Value will be written here
I suspect the documentation you have used may be wrong looking at what you have written above.
Last edited by LdB on Sat Jun 03, 2017 3:45 am, edited 11 times in total.

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

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 3:13 am

Makogan wrote:I discovered seggers does not support the cortex a53 yet and I am working on a pi 3, and I have been trying to find a way to use my jtag device to trace the registers,
You certainly don't need jtag for debugging, dwelch67 has a huge collection of examples that show how to output information to the serial port so you can display the results of your code and work out where the problem lies.
Ultibo.org | Make something amazing
https://ultibo.org

User avatar
rpdom
Posts: 11566
Joined: Sun May 06, 2012 5:17 am
Location: Essex, UK

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 5:32 am

Ultibo wrote:
Makogan wrote:I discovered seggers does not support the cortex a53 yet and I am working on a pi 3, and I have been trying to find a way to use my jtag device to trace the registers,
You certainly don't need jtag for debugging, dwelch67 has a huge collection of examples that show how to output information to the serial port so you can display the results of your code and work out where the problem lies.
When I started with bare metal on the Pi, I initially used a GPIO LED for debugging (which was tedious, but worked), then wrote a simple driver for a 16x2 LCD module with register dump routines. That was invaluable when getting my frame buffer code working. That was all on a Pi 1, I haven't had time to work on any bare metal on a Pi 2 or 3 yet.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Sat Jun 03, 2017 11:50 pm

LdB wrote:Your write to mailbox routine is wrong :-)

For the record the returned frame buffer is definitely a bus address as per what Ultibo told you.

Your struct values are dorked .... Try:

Code: Select all

  .tag4 = ALLOCATE,
  .buff_size4 = 8,
  .val_length4 = 4,    // response will be 4 bytes
  .fb_ptr = 16,           // Tell it align 16
.fb_size = 0,             //  Value will be written here
I suspect the documentation you have used may be wrong looking at what you have written above.
Why is it wrong (not a challenge I legit want to know what the problem is to correct it ASAP)

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

Re: What am i doing wrong when accessing and using a framebu

Sun Jun 04, 2017 8:49 am

Looking at your struct labels the result comes back in what you describe as fb_size. You don't use that you use fb_ptr in your write routine which is not where the return will be. Why did you label them as such? The return is also only 4 bytes which you have entered a value of 8.

So for some reason you think the return is 8 bytes and you think the result is going to be in fb_ptr in your struct which it won't. The documentation you seem to be using is for old firmware.

I have given you what the bytes for the tag are
4 bytes = 0x00040001
4 bytes = 8 // Set value of 8 which is size of data we are providing
4 bytes = 4, // Response will be 4 bytes .. this will turn to 0x8000004 if successful
4 bytes = 16, // Tell VC to align 16 the buffer (On old firmware return was always align 16) does not have to be nowdays
4 bytes = 0, // Framebuffer return value will be written here

I know that works and I got the details from the linux driver.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Sun Jun 04, 2017 10:23 pm

LdB wrote:Looking at your struct labels the result comes back in what you describe as fb_size. You don't use that you use fb_ptr in your write routine which is not where the return will be. Why did you label them as such? The return is also only 4 bytes which you have entered a value of 8.

So for some reason you think the return is 8 bytes and you think the result is going to be in fb_ptr in your struct which it won't. The documentation you seem to be using is for old firmware.

I have given you what the bytes for the tag are
4 bytes = 0x00040001
4 bytes = 8 // Set value of 8 which is size of data we are providing
4 bytes = 4, // Response will be 4 bytes .. this will turn to 0x8000004 if successful
4 bytes = 16, // Tell VC to align 16 the buffer (On old firmware return was always align 16) does not have to be nowdays
4 bytes = 0, // Framebuffer return value will be written here

I know that works and I got the details from the linux driver.
Because according to:

https://github.com/raspberrypi/firmware ... -interface

The response is 8 bytes, where the first is the size of the framebuffer (returned on the same section of the struct as the alignment) and the second is the address itself (returned where you specified).

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

Re: What am i doing wrong when accessing and using a framebu

Mon Jun 05, 2017 2:54 am

Here look => https://www.codeproject.com/Articles/11 ... he-Pi-part

See I have no problem writing to the framebuffer nor does Ultibo ... try the code from either of us :-)
David Welch and Peter Lemon also have repos with working code.

We all just followed what the Linux driver did which ultimately is the authority to follow because it is the O/S the Pi foundation supports, they don't really support baremetal access and all documentation needs to be taken with a grain of salt. The bootstrap loader is continually changing and I am not sure the documentation is ever fully in sync. If you look at the post by Ultibo on the leds on the Pi3 there again are changes that you won't find documented anywhere he gleaned it off the linux driver changes for the Pi3.

The differences I can see with your code to mine which mimics the linux driver is the struct values that are loaded are different and you don't wait for the response from the channel command write. The problem must lie in one of those two areas.

What we can tell you is tag 0x40001 works if you use it like the Linux driver does and you should always use the linux driver as the ultimate guide not documentation.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Mon Jun 05, 2017 9:01 pm

I am sorry but, where is the linux driver for the raspberry pi 3?

dwelch67
Posts: 825
Joined: Sat May 26, 2012 5:32 pm

Re: What am i doing wrong when accessing and using a framebu

Mon Jun 05, 2017 10:39 pm

Implied from two posts above

https://github.com/raspberrypi

and there is a linux repo

dwelch67
Posts: 825
Joined: Sat May 26, 2012 5:32 pm

Re: What am i doing wrong when accessing and using a framebu

Mon Jun 05, 2017 10:40 pm

also implied by the baremetal resources pinned topic for this forum. doesnt say linux sources but shows there is a raspberry pi github account/user.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Tue Jun 06, 2017 12:18 am

I just realised something, I am using an HDMI cable to try to get the output out. Will this work? Is the videocore HDMI ready?

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

Re: What am i doing wrong when accessing and using a framebu

Tue Jun 06, 2017 3:01 am

The HDMI is the normal video output on the Pi, you would have to do fancy footwork with the config file to make it not boot like that :-)

So lets be precise here, all my screencaps are on a HDMI monitor and I don't do anything other than use tag system set the resolution and get the framebuffer which is exactly what you are trying to do. It works like that for all the main 3 models of Pi.

EDIT: Okay modifying this because I am pretty sure I have worked out why your code doesn't work.

This is your current code, you check the mailbox isn't full (a plus you obviously looked at some code from a source) but you write the mailbox and run away blindly that isn't right. You are going to have a mailbox response stuck in a queue pending back to you at best. Each time you post on the mailbox it gives you a response even if you don't want to use the response I suggest you at least clear it. Code house keeping is you should also clear the lower 4 channel bits before OR'ing the channel on in case you make an error at the upper level so you don't get the wrong tag channel. Perhaps that is what you were trying to do with the commented out left shift 4 but it just needs to be an AND NOT 0xF operation. The address you are providing as the message is balign 16 for that exact reason to make sure those channel bits are clear.

Code: Select all

void write_to_mailbox(uint32_t message, Channel channel)
{
  uint32_t status;

  do
    status = *(volatile uint32_t *)(MAIL_BASE + IO_BASE + 0x18);
  while((status & MAIL_FULL));

  *(volatile uint32_t *)(MAIL_BASE + IO_BASE + 0x20) = ((uint32_t)(message) /*<< 4)*/ | (uint32_t)(channel));
}
Looking at your code you already have the function "read_from_mailbox" which would do fine to clear the response.

There is a funny thing that could be happening with your code because you don't wait for the response confirmation you post and blindly run. Then the fun begins after you post the tag command you go into this check.

Code: Select all

  while(t.request != 0x80000000)
  {
    blink();
}
Well t.request might well be not set initially because you didn't wait for the mailbox to acknowledge a response. You didn't declare t.request as volatile so the compiler is well within it's right to hold that first read value and just loop using that first read value. That is even if t.request later changes you will never see it .. it will get stuck there looping infinitely using the 1st value read.

So can I ask does it get stuck in that loop all the time?

Try making t.request volatile for me :-)
That code won't work properly on any good compiler the loop is pointless it will only ever reflect the first test result.
It requires this:

Code: Select all

struct temp
{
  int size;
volatile int request;
Can I also strongly suggest you turn those int's in that struct to uint32_t like you have used elsewhere so we know for certain they are always 32 bits. Your totally relying on an int to be 32bits which isn't guaranteed and if you want to compile in 64bit mode for example that is drop dead.

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Wed Jun 07, 2017 9:46 pm

Hello ldb. I made the modifications you suggested, the code now looks as:

Code: Select all

void init_display()
{
  wait(0x100000);

  write_to_mailbox((uint32_t) &t , (Channel)(PTAG_ARM_TO_VC));
  read_from_mailbox(PTAG_ARM_TO_VC);

  while(t.request != 0x80000000)
  {
    blink();
  }

  for(int i=0; i<10; i++)
  {
    *(volatile uint32_t *)((t.fb_ptr & ~0xC0000000) + i*2) = 0xFFFF;
  }
}
And the struct declaration:

Code: Select all

struct temp
{
  volatile uint32_t size;
  volatile uint32_t request;

  volatile uint32_t tag1;
  volatile uint32_t buff_size1;
  volatile uint32_t val_length1;
  volatile uint32_t widthP;
  volatile uint32_t heightP;

  volatile uint32_t tag2;
  volatile uint32_t buff_size2;
  volatile uint32_t val_length2;
  volatile uint32_t widthV;
  volatile uint32_t heightV;

  volatile uint32_t tag3;
  volatile uint32_t buff_size3;
  volatile uint32_t val_length3;
  volatile uint32_t depth;

  volatile uint32_t tag4;
  volatile uint32_t buff_size4;
  volatile uint32_t val_length4;
  volatile uint32_t fb_size;   
  volatile uint32_t fb_ptr;
 
  volatile uint32_t end;
};
I never see the LED blinking (aside from the boot step where it blinks once), so not only does it not get stuck on that loop, it seems the code is getting stuck somewhere else.

After those modifications I am still blind :p

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

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 2:46 am

Sigh, ok I have not spotted problem. Let me grab the code from your repo and compile it.

What you have now looks right and I would have expected to put some colour line out to screen :-)

Just checking you know it won't be white because you wrote 0xFFFF out not 0xFFFFFFFF it's RGBA in 32bit colour depth mode.

UPDATE: Ok first thing I suggest is you turn your error level up on your compiler. On GCC compile with -Wall option. Now I have to work out whats going on with your linker directive file.

structural checks:

mailbox.cpp changed to mailbox.c ... it is a c file not a cpp file, my structural checker wont allow
in kernel_main.c changed #include <mailbox.h> to #include "mailbox.h" ... not in preprocessor file path, my structural checker wont allow
in mailbox.h changed #include <peripherals.h> to #include "..\boot\peripherals.h" ... not in preprocessor file path, my structural checker wont allow
in mailbox.c changed #include <mailbox.h> to #include "mailbox.h" ... not in preprocessor file path, my structural checker wont allow
in kernel_main.c line 46 "volatile int tst = 0;" commented out as not in use

errors:

mailbox.c Line 29 volatile Mail_Message_LED led_message
Mail_Message_LED is not a type it is a struct
changed:
volatile struct Mail_Message_LED led_message

mailbox.c Line 56 "void write_to_mailbox(uint32_t message, Channel channel)" does not match header mailbox.h
void write_to_mailbox(uint32_t message, uint32_t channel); is definition in mailbox.h
changed: mailbox.h
void write_to_mailbox(uint32_t message, Channel channel);

mailbox.c Line 148 "volatile temp t __attribute__ ((aligned (16)))"
temp is not a type it is a struct
changed:
volatile struct temp t __attribute__ ((aligned (16)))

mailbox.c Line 150 ".size = sizeof(temp)"
temp is not a type it is a struct
changed:
.size = sizeof(struct temp)

mailbox.c Line 216 "volatile Mail_Message_FB message;"
Mail_Message_FB is not a type it is a struct
changed:
volatile struct Mail_Message_FB message;

mailbox.c Line 182 " message.messageSize = sizeof(Mail_Message_FB);"
Mail_Message_FB is not a type it is a struct
changed:
message.messageSize = sizeof(struct Mail_Message_FB);

mailbox.c Line 229 function test return without a value
you declare test returns an integer .... "int test" but no value is returned
changed:
return 0; added before function exit


kernel_main.c Line 84 .. function "wait" is already defined at Line 179 in mailbox.c
The linker can see both definitions of wait
changed: Line 179 in mailbox.c
static void wait(uint32_t time)

That got me compiling but now I get
error: the input file 'kernel.elf' has no sections

So the linker file kernel.ld has issues ... looking at that now.

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

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 4:26 am

Okay problem with linker was I have throw unused sections turned on and you have no keep section on the boot.s code which goes into code section .init

The fix was to do this in kernel.ld
.init 0x8000 :
{
KEEP(*(.init))
}

I also strongly suggest this change in the linker directive as GCC may label some text sections
.text :
{
*(.text .text.* .gnu.linkonce.t.*)
}

I would also strongly suggest you not align 16 the whole data block. You have attributes on the block you need align16 I would leave the linker at align 4

It just tells the linker to always keep section .init which is your start code, that should avalache out to any code it calls. To check that I map kernel.elf and I get what I expected in my map file
00008000 T _start
0000807c T init_display
00008008 T kernel_main
00008130 D led_message
00008014 T set_LED
00008150 D t

So now I can check your code and I ran straight into first problem you don't get the Pi out of HYP mode in boot.s :-)

Makogan
Posts: 71
Joined: Tue May 16, 2017 9:17 pm

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 4:55 am

Hello LDB, first you do not know how grateful I am that you are spending any amount of time helping me with this. To prevent future headaches, I got my hand on a pi 2 and was doing some testing with it so the very latest ode on my github is actually for a pi 2 (I swapped fb_ptr and fb_size again, so on the latest repo those are "wrong" for the pi 3). I also changed color depth to 32.

As a question, why would I need to switch out of hyp mode if I am just trying to write to the screen? shouldn't I have MORE power in hypervisor mode?

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

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 5:12 am

You need to bring the floating point unit online it starts offline and sort of dangling. You can't touch those registers to do that in HYP mode. The mode is about security not power.

On the Pi1 you can get away with it as it won't crash (I think) until something in C tries to access the FPU. On the Pi2/3 when I was playing around if you don't specifically put the FPU to one of the cores it gets very unstable. I seem to remember David Welch saying something about the instability but I just always do it now. As most of this stuff isn't documented you need to sort of do things just in case because it has bitten you in butt before.

Are you also aware you set the stack pointer to decimal 8000 not 0x8000 which is what I think you meant to do. Not fatal just weird. You also don't clear the C BSS segment so don't rely on things being zero in the C code they will start in some random state not zero.

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

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 7:22 am

Your code now works when I fix up Boot.S and I win and the documentation is wrong
I cut and paste my font and text routines into your code
Image

That is the order of the struct
.tag4 = ALLOCATE,
.buff_size4 = 8,
.val_length4 = 4,
.fb_ptr = 16,
.fb_size = 0,

This is the print line to produce the screen
printf("fb_ptr: %8lX fb_size: %8lX\n", t.fb_ptr, t.fb_size);

To write the text I use this to create a pointer for my font routines
RPi_FrameBuffer = t.fb_size & ~0xC0000000;

It looks like the documentation has the two struct fields in reverse.

Are you happy to fix up Boot.S or do you want me to make a minimal one for you?

Update: I got rid of most of my startup and you had me going with why your pixel write code was producing a single pixel not a line. I had adjusted it to use the right field, but then I realized you do love your int's :-)
0xFFFF is cyan in 32 bit colour for the record

Code: Select all

for(uint32_t i=0; i<10000; i++) {
    *(volatile uint32_t *)((t.fb_size & ~0xC0000000) + i*4) = 0xFFFF;
 }
Produces a cyan bar at the top, which is what I guess you were expecting.
Image

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

Re: What am i doing wrong when accessing and using a framebu

Thu Jun 08, 2017 8:17 am

Thought I might as well finish the job and others might be able to use
added a BSS section to your linker file. I threw it in after your data section.

Code: Select all

.bss :
    {
        . = ALIGN(4);
        __bss_start__ = .;
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN(4);
        __bss_end__ = .;
   }
The minmal boot.s

Code: Select all

//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/*
* Authors: Camilo Talero Nasir Osman
*
*
* File type: ARM Assembly
*
* This file contains assembly code needed to initialize the hardware of the
*Raspberry PI™ before execution of the main kernel loop
*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.section .init
.global _start

_start:
        ldr     sp, =0x8000 // initialize stack pointer
        //bl      enable_jtag // Enable JTAG


 /* CHANGES ADDED BY LdB */
        bl  RPi_CheckAndExitHypModeToSvcMode;	;@ First check for HYP_MODE and if in it drop out to SRV_MODE

    	ldr sp, =0x8000					;@ Reset the stack pointer for that mode


@"================================================================"
;@ PI NSACR regsister setup for access to floating point unit
;@ Cortex A-7 => Section 4.3.34. Non-Secure Access Control Register
;@ Cortex A-53 => Section 4.5.32. Non-Secure Access Control Register
;@"================================================================"
	mrc p15, 0, r0, c1, c1, 2				;@ Read NSACR into R0
	cmp r0, #0x00000C00						;@ Access turned on or in AARCH32 mode and can not touch register or EL3 fault
	beq .free_to_enable_fpu
	orr r0, r0, #0x3<<10					;@ Set access to both secure and non secure modes
	mcr p15, 0, r0, c1, c1, 2				;@ Write NSACR
;@"================================================================"
;@ Bring fpu online
;@"================================================================"
.free_to_enable_fpu:
	mrc p15, 0, r0, c1, c0, #2				;@ R0 = Access Control Register
	orr r0, #(0x300000 + 0xC00000)			;@ Enable Single & Double Precision
	mcr p15,0,r0,c1,c0, #2					;@ Access Control Register = R0
	mov r0, #0x40000000						;@ R0 = Enable VFP
	vmsr fpexc, r0							;@ FPEXC = R0
 ;@"================================================================"
;@ Enable L1 cache
;@"================================================================"
    mrc p15,0,r0,c1,c0,0					;@ R0 = System Control Register

/*==========================================================================}
;{			  RASPBERRY PI LEVEL L1 CACHE CONSTANTS DEFINED				    }
;{=========================================================================*/
#define SCTLR_ENABLE_DATA_CACHE			0x4
#define SCTLR_ENABLE_BRANCH_PREDICTION	0x800
#define SCTLR_ENABLE_INSTRUCTION_CACHE  0x1000

    // Enable caches and branch prediction
    orr r0, #SCTLR_ENABLE_BRANCH_PREDICTION
    orr r0, #SCTLR_ENABLE_DATA_CACHE
    orr r0, #SCTLR_ENABLE_INSTRUCTION_CACHE

    mcr p15,0,r0,c1,c0,0					;@ System Control Register = R0
;@"================================================================"
;@ Now Clear the .BSS segment as the C compiler expects us to do
;@"================================================================"
	ldr   r0, =__bss_start__
	ldr   r1, =__bss_end__	
	mov   r2, #0
.clear_bss:
    cmp   r0, r1
    bge   .clear_bss_exit
    str   r2, [r0]
	add   r0, r0, #4
    b .clear_bss
.clear_bss_exit: 

 /* END OF CHANGES ADDED BY LdB */
     
	 
	 
	 b       kernel_main


 /* CODED ADDED BY LdB */
/* "PROVIDE C FUNCTION: bool RPi_CheckAndExitHypModeToSvcMode (void);" */
.section .text.RPi_CheckAndExitHypModeToSvcMode, "ax", %progbits
.balign	4
.type RPi_CheckAndExitHypModeToSvcMode, %function
.syntax unified
.arm
;@"================================================================"
;@ RPi_CheckAndExitHypModeToSvcMode -- Composite Pi1, Pi2 & Pi3 code
;@ Return: Drops out from HYP_MODE to SRV_MODE and FIQ/IRQ disabled
;@         If not in HYP_MODE will exit unchanged
;@"================================================================"
RPi_CheckAndExitHypModeToSvcMode:
	mrs r0, cpsr							;@ Fetch the cpsr register             
	and r1, r0, #0x1F						;@ Mask off the arm mode bits in register                            
 	cmp r1, #0x1A							;@ check we are in HYP_MODE AKA register reads 1A							
	beq .WeHaveHyperMode
	mov r0, #0;								;@ return false
	bx lr									;@ Return we are not in hypermode
.WeHaveHyperMode:
	bic r0, r0, #0x1F						;@ Clear the mode bits		             
	orr r0, r0, #0xD3						;@ We want SRV_MODE with IRQ/FIQ disabled			
	mov r1, #0								;@ Make sure CNTVOFF to 0 before exit HYP mode
	mcrr p15, #4, r1, r1, cr14				;@ We do not want our clocks going fwd or backwards
	orr r0, r0, #0x100						;@ Set data abort mask	 
	msr spsr_cxsf, r0						;@ Load our request into return status register
	mov r0, #1;								;@ return true
	/* I borrowed this trick from Ultibo because ARM6 code running on an ARM7/8 needs this opcode  */
	/* The ARM6 compiler does not know these instructions so it is a way to get needed opcode here */
    /* So our ARM6 code can drop an arm7 or arm8 out of HYP mode and run on an ARM7/8.             */
 	/* Native ARM7/8 compilers already understand the OPCODE but do not mind it this way either	   */        
	.long 0xE12EF30E						;@ "msr ELR_hyp, lr"
	.long 0xE160006E						;@ "eret"	
;@ No ltorg data required for this function 
.size	RPi_CheckAndExitHypModeToSvcMode, .-RPi_CheckAndExitHypModeToSvcMode
Your code works just fine after that ... and I am done here :-)

Return to “Bare metal”

Who is online

Users browsing this forum: No registered users and 4 guests