otah007
Posts: 16
Joined: Tue Feb 12, 2013 3:14 pm

VideoCore returning 1 on framebuffer request

Thu Jun 07, 2018 1:21 am

I have been trying to get something to display on the screen using assembly and an RPI model B. Through much trial and error, the best I have managed is to draw a broken blue line horizontally across the centre of the screen. I have only succeeded in colouring the screen completely once, and resetting the Pi caused the previous blue line behaviour, so I can only assume I got lucky with some memory allocation or something.

I have written a minimal program that shows that the VC is returning 1 after I request a framebuffer. I can tell that the return value is 1 because I have written a subroutine that flashes the OK/ACT led in short and long flashes once to tell me the return value one bit at a time and I an getting 27 0s, 1 1, 3 0s, and 1 1, which corresponds to 0x00000011. However the last nibble is simply the channel (1) so the actual return value, after a right shift by 4, is 0x00000001. Additionally, the address returned by the VC seems to consistently be 0x5ebdc000, which when offset back into normal memory is 0x1ebdc000. This particular program draws absolutely nothing, even if I disregard the return value and try to draw anyway. Note that I am using a version 1 board, hence the use of the framebuffer channel over the property channel and the values of some constants.

I would appreciate it if anyone could help me understand what is going wrong.

Here is my code:

Code: Select all

.text
.global _start
_start:

    @ Set up GPIO
    LDR R0, =0x20200004
    MOV R1, #1
    LSL R1, #18
    STR R1, [R0]
    
    @ Long flash once
    MOV R7, #0x1800000
    BL flashLight
    BL delay

setup:
    
    @ Write to mailbox
    LDR R0, =0x2000b880
    LDR R1, =fb
    ADD R1, #0x40000000
    ORR R1, R1, #1

    write:
        LDR R2, [R0, #0x18]
        TST R2, #0x80000000
        BNE write

    STR R1, [R0, #0x20]

    @ Read from mailbox
    read1:
        read2:
            LDR R1, [R0, #0x18]
            TST R1, #0x40000000
            BNE read2
        LDR R1, [R0, #0]
        AND R2, R1, #0xf
        TEQ R2, #1
        BNE read1    

    @ Flash the return value
    MOV R0, R1
    BL flashReg
    MOV R7, #0x1800000
    BL delay
    
    @ Flash the returned address
    LDR R0, =fb
    LDR R0, [R0, #32]
    BL flashReg
    BL delay

    LDR R0, =0xfffffff0
    AND R1, R1, R0

    @ Loop if return is not 0
    CMP R1, #0
    BNE setup

draw:
    @ Draw to the screen
    LDR R0, =fb
    LDR R0, [R0, #32]
    SUB R0, R0, #0x40000000
    MOV R1, #640
    MOV R2, #480
    MUL R1, R2, R1
    MOV R2, #3
    MUL R1, R2, R1
    MOV R2, #0xa8

    loop:
        STRB R2, [R0], #1
        SUBS R1, R1, #1
        BNE loop

    B draw

inf:
    B inf

@ Flash R0's value one bit at a time
flashReg:
    PUSH {R0-R1, R7, LR}

    MOV R1, #0x80000000
    flashReg_loop:
        TST R0, R1
        MOVEQ R7, #0x300000     @ Short flash
        MOVNE R7, #0x600000     @ Long flash
        BL flashLight
        LSRS R1, #1
        BNE flashReg_loop

    POP {R0-R1, R7, PC}

error:
    BL setLight
    B error 

@ Turn OK on
setLight:
    LDR R0, =0x20200028
    MOV R1, #1
    LSL R1, #16
    STR R1, [R0]
    BX LR

@ Turn OK off
clearLight:
    LDR R0, =0x2020001C
    MOV R1, #1
    LSL R1, #16
    STR R1, [R0]
    BX LR

@ Pause for the time in R7
delay:
    MOV R0, R7
    delay_loop:
        SUBS R0, R0, #1
        BNE delay_loop
    BX LR

@ Flash OK for the time in R7
flashLight:
    PUSH {R0, R1, LR}
    BL setLight
    BL delay
    BL clearLight
    BL delay
    POP {R0, R1, PC}

.data
.align 16
@ Framebuffer
fb:
    .word 640   @ X res
    .word 480   @ Y res
    .word 640   @ Virtual X res
    .word 480   @ Virtual Y res
    .word 0
    .word 24    @ Bits per pixel
    .word 0
    .word 0
    .word 0     @ Return address
    .word 0
Last edited by otah007 on Thu Jun 07, 2018 10:06 am, edited 2 times in total.

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

Re: VideoCore returning 1 on framebuffer request

Thu Jun 07, 2018 4:44 am

Your code works fine you just forgot one thing called the stack pointer :-)

You merrily push and pop stuff onto the stack in flashReg and flashlight but nowhere did you set it.
Make it the first line after start like so ... it will start at 0x8000 and go down away from your code towards #0x0

Code: Select all

_start:
	MOV SP, #8000
Yes after all the slow flashing sequences and carry on you get a full grey screen

You also have a slight bug which is because you have copied others who have copied the valvers tutorials
The buffer write full status is read at offset 0x38 not 0x18. It works as is because the read status is never full and you only write a single command and so you get away with it.

So this

Code: Select all

write:
        LDR R2, [R0, #0x18]
        TST R2, #0x80000000
        BNE write
Should be this

Code: Select all

write:
        LDR R2, [R0, #0x38]
        TST R2, #0x80000000
        BNE write

Also for the record you don't need 2 labels read1: and read2: at the same point just because you have 2 loops, use one label.

otah007
Posts: 16
Joined: Tue Feb 12, 2013 3:14 pm

Re: VideoCore returning 1 on framebuffer request

Thu Jun 07, 2018 9:01 am

Thanks for your help, however the program still does not work properly.

I have added the stack pointer initialisation and modified where the status is read from when writing to the mailbox. However, I still get a return value of 1 after requesting a framebuffer. Ignoring this and writing anyway, I get a thick red line horizontally across the screen, which eventually turns blue and then my monitor loses the signal from the PI.

Do you know what could be causing this? Assuming it is not a faulty board, of course.

Edit: I managed to fill the entire screen blue for around half a second by looping for 0x10000000 bytes rather than simply 640*480*3 bytes. However the monitor immediately went no signal after this. The buffer size returned also seems to be too small. Writing only as far as the buffer allows produces the thick red line and does not change colour or cause the monitor to lose the signal.

Also I realised I made an error in the first post, I am using a model B not B+.

otah007
Posts: 16
Joined: Tue Feb 12, 2013 3:14 pm

Re: VideoCore returning 1 on framebuffer request

Thu Jun 07, 2018 9:43 am

I have found out a few things.

It seems that the size of the buffer is exactly 1920*64 bytes, regardless of the requested resolution or bit depth. Incidentally, my monitor has 1920x1200 resolution. Incrementing the value I write by one each time I write a byte draws a strange pattern, unfortunately it's too small to take a good photo of. The pattern has a length of 128 pixels, therefore it repeats 15 times across the screen. It starts off with green and blue stripes, then progresses to orange/yellow and purple stripes. It is like 32 tiny 4-pixel gradients of slowly changing and alternating colours. This pattern is the same regardless of the requested bit depth and resolution, and is stable.

I have no idea what is happening! Is it possible to use the property channel to get a framebuffer on RPI 1?

otah007
Posts: 16
Joined: Tue Feb 12, 2013 3:14 pm

Re: VideoCore returning 1 on framebuffer request

Thu Jun 07, 2018 12:19 pm

Problem solved! I had not been using a linker script! I can only assume the program binary was dumped somewhere unreasonable since I didn't specify a location. My previous programs all worked but they never talked to the VC so I assume that must also be part of the problem. Thank you for the help regardless.

Return to “Bare metal, Assembly language”

Who is online

Users browsing this forum: No registered users and 6 guests