@.CharSet=CP1251
@GNU AS

@.DESC type=module
@ +------------------------------------------------------------------------------+
@ |                              Модуль демонстратор                             |
@ |                       Контроллер внешних прерываний EXTI                     |
@ |                                                                              |
@ |   для микроконтроллера STM32F4xxx   отладочная плата  MiniSTM32F401          |
@ +------------------------------------------------------------------------------+
@ |                                                                              |
@ | При нажатии на кнопку User\WakeUp (GPIOA pin 0) вызывается процедура         |
@ | LED_ChangeState в которой переключается состояние светодиода                 |
@ |                                                                              |
@ | ВНИМАНИЕ !                                                                   }
@ } Для корректной работы модуля необходима полная таблица прерываний isr.asm    |
@ | ( Core + Periph )                                                            |
@ |                                                                              |
@ +------------------------------------------------------------------------------+
@ |                                                                              |
@ | Видеоурок по модулю:                                                         |
@ | ArmAsmEditor: STM32 на Ассемблере: EXTI + Прерывания микроконтроллера        |
@ | STM32F4xxx, Видео 23-1                                                       |
@ | https://youtu.be/agbWchRo-tQ                                                 |
@ |                                                                              |
@ +------------------------------------------------------------------------------+
@.ENDDESC

.syntax unified     @ синтаксис исходного кода
.thumb              @ тип используемых инструкций Thumb
.cpu cortex-m4      @ процессор

.INCLUDE  "/src/inc/rcc.inc"
.INCLUDE  "/src/inc/exti.inc"
.INCLUDE  "/src/inc/nvic.inc"
.include  "/src/inc/syscfg.inc"

.section .asmcode

@.DESC name=EXTI_PA0_INIT  type=proc
@ +------------------------------------------------------------------------------+
@ |             Инициализация внешних прерываний EXTI для PA0                    |
@ +------------------------------------------------------------------------------+
@ |  Параметров у процедуры нет                                                  |
@ |                                                                              |
@ | При выходе изменяются регистры R0-R3                                         |
@ |                                                                              |
@ +------------------------------------------------------------------------------+
@.ENDDESC

.global EXTI_PA0_INIT
EXTI_PA0_INIT:
                    MOV        R1, 1

                    @ включим тактирование SYSCFG
                    @ по умолчанию все настройки для GPIOA и если не включить SYSCFG то с другими портами работать не будет
                    LDR             R0, = PERIPH_BB_BASE + ( RCC_BASE + RCC_APB2ENR ) * 32
                    STR             R1, [ R0, RCC_APB2ENR_SYSCFGEN_N * 4 ]


                    @ настроим вход  EXTI 0 на GPIO A pin 0
                    @ по умолчанию входы EXTI настроены на GPIOA, но если нужно будет использовать другой GPIO
                    @ то этот код обязательно должен быть
                    LDR        R0, = PERIPH_BASE + SYSCFG_BASE
                    LDR        R3, [ R0, SYSCFG_EXTICR1 ]
                    MOV        R2, SYSCFG_EXTICR_EXTI_PA              @ выбор GPIOA для входа EXTI0
                    BFI        R3, R2, SYSCFG_EXTICR1_EXTI0_N, 4
                    STR        R3, [ R0, SYSCFG_EXTICR1 ]

                    @ включим триггер  опускание уровня на EXTI 0 (PA0)
                    @ EXTI_RTSR - триггера на поднятие уровня (Rising)
                    @ EXTI_FTSR - триггер на опускание уровня (Falling)
                    LDR        R0, = PERIPH_BB_BASE + ( EXTI_BASE + EXTI_FTSR ) * 32
                    STR        R1, [ R0, 0 * 4 ]

                    @ сбросим флаг прерывания по EXTI_0
                    LDR        R0, = PERIPH_BB_BASE + ( EXTI_BASE + EXTI_PR ) * 32
                    STR        R1, [ R0, 0 * 4 ]

                    @ включим прерывания по EXTI_0
                    LDR        R0, = PERIPH_BB_BASE + ( EXTI_BASE + EXTI_IMR ) * 32
                    STR        R1, [ R0, 0 * 4 ]

                    @ зададим приоритет прерывания
                    LDR        R0, = NVIC_BASE
                    LDR        R1, [ R0, NVIC_IPR1 ]
                    MOV        R2, 0xF0              @ 0xF0 - низший приоритет, 0х00 - высший приоритет
                    BFI        R1, R2, NVIC_IPR1_IP6_N, 8
                    STR        R2, [r0, NVIC_IPR1]

                    @ включим прерывания по EXTI_0 в NVIC
                    LDR        R1, [ R0, NVIC_ISER0 ]
                    MOV        R2, NVIC_ISER0_INT6   @ номер прерывания из RM0368 стр.203, колонка Position
                    ORR        R1, R1, R2
                    STR        R1, [ R0, NVIC_ISER0 ]

                    BX         LR


@.DESC name= IRQ_EXTI0  type=proc
@ +------------------------------------------------------------------------------+
@ |                           Обработчик прерывания EXTI0                        |
@ +------------------------------------------------------------------------------+
@ | При возникновении прерывания (нажатии на кнопку UserWakeUp) вызывается про-  |
@ | цедура LED_ChangeState                                                       |
@ +------------------------------------------------------------------------------+
@.ENDDESC

.GLOBAL   IRQ_EXTI0
IRQ_EXTI0:          @ обработчик прерывния EXTI_0
                    MOV        R1, 1

                    @ сбросим флаг прерывания по EXTI 0 иначе прерывание будет возникать снова и снова
                    LDR        R0, = PERIPH_BB_BASE + ( EXTI_PR + EXTI_BASE ) * 32
                    STR        R1, [ R0, 0 * 4 ]

                    PUSH       { LR }
                    @ внешняя процедура-обработчик возникновения прерывания
                    BL         LED_ChangeState        @ переключим состояние светодиода

                    POP        { PC }




