gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > Burst Boot & GAS

#29438 - Joe_Sextus - Sat Nov 20, 2004 1:19 am

I was wondering if any one has implemented Burst Boot in GNU's syntax. I am not very familar with the ARM assembler and when I translated the Burst Boot code for A22i to GAS syntax the program never (as for as I can tell) receives any SIO IRQs. I am using DevKitArm_r8.

Here's my Code:
Code:

  .ARM
  .ALIGN
  .GLOBAL main

msg_boot:  .ascii "BOOT"
msg_okay:  .ascii "OKAY"
msg_brst:  .ascii "BRST"

irq_handler:
  mov  r8, #0x03E0
  strh r8, [r5]
 
  mov  r1, #0x4000000             @> Base of address of all I/O Registers
 
  ldr  r0, [r1, #0x200]           @\ Read REG_IE & REG_IF
  and  r0, r0, r0, lsr #16        @] check for handled IRQs
  add  r3, r1, #0x200             @] and place back in REG_IF
  strh r0, [r3, #2]               @/
 
  ldrh r3, [r1, #-8]              @\
  orr  r3, r3, r0                 @] Mirror REG_IF at REG_IRQ_MIRROR (0x3007FF8)
  strh r3, [r1, #-8]              @/
 
  and   r3, r0, #0x80             @\
  cmp   r3, #0x80                 @] Check for the Burst Boot (SIO) IRQ
 
  mov r11, r11
  moveq  r8, #0x001F
  streqh r8, [r5]
  ldreq r2, [r1 , #0x120]         @]
  ldreq r3, msg_brst              @] if "BRST" received jump to the
  cmpeq r2, r3                    @] Burst Boot Handler
  mov r11, r11
 
  beq   burst_boot                @/
 
  @Insert Additional IRQ Handler Code Hear
 
  bx   lr                         @> return
 
burst_boot:   @requires icoming r1=0x4000000

  @Disable DMA Transfers
  ldr   r4, msg_okay              @\ Receive transfer length in bytes
  bl    sio_transfer              @] and reply "OKAY"
  mov   r2, r0                    @/
 
  mov   r3, #0x3000000            @\
  mov   r4, #0                    @] Download Burst Loader to
 burstLoop:                       @] 0x3000000 and up
  bl    sio_transfer              @]
  stmia r3!, {r0}                 @]
  add   r4, r4, r0                @]
  subs  r2, r2, #4                @]
  bhi   burstLoop                 @/
 
  bl    sio_transfer              @> Send the CRC value back to the master
 
  mov   r14, #0x3000000
  bx    lr
 
  @b     0x3000000                 @> start the loader
 
sio_transfer:
  str   r4, [r1, #0x120]          @siodata32 ;-set reply/send data
 
  ldr   r0, [r1, #0x128]          @\
  orr   r0, r0, #0x80             @] activate slave transfer
  str   r0, [r1,#0x128]           @/
 
 sio_wait:                        @\
  ldr   r0, [r1, #0x28]           @] wait until transfer completed
  tst   r0, #0x80                 @]
  bne   sio_wait                  @/
 
  ldr   r0, [r1, #0x120]          @> get received data
  bx   lr                         @> return
 
download_rom_to_ram:
  bx   lr                         @> return
 
init_interrupts:
  mov  r4, #0x4000000             @> Base of address of all I/O Registers
 
  ldr  r0, =irq_handler           @\ Place the address of irq_handler in
  str  r0, [r4, #-4]              @/ REG_IRG_HANDLER (0x3007FFFC)
 
  mov  r0, #0x0008                @\ Enable the VBlank IRQ in REG_DISPCNT
  strh r0, [r4, #0x4]             @/
 
  mrs  r0, cpsr                   @\
  bic  r0, r0, #0x80              @] Enable CPU Interrupts (clear i-flag)
  msr  cpsr, r0                   @/
 
  mov  r0, #0                     @\
  str  r0, [r4, #0x120]           @] Init SIO Normal mode, External Clock
  ldr  r0, =0x5080                @] 32-bit, Enable IRQ, transfer Started
  str  r0, [r4, #0x128]           @/
 
  ldr  r0, msg_boot               @\ output "BOOT" to the link
  str  r0, [r4, #0x120]           @/
 
  mov  r0, #1                     @\ Master interrupt enable (REG_IME)
  str  r0, [r4, #0x208]           @/
 
  mov  r0, #0x81                  @\ Enable VBlank and SIO (Burst Boot)
  str  r0, [r4, #0x200]           @/ IRQs
 
  bx   lr                         @> return

main:
  mov r0, #0xFE                   @\ Clear all RAM Registers
  swi 0x10000                     @/ except Multiboot Register
 
  bl init_interrupts              @> install irq_handler
 
  mov  r4, #0x4000000             @\ Enable video by clearing
  strh r4, [r4]                   @] the forced blank bit of
                                  @/ REG_DISPCNT
 
  mov r5, #0x5000000
  mov r8, #0x7C00
 
  mainLoop:
    swi 0x50000                   @> WaitForVIRQ
         
    strh r8, [r5]                 @>
     
    b mainLoop
  .ALIGN
  .POOL


In my code the screen starts out blue, then when irq_handler is called by bios it changes the screen color to green. Now when a SIO IRQ is received the screen should turn red, but this never happens.

If I boot this up in an emulator and check the memory locations on REG_IE the value is 0x81 (VBlank and SIO) and 0x4000120 = BOOT like it does in the original.

Any help would be appreciated.

-Joe

#31170 - Joe_Sextus - Wed Dec 08, 2004 4:56 pm

I have found my errors and am posting the fixed so everyone else can use it.
In init_interrupts the line
Code:
str  r0, [r4, #0x120]           @] Init SIO Normal mode, External Clock

should read
Code:
str  r0, [r4, #0x134]           @] Init SIO Normal mode, External Clock

and in sio_transfer the line
Code:
ldr   r0, [r1, #0x28]           @] wait until transfer completed

should read
Code:
ldr   r0, [r1, #0x128]           @] wait until transfer completed


And here is the complete fixed code
Code:
  .ARM
  .ALIGN
  .GLOBAL main

msg_boot:  .ascii "BOOT"
msg_okay:  .ascii "OKAY"
msg_brst:  .ascii "BRST"

irq_handler:
  mov  r8, #0x03E0
  strh r8, [r5]
 
  mov  r1, #0x4000000             @> Base of address of all I/O Registers
 
  ldr  r0, [r1, #0x200]           @\ Read REG_IE & REG_IF
  and  r0, r0, r0, lsr #16        @] check for handled IRQs
  add  r3, r1, #0x200             @] and place back in REG_IF
  strh r0, [r3, #2]               @/
 
  ldrh r3, [r1, #-8]              @\
  orr  r3, r3, r0                 @] Mirror REG_IF at REG_IRQ_MIRROR (0x3007FF8)
  strh r3, [r1, #-8]              @/
 
  and   r3, r0, #0x80             @\
  cmp   r3, #0x80                 @] Check for the Burst Boot (SIO) IRQ
 
  mov r11, r11
  moveq  r8, #0x001F
  streqh r8, [r5]
  ldreq r2, [r1 , #0x120]         @]
  ldreq r3, msg_brst              @] if "BRST" received jump to the
  cmpeq r2, r3                    @] Burst Boot Handler
  mov r11, r11
 
  beq   burst_boot                @/
 
  @Insert Additional IRQ Handler Code Hear
 
  bx   lr                         @> return
 
burst_boot:   @requires icoming r1=0x4000000

  @Disable DMA Transfers
  ldr   r4, msg_okay              @\ Receive transfer length in bytes
  bl    sio_transfer              @] and reply "OKAY"
  mov   r2, r0                    @/
 
  mov   r3, #0x3000000            @\
  mov   r4, #0                    @] Download Burst Loader to
 burstLoop:                       @] 0x3000000 and up
  bl    sio_transfer              @]
  stmia r3!, {r0}                 @]
  add   r4, r4, r0                @]
  subs  r2, r2, #4                @]
  bhi   burstLoop                 @/
 
  bl    sio_transfer              @> Send the CRC value back to the master
 
  mov   r14, #0x3000000           @\ start the loader
  bx    lr                        @/
 
sio_transfer:
  str   r4, [r1, #0x120]          @siodata32 ;-set reply/send data
 
  ldr   r0, [r1, #0x128]          @\
  orr   r0, r0, #0x80             @] activate slave transfer
  str   r0, [r1,#0x128]           @/
 
 sio_wait:                        @\
  ldr   r0, [r1, #0x128]          @] wait until transfer completed
  tst   r0, #0x80                 @]
  bne   sio_wait                  @/
 
  ldr   r0, [r1, #0x120]          @> get received data
  bx   lr                         @> return
 
download_rom_to_ram:
  bx   lr                         @> return
 
init_interrupts:
  mov  r4, #0x4000000             @> Base of address of all I/O Registers
 
  ldr  r0, =irq_handler           @\ Place the address of irq_handler in
  str  r0, [r4, #-4]              @/ REG_IRG_HANDLER (0x3007FFFC)
 
  mov  r0, #0x0008                @\ Enable the VBlank IRQ in REG_DISPCNT
  strh r0, [r4, #0x4]             @/
 
  mrs  r0, cpsr                   @\
  bic  r0, r0, #0x80              @] Enable CPU Interrupts (clear i-flag)
  msr  cpsr, r0                   @/
 
  mov  r0, #0                     @\
  str  r0, [r4, #0x134]           @] Init SIO Normal mode, External Clock
  ldr  r0, =0x5080                @] 32-bit, Enable IRQ, transfer Started
  str  r0, [r4, #0x128]           @/
 
  ldr  r0, msg_boot               @\ output "BOOT" to the link
  str  r0, [r4, #0x120]           @/
 
  mov  r0, #1                     @\ Master interrupt enable (REG_IME)
  str  r0, [r4, #0x208]           @/
 
  mov  r0, #0x81                  @\ Enable VBlank and SIO (Burst Boot)
  str  r0, [r4, #0x200]           @/ IRQs
 
  bx   lr                         @> return

main:
  mov r0, #0xFE                   @\ Clear all RAM Registers
  swi 0x10000                     @/ except Multiboot Register
 
  bl init_interrupts              @> install irq_handler
 
  mov  r4, #0x4000000             @\ Enable video by clearing
  strh r4, [r4]                   @] the forced blank bit of
                                  @/ REG_DISPCNT
 
  mov r5, #0x5000000
  mov r8, #0x7C00
 
  mainLoop:
    swi 0x50000                   @> WaitForVIRQ
         
    strh r8, [r5]                 @>
     
    b mainLoop
  .ALIGN
  .POOL

#31171 - keldon - Wed Dec 08, 2004 5:00 pm

It would help to have defines (or your assemblers equivalent) instead of using the address number everytime you make an access to hardware.

Basically we're all error prone. And if you use a define that you type wrong; your code will not compile. But if you make an error with an address it will still compile. So it is best to go with defines.

#31192 - Joe_Sextus - Wed Dec 08, 2004 7:54 pm

I was just try to get it to work with gas, so that i understood what it was doing. I plan to translate it to C/C++ eventually.