@.CharSet=CP1251
@GNU AS

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

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

.INCLUDE  "/src/inc/rcc.inc"
.INCLUDE  "/src/inc/gpio.inc"
.INCLUDE  "/src/inc/exti.inc"
.INCLUDE  "/src/inc/nvic.inc"

.section .asmcode

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

.global EXTI_PA0_INIT
EXTI_PA0_INIT:
                    MOV        R1, 1

                    @ включаем используемую периферию микроконтроллера
                    LDR        R0, = PERIPH_BASE + PERIPH_BB_BASE + ( RCC_BASE + RCC_APB2ENR ) * 32

                    STR        R1, [ R0, RCC_APB2ENR_IOPAEN_N * 4 ]    @ включим GPIO A - кнопка на PA0
                    STR        R1, [ R0, RCC_APB2ENR_AFIOEN_N * 4 ]    @ включим AFIO

                    @ настроим GPIO A: PA0:  на Input + Pull_Up (кнопка USER \ WAKEUP)
                    LDR        R0, = PERIPH_BASE + GPIOA_BASE
                    LDR        R3, [ R0, GPIO_CRL ]
                    MOV        R2, GPIO_MODE_INPUT + GPIO_CNF_INP_FLOAT << 2
                    BFI        R3, R2, GPIO_CRL_MODE0_N, 4
                    STR        R3, [ R0, GPIO_CRL ]

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

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

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

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

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

                    @ включим прерывания по EXTI_0 в NVIC
                    LDR        R0, = NVIC_BASE
                    LDR        R3, [ R0, NVIC_ISER0 ]
                    MOV        R2, NVIC_ISER0_INT6   @ номер прерывания из RM0041 стр.131, колонка Position
                    ORR        R3, R3, R2
                    STR        R3, [ 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_BASE + PERIPH_BB_BASE + ( EXTI_PR + EXTI_BASE ) * 32
                    STR        R1, [ R0, 0 * 4 ]

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

                    POP        { PC }




