Skip to content

Instantly share code, notes, and snippets.

@lmBored
Created March 26, 2026 12:27
Show Gist options
  • Select an option

  • Save lmBored/22b9ddc1cec6f479e01a6f27126f09d9 to your computer and use it in GitHub Desktop.

Select an option

Save lmBored/22b9ddc1cec6f479e01a6f27126f09d9 to your computer and use it in GitHub Desktop.
@ Binary.s
@ Adam Watkins, Richard Verhoeven
@ December 2021
@ Wire the Gertboard as follows:
@ On J2 On J3
@ GP0 -> B12
@ GP1 -> B11
@ GP4 -> B10
@ GP7 -> B9
@ GP17-GP24 -> B8-B3
@ GP25 -> B1
@ Put output jumpers on B1-B12 (Output side of U3,U4,U5)
.global main
.equ SYS_EXIT, 0x1
.equ GPCLR0, 0x28 @ Value to set a GPIO pin to OFF
.equ GPSET0, 0x1C @ Value to set a GPIO pin to ON
.equ DISP_MASK, 0x9C6009C
.text
.include "Init_pins.s"
.include "Hardware2.s"
main:
BL map_io @ open /dev/mem and map hardware
BL init_pins
MVN R0, #0 @ Value to display
BL disp_num
exit:
BL unmap_io @ unmap and close hardware addresses
MOV R7, #SYS_EXIT
SWI 0
@ Functions
@@@@ disp_num : Function to display a number in binary on LEDS
@ Parameters:
@ R0: number < 1024.
@ Returns:
@ None
disp_num:
STMFD SP!, {R1-R4,LR}
MOV R1, #1024
SUB R1, #1 @ R1 = 1023 = 0x3FF
AND R0, R1 @ restrict R1 to 10 bits.
MOV R1, #0 @ R1 collects bit pattern (set to 0)
LDR R2, =disp_bits @ R2: Address of bit mask array
MOV R3, #0 @ R3: offset within array
disp_num_loop:
ANDS R4, R0, #1 @ if last bit is set ..
LDRNE R4, [R2, R3] @ ... load pattern for that bit
ORRNE R1, R1, R4 @ ... and update pattern
ADD R3, #4 @ increase offset in array
MOVS R0, R0, LSR #1 @ shift, and update flags
BNE disp_num_loop @ if not zero, continue.
@ R1 contains pattern for setting the bits.
LDR R2, =gpiobase
LDR R2, [R2]
CMP R1, #0
STRNE R1, [R2, #GPSET0]
@ Adjust pattern for clear
LDR R3, =DISP_MASK @ load all bits value
SUBS R1, R3, R1 @ substract bits for set
STRNE R1, [R2, #GPCLR0] @ if not zero, clear bits
LDMFD SP!, {R1-R4,LR}
MOV PC, LR
@@@@@ set_pin_function : function to set pin n to output in GPSELm
@ Parameters:
@ R0: pin number
@ R1: code of function (see chapter 6 BCM2837 manual for codes)
@ Returns:
@ R0: -1 on error
set_pin_function:
@ successively subtract 10 from R1 until <10
@ store offset of of GPSELm in R5
STMFD SP!, {R2-R7, LR} @ Save registers
BL check_pin @ Check if pin number OK
CMP R0, #0 @ If returned value is
BLT exit_set_func @ <0 (error) then exit function
@ Find GPSELm from pin number
CMP R0,#9 @ GPSEL0?
MOV R5,#0
BHI gpsel1
BAL clr_GPSELm @ Offset of GPSEL0 (= GPIO base address) in R5 = 0
gpsel1:
SUB R0, #10
CMP R0, #9 @ GPSEL1?
BHI gpsel2
MOV R5,#4
BAL clr_GPSELm @ Offset of GPSEL1 in R5
gpsel2:
SUB R0, #10
MOV R5,#8 @ Offset of GPSEL2 in R5
clr_GPSELm:
MOV R3, R0 @ Save R0
MOV R6, #0b111 @ Load R6 with bit pattern for BIC to clear 3 bits
MOV R2, #3
MUL R7, R3, R2
MOV R6, R6, LSL R7 @ Shift R6 R3*3 times left
clear: LDR R3, =gpiobase
LDR R2, [R3] @ Load base memory address of gpio
LDR R4, [R2,R5] @ Load current contents of GPSELm
BIC R4, R4, R6 @ Clear the 3 bits corresponding to the pin
MOV R1, R1, LSL R7 @ Shift R1 (function) R7 times left
ORR R4, R1 @ Set the function bits in R4 ( R4 is a copy of the
@ Current GPSELm register with the 3 bits corresponding
@ To pin R1 set o 0)
LDR R3, =gpiobase
LDR R3, [R3] @ Load memory base address of gpio
STR R4, [R3,R5] @ Copy R4 to GPSELm
exit_set_func:
LDMFD SP!,{R2-R7, LR} @ Restore R2-R7 and LR
MOV PC, LR @ R0 still holds GPIO base address if no error occurred..
@@@@ set_pin_value: function to set the pin
@ Paramters:
@ R0: pin number
@ R1: offset of GPSET0/GPCLR0
@ Returns:
@ R0: returns: -1 if error
set_pin_value:
STMFD SP!, {R3, LR}
MOV R3, R0 @ save R0
BL check_pin @ check if pin number is correct
CMP R0, #0 @ if value returned from check_pin
BLT ret_set @ <1 then return (error)
MOV R3, #1 @ will be shifted until pin position R1
MOV R3, R3, LSL R0 @ shift by R0 bits left
LDR R2, =gpiobase @ gpio base address in memory
LDR R2, [R2]
STR R3, [R2,R1] @ set or clear pin; R0+R2 address of GPSET/CLR0
@ notice that register is Write only
ret_set:
LDMFD SP!,{R3, LR}
MOV PC, LR @ return - R0 still holds base address if no error occurred
@@@@ check_pin : check if pin number is legal
@ Parameters:
@ R0: pin number
@ Return
@ R0: -1 if illegal
check_pin:
CMP R0, #1 @ GPIO 0 and 1 not available
BLS error @ GPIO2 is connected to GP0, GPIO3 to GP1
CMP R0, #5 @ GPIO5 not available
BEQ error
CMP R0, #6 @ GPIO6 not available
BEQ error
CMP R0, #16 @ GPIO 12, 13, 16 not available - R1 >16?
BHI next_check @ GPIO 14 and 15 set for UART so leave alone
CMP R0, #11 @ GPIO# <12?
BLS next_check
BAL error
next_check:
CMP R0, #21 @ GPIO19, 20 and 21 not available
BHI check_next
CMP R0, #18
BLS check_next
BAL error
check_next:
CMP R0, #27 @ GPIO27 is connected to GP21
BEQ ret
CMP R0, #25 @ no pins over 25
BHI error
MOV PC, LR
error: MOV R0, #-1 @ signal error to caller
ret: MOV PC, LR
.data
@@@@ Constants
dev_mem: .asciz "/dev/mem"
@ Mapping of bits to GPIO pins
@ Note: the numbers on the Gertboard don't match the GPIO numbers.
@ See page 10 of the Gertboard documentation.
@ Each value is (1 << GPIO_pin_number)
.align 4
disp_bits:
.word 0x4 @ bits[0]: GPIO2
.word 0x8 @ bits[1]: GPIO3
.word 0x10 @ bits[2]: GPIO4
.word 0x80 @ bits[3]: GPIO7
.word 0x20000 @ bits[4]: GPIO17
.word 0x40000 @ bits[5]: GPIO18
.word 0x400000 @ bits[6]: GPIO22
.word 0x800000 @ bits[7]: GPIO23
.word 0x1000000 @ bits[8]: GPIO24
.word 0x8000000 @ bits[9]: GPIO25
@@@@ Variables
.align 4
file_desc: .word 0x0 @ file descriptor for /dev/mem
gpiobase: .word 0x0 @ mapped GPIO base address
clockbase: .word 0x0 @ mapped System Timer base address
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment