.syntax unified @ Use the unified syntax .thumb @ Use the Thumb instruction set .global leds_blink .global delay_loop .global leds_init .global main .equ rcc_reg, 0x40023800 // adresa registru RCC .equ rcc_ahb1enr_offset, 0x30 // offset registru AHB1ENR .equ rcc_gpiob_en, 0x0002 // bit pro povoleni hodin pro GPIOB .equ rcc_gpioa_en, 0x0001 // bit pro povoleni hodin pro GPIOB .equ gpio_a, 0x40020000 // adresa registru GPIOA .equ gpio_b, 0x40020400 // adresa registru GPIOA // .equ gpio_c, 0x40020800 // adresa registru GPIOB .equ gpio_moder_offset, 0x00 // offset adresy registru MODER .equ gpio_otyper_offset, 0x04 // offset adresy registru OTYPER .equ gpio_odr_offset, 0x14 // offset adresy registru ODR .equ gpioa_odr_init, (0 << 5) // inicializacni hodnota pro registr ODR (turn off upper 4 leds) // Initialization values for moder, odr, otyper .equ gpioa_moder_leds, (0x01 << (2 * 5)) | (0x01 << (2 * 6)) | (0x01 << (2 * 7)) .equ gpiob_moder_leds, (0x01 << (2 * 6)) .equ gpioa_odr_leds, (0x7 << 5) .equ gpiob_odr_leds, (0x1 << 6) .equ gpioa_otyper_leds, (0x3 << 6) // The first one should not be open-drain. .equ gpiob_otyper_leds, gpiob_odr_leds .equ gpioa_leds_count, 3 // How many leds correspond to first gpio - gpioa .equ gpioa_leds_lsb_pos, 5 // What is the position of leds lsb in gpioa .equ gpiob_leds_lsb_pos, 6 // What is the position of led lsb in gpiob .equ last_led_position, (0x1 << 3) // Four LEDs total .equ init_led_position, (0x3 << 0) // The inital value for the shift value (1 means off) .equ mask_led_position, 0xF // The mask for all leds (4 leds total) .equ count_1ms, 7999 // pocet opakovani na 1 ms .equ delay, 500 // zpozdeni 500 ms .section .data shift_value: .word .section .text .thumb_func leds_init: push {R0-R3}; // Enable GPIOA in RCC->AHB1ENR ldr R0, =rcc_reg; ldr R1, =rcc_ahb1enr_offset; ldr R2, [R0, R1]; ldr R3, =rcc_gpioa_en; orr R2, R3 ; ldr R3, =rcc_gpiob_en; orr R2, R3; str R2, [R0, R1]; ldr R0, =gpio_a; ldr R1, =gpio_moder_offset; ldr R2, =gpioa_moder_leds; ldr R3, [R0, R1] ; orr R3, R2 str R3, [R0, R1]; ldr R0, =gpio_b; ldr R1, =gpio_moder_offset; ldr R2, =gpiob_moder_leds; ldr R3, [R0, R1] ; orr R3, R2 str R3, [R0, R1]; // Output open-drain ldr R0, =gpio_a; ldr R1, =gpio_otyper_offset; ldr R2, =gpioa_otyper_leds; str R2, [R0, R1]; ldr R0, =gpio_b; ldr R1, =gpio_otyper_offset; ldr R2, =gpiob_otyper_leds; str R2, [R0, R1]; pop {R0-R3}; bx lr; .thumb_func shift: push {R0-R1} ldr R0, =shift_value ldr R1, [R0] // Shift right by one lsrs R1, R1, #1 // Skip next section if no carry bcc shift_next // Set last bit, as one has just disappeared ldr R0, =last_led_position orr R1, R0 shift_next: ldr R0, =shift_value str R1, [R0] bx lr .thumb_func write_leds: push {R0-R4} // GPIOA first // Load the shift value, to R1 ldr R0, =shift_value ldr R2, [R0] // R2 contains the shift position // Load gpioa leds lsb position ldr R0, =gpioa_leds_lsb_pos // Shift the shift value to led positions lsl R2, R2, R0 // Mask the value with gpioa_odr_leds ldr R0, =gpioa_odr_leds and R2, R0 ldr R0, =gpio_a ldr R1, =gpio_odr_offset // Store the shift value in R2. // NOTE: Ideally, it should only set the few // bits, but it does not matter since other // bits are always zero in this program. str R2, [R0, R1] // GPIOB second // Load the shift value, to R1 ldr R0, =shift_value ldr R2, [R0] // R2 contains the shift position // Shift right by number of leds in gpioa ldr R0, =gpioa_leds_count lsr R2, R2, R0 // Shift the shift value to led positions ldr R0, =gpiob_leds_lsb_pos lsl R2, R2, R0 // Mask the value with gpiob_odr_leds ldr R0, =gpiob_odr_leds and R2, R0 ldr R0, =gpio_b ldr R1, =gpio_odr_offset // Store the shift value in R2. // NOTE: Ideally, it should only set the few // bits, but it does not matter since other // bits are always zero in this program. str R2, [R0, R1] pop {R0-R4} bx lr .thumb_func delay_loop: push {R0-R1}; ldr R1, =delay // Load counter for 1ms delay .thumb_func load_1ms: ldr R0, =count_1ms .thumb_func count_loop: // Loop through the counter to 1 ms subs R0, #1 bne count_loop // Loop through the number of ms (delay value) subs R1, #1 bne load_1ms pop {R0-R1}; bx lr; .thumb_func main: bl leds_init; ldr R0, =shift_value ldr R1, =init_led_position str R1, [R0] main_loop: bl shift; bl write_leds; bl delay_loop; b main_loop;