1

I am trying to do some bare metal coding for the RBPI model 3. I have some assembly code that works (all it does is turning the green led on indefinitely) that I took from somewhere. I am trying to translate the arm assembly code to C. However the light doesn't turn on green for my C code. I was hoping someone could tell me what I am doing wrong.

This is the assembly code:

@;
@; This turns on the ACT LED for the Raspberry Pi 3 Model B v1.2
@;
@; The ACT LED is no longer wired directly to a GPIO pin and now belongs on
@; the GPIO expander, which is controlled by the GPU. In order to communicate
@; with the GPIO expander, we need to use the GPU's mailbox interface (in
@; particular, we need to send a message to the property tag channel).
@;
@; Mailbox base address: 0x3f00b880
@; Mailbox 1 write address: [0x3f00b880, #0x20]
@; Property tag channel: 8
@; Property tag ID: 0x00038041 (SET_GPIO_STATE)
@; Property tag message: 130 1 (ACT_LED pin number followed by state)
@;

.global _start @; Make _start available to the outside world

.section .data
.align 4 @; This ensures lowest 4 bits are 0 for the following label
PropertyInfo:
  @; = Message Header =
  .int PropertyInfoEnd - PropertyInfo @; Calculate buffer size
  .int 0 @; Request code: Process Request
  @; = Tag Header =
  .int 0x00038041 @; Tag ID (SET_GPIO_STATE)
  .int 8 @; Value buffer size
  .int 0 @; Request/response size
  @; = Tag Value Buffer =
  .int 130 @; ACT_LED pin number
  .int 1 @; Turn it on
  .int 0 @; End tag
PropertyInfoEnd:

.section .text
_start:
  mailbox .req r0 @; Alias mailbox to r0
  ldr mailbox, =0x3f00b880 @; Load the mailbox's base address into r0

  wait1$:
    status .req r1 @; Alias status to r1
    ldr status, [mailbox, #0x18] @; Load the Mailbox 0 status address
    tst status, #0x80000000 @; Check the status against the FULL bit
    .unreq status @; Unset the alias
    bne wait1$ @; Keep checking the mailbox until it isn't full

  message .req r1 @; Alias message to r1
  ldr message, =PropertyInfo @; Load r1 with address of our message buffer
  add message, #8 @; Put the channel in the last 4 bits
  str message, [mailbox, #0x20] @; Put the message in the mailbox
  .unreq message @; Unset the alias

  hang:
    b hang @; Give the CPU something to do ad infinitum

And this is my C implementation:

#define REGISTERS_BASE 0x3F000000
#define MAIL_BASE 0xB880  // Base address for the mailbox registers
// This bit is set in the status register if there is no space to write into the mailbox
#define MAIL_FULL 0x80000000
// This bit is set in the status register if there is nothing to read from the mailbox
#define MAIL_EMPTY 0x40000000

int MailboxMessage[8];



/** Main function - we'll never return from here */
int main(void) __attribute__((naked));
int main(void)
{
  MailboxMessage[0] = 32;
  MailboxMessage[1] = 0;
  MailboxMessage[2] = 0x00038041;
  MailboxMessage[3] = 8;
  MailboxMessage[4] = 0;
  MailboxMessage[5] = 130;
  MailboxMessage[6] = 1;
  MailboxMessage[7] = 0;

  int *mailbox = (void*)(REGISTERS_BASE + MAIL_BASE);

  int status;

  do
  {
    status = *mailbox;
  }
  while(status != MAIL_FULL);

  int *mailbox_led = (void*) &MailboxMessage;

  while(1);
}
Makogan
  • 8,208
  • 7
  • 44
  • 112
  • what does the disassembly show of the compiled code? is it functionally the same as the one you borrowed? – old_timer May 18 '17 at 02:47
  • it might fit better on https://reverseengineering.stackexchange.com/ – phuclv May 18 '17 at 03:00
  • I have never disasembled a binary before, which tool is available on linux? – Makogan May 18 '17 at 03:01
  • If you don't tell the compiler that `*mailbox` might probably change from outside the influence of the program (using `volatile`) the compiler will optimize out that read. – tofro May 18 '17 at 07:12
  • Also, `while (status != MAIL_FULL)` does **not** check for a set `FULL` bit, but rather does something different... – tofro May 18 '17 at 07:15
  • so i should be using the bitwise & operator instead? – Makogan May 18 '17 at 20:36

0 Answers0