#****************************************************************************************#
#   Project:    task2 - ASM: Interrupts
#   File:       task2.s
#
#   Language:   ASM
#
#   Hardware:   STefi Light v1.1
#   Processor:  STM32G431KBT6U
#
#   Author:     Manuel Lederhofer
#   Datum:      31.10.2014
#
#   Version:    6.0
#   History:
#       31.10.2014  ML  create file
#       27.09.2018  ML  edit comments, extend vector table
#       18.12.2018  ML  port from MKL05Z32VLC4 to STM32L476RG
#       27.02.2019  ML  move section of exception handlers to bottom of file
#		25.09.2019	ML	minor changes for a better code and comment understanding
#       04.09.2020  HL  port from STM32L476RG to STM32F411xE
#       21.09.2020  ML  tidy up, comments and formatting
#       29.09.2021  ML  port from STM32F411xE to STM32F042K6T6
#       09.03.2022  ML  port from STM32F042K6T6 to STM32G431KBT6U
#       10.02.2025  TK  remove ASM:Polling,move ASM:Interrupts to task2
#       24.06.2025  TK  remove /* ... place your code here ... */
#
#   Status:     working
#
#   Description:
#       See the description and requirements of the requested application
#       in the lab exercise guide.
#
#   Notes:
#       - MCU speed at startup is 16 MHz
#
#   ToDo:
#       - Change the example code to match the description and requirements
#          of the requested application in the lab exercise guide.
#****************************************************************************************#

    .include "G431_addr.s"


#----------------------------------------------------------------------------------------#
    .section .vectortable,"a"   // vector table at begin of ROM
#----------------------------------------------------------------------------------------#

    .align  2

    .word   0x20004000          // initial Stack Pointer:   0x20000000 (RAM base) + 0x4000 (16K SRAM1 length)
    .word   0x08000401          // initial Program Counter
    .word   _ISR_NMI            // non-masking interrupt
    .word   _ISR_HARDF          // hard fault interrupt



    /* N.B.
        Look at the .space or the .org assembler directive to insert the address of the
        ISRs at the right place in the vector table. Verify your settings by the help of
        the list file. */

    .word   _ISR_S0


#----------------------------------------------------------------------------------------#
    .text                       // section .text (default section for program code)
#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .thumb_func
    .global init
    .type   init, %function
init:
    CPSID   i                   // disable interrupts globally

    MOVS    r0, #0              // safely initialize the GPRs
    MOVS    r1, #0
    MOVS    r2, #0
    MOVS    r3, #0
    MOVS    r4, #0
    MOVS    r5, #0
    MOVS    r6, #0
    MOVS    r7, #0
    MOV     r8, r0
    MOV     r9, r0
    MOV     r10, r0
    MOV     r11, r0
    MOV     r12, r0

#--- enable port clocking
    LDR     r1, =RCC_AHB2ENR    // load address of RCC_AHB2ENR
    MOV     r2, #0x01           // load mask for adjusting port clock gating (A: LEDs)
    LDR     r0, [r1, #0]        // get current value of RCC_AHB2ENR
    ORRS    r0, r0, r2          // configure clock gating for ports
    STR     r0, [r1, #0]        // apply settings

#--- port init
#- LEDs
    LDR     r1, =GPIOA_MODER    // load port A mode register address
    MOVS    r2, #0x03           // prepare mask
    LDR     r0, [r1, #0]        // get current value of port A mode register
    BICS    r0, r2              // delete bits
    MOVS    r2, #0x01           // load configuration mask
    ORRS    r0, r0, r2          // apply mask
    STR     r0, [r1, #0]        // apply result to port A mode register

    LDR     r1, =GPIOA_MODER
    MOVS    r3, #0x01
    LDR     r0, [r1, #1]
    BICS    r0, r3
    MOVS    r3, #0x01
    ORRS    r0, r0, r3
    STR     r0, [r1, #1]

#- switch LED off
    LDR     r1, =GPIOA_ODR      // load port A output data register
    MOVS    r2, #0x01           // load mask for LED
    LDR     r0, [r1, #0]        // get current value of GPIOA
    ORRS    r0, r0, r2          // configure pin state
    STR     r0, [r1, #0]        // apply settings

#- buttons

    /* ... place your code here ... */


#--- button interrupt config

#- enable clock for SYSCFG module


#- connect GPIO pins of the buttons to EXTended Interrupt controller lines (EXTI)
#  in SYSCFG module (SYSCFG_* registers)




#- configure lines in EXTI module (EXTI_* registers)



#- NVIC: set interrupt priority, clear pending bits
#  and enable interrupts for buttons (see: PM, ch. 4.3, NVIC)



    CPSIE   i                   // enable interrupts globally


#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .thumb_func
    .global main
    .type   main, %function
main:
    LDR     r1, =GPIOA_ODR
    EORS    r0, r0, r3

    STR     r0, [r1, #0]



    BL      delay


    B       main


#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .thumb_func
    .global delay
    .type   delay, %function
delay:
    MOVS    r6, #0              // ...
    LDR     r7, =2000000        // ...
.L1:
    ADDS    r6, r6, #1          // ...
    CMP     r6, r7              // ...
    BNE     .L1                 // ...
    BX      lr                  // ...


#----------------------------------------------------------------------------------------#

    .align 2
    .global stop
stop:
    NOP                         // do nothing (NOP is here to avoid a debugger crash, only)
    B       stop                // if this line is reached, something went wrong


#----------------------------------------------------------------------------------------#
.lp1:           // this label is only to nicify the line up in the .lst file
    .ltorg
#----------------------------------------------------------------------------------------#


#----------------------------------------------------------------------------------------#
    .section .exhand,"ax"       // section for exception handlers
#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .type   _ISR_NMI, %function
_ISR_NMI:
#--- enable clock
    LDR     r1, =RCC_AHB2ENR    // load address of RCC_AHB2ENR
    MOV     r2, #0x01           // load mask
    LDR     r0, [r1, #0]        // get current value of RCC_AHB2ENR
    ORRS    r0, r0, r2          // configure clock gating for port
    STR     r0, [r1, #0]        // apply settings

#--- init pins
    LDR     r1, =GPIOA_MODER    // load port A mode register address
    MOVS    r2, #0xFF           // prepare mask
    LDR     r0, [r1, #0]        // get current value of port A mode register
    BICS    r0, r0, r2          // delete bits
    MOVS    r2, #0x44           // load configuration mask
    ORRS    r0, r0, r2          // configure pins
    STR     r0, [r1, #0]        // apply settings to port A mode register

#--- switch some LEDs on
    LDR     r1, =GPIOA_ODR      // load port A data output register address
    MOVS    r2, #0x0A           // load mask for blue and yellow LED
    LDR     r0, [r1, #0]
    BICS    r0, r0, r2
    STR     r0, [r1, #0]        // switch LEDs on

    B   _ISR_NMI


#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .type   _ISR_HARDF, %function
_ISR_HARDF:
#--- enable clock
    LDR     r1, =RCC_AHB2ENR    // load address of RCC_AHB2ENR
    MOV     r2, #0x01           // load mask
    LDR     r0, [r1, #0]        // get current value of RCC_AHB2ENR
    ORRS    r0, r0, r2          // configure clock gating for port
    STR     r0, [r1, #0]        // apply settings

#--- init pins
    LDR     r1, =GPIOA_MODER    // load port A mode register address
    MOVS    r2, #0xFF           // prepare mask
    LDR     r0, [r1, #0]        // get current value of port A mode register
    BICS    r0, r0, r2          // delete bits
    MOVS    r2, #0x11           // load configuration mask
    ORRS    r0, r0, r2          // configure pins
    STR     r0, [r1, #0]        // apply settings to port A mode register

#--- switch some LEDs on
    LDR     r1, =GPIOA_ODR      // load port A data output register address
    MOVS    r2, #0x05           // load mask for red and green LED
    LDR     r0, [r1, #0]
    BICS    r0, r0, r2
    STR     r0, [r1, #0]        // switch LEDs on

    B       _ISR_HARDF


#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .type   _ISR_S0, %function
_ISR_S0:
    PUSH    {lr}                // save special content

#--- do the work


#--- clear interrupt flag


#--- leave ISR
    POP     {r1}                // get special content back
    BX      r1                  // go back to where we came from


#----------------------------------------------------------------------------------------#

    .align  2
    .syntax unified
    .thumb
    .type   _ISR_S1, %function
_ISR_S1:
    PUSH    {lr}                // save special content

#--- do the work




#--- clear interrupt flag



#--- leave ISR
    POP     {r1}                // get special content back
    BX      r1                  // go back to where we came from


#----------------------------------------------------------------------------------------#
.lp2:           // this label is only to nicify the line up in the .lst file
    .ltorg
#----------------------------------------------------------------------------------------#

    .end

#************************************** E O F *******************************************#
