@.CHARSET CP1251

@GNU AS
@ ***************************************************************************
@ *                МОДУЛЬ  СЧЕТЧИКА ЦИКЛОВ МИКРОКОНТРОЛЛЕРА                 *
@ ***************************************************************************
@ * Модуль настраивает DWT счетчик (32-ух разрядный счетчик машинных циклов *
@ * шины AHB (для STM32F401 84 Мгц)                                        *
@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
@ * Модуль вызывать без параметров, регистры сохраняются                    *
@ * команда вызова:                                                         *
@ *           BL     DWT_START                               *
@ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
@ * Для того чтобы прочитать значение счетчика в R0 вызвать:                *
@ *             BL      DWT_GETCOUNTER                                      *
@ ***************************************************************************
@ * Первоисточник: http://www.stm32asm.ru/407/f407_dwt_init.html            *
@ ***************************************************************************
@
.syntax unified      @ синтаксис исходного кода
.thumb               @ тип используемых инструкций Thumb
.cpu cortex-m4       @ процессор


.equ DEMCR        ,0xE000EDFC @ Debug Exception and Monitor Control Register
.equ DWT_CTRL     ,0xE0001000 @ Control Register
.equ DWT_CYCCNT   ,0xE0001004 @ Cycle Count Register

.section .asmcode

.GLOBAL        DWT_START
DWT_START:
                    PUSH            { R0, R1 }
          @ Включаем системный бит TRCENA
                    LDR             R0, = DEMCR
                    LDR             R1, [ R0 ]
                    ORR             R1, ( 1 << 24 )
                    STR             R1, [ R0 ]

          @ Разрешаем DWT
                    LDR             R0, = DWT_CTRL
                    LDR             R1, [ R0 ]
                    ORR             R1, 1
                    STR             R1, [ R0 ]
                    POP             { R0, R1 }
                    BX              LR


.GLOBAL        DWT_GETCOUNTER
DWT_GETCOUNTER:
          @ чтение счетчика
                    LDR             R0, = DWT_CYCCNT
                    LDR             R0, [ R0 ]
                    BX              LR


.GLOBAL        DWT_RESET
DWT_RESET:
           @ сброс счетчика
                    PUSH            { R0, R1 }

                    LDR             R0, = DWT_CYCCNT
                    MOV             R1, 0
                    STR             R1, [ R0 ]

                    POP             { R0, R1 }
                    BX              LR


.GLOBAL        DWT_DELAY
DWT_DELAY:
           @ пауза в мкс
                    PUSH            { R1, R2, LR }

                    BL              DWT_RESET @ сбросим счетчик

                    LDR             R1, = 84000000 / 1000000  @ количество тактов на 1 мкс
                    MUL             R0, R0, R1

                    LDR             R2, = DWT_CYCCNT
DWT_Delay_loop:
                    LDR             R1, [ R2 ]
                    CMP             R0, R1
                    BCS             DWT_Delay_loop

                    POP             { R1, R2, PC }


