Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- @@ Таймер SysTick
- .syntax unified
- .cpu cortex-m3
- .thumb
- .global _start
- @; Интервал переключения диода на PC13, миллисекунд :
- LED_TOGGLE_TIME_ms = 3000 / 2
- @; регистры, биты и макросы :
- SCB_VTOR = 0xe000ed00 + 0x08
- STK = 0xe000e010
- STK_CTRL = STK + 0x00
- STK_LOAD = STK + 0x04
- STK_VAL = STK + 0x08
- COUNTFLAG = 1 << 16
- RCC_APB2ENR = 0x40021000 + 0x18
- IOPCEN = 1 << 4
- GPIOC = 0x40011000
- GPIOC_CR = GPIOC + 0x00
- GPIOC_ODR = GPIOC + 0x0c
- PC13 = 1 << 13
- O_OPEN_DRAIN = 0b0101
- .macro WriteReg reg, val
- ldr r0, =\reg
- ldr r1, =\val
- str r1, [r0]
- .endm
- .macro ConfigPin gpio, pin, conf
- ldr r0, =\gpio + \pin / 8 * 4
- ldr r1, [r0]
- ldr r2, =\conf
- bfi r1, r2, #\pin % 8 * 4, #4
- str r1, [r0]
- .endm
- .text
- vectors:
- .word 0x20005000 @; значение sp
- .word _start + 1 @; reset; адрес начала программы + 1
- @; убери /** и **/, если собираешься
- @; использовать прерывание таймера.
- @; вектор этого прерывания находится
- @; по адресу 0x3c относительно начала
- @; таблицы векторов
- /**
- .org vectors + 0x3c
- .word stk_int + 1 @; systick; адрес обработчика + 1
- stk_int:
- @; здесь надо написать что будет,
- @; когда сработает прерывание (когда
- @; таймер досчитает до нуля),
- @; например:
- @; ldr r0, =GPIOC_ODR
- @; ldr r1, [r0]
- @; eor r1, #PC13
- @; str r1, [r0]
- @; возвращаемся из прерывания :
- bx lr
- **/
- _start:
- @; (важно!)
- @; если не менять регистр SCB_VTOR, то
- @; прерывания могут не работать сразу после
- @; запуска кода ЗАГРУЗЧИКОМ и при компиляции
- @; для адресов, отличных от 0x00000000,
- @; 0x08000000 и 0x20000000.
- @; WriteReg SCB_VTOR, vectors
- @; настраивам выход PC13 :
- WriteReg RCC_APB2ENR, IOPCEN
- ConfigPin GPIOC_CR, 13, O_OPEN_DRAIN
- @; (необязательно)
- @; сбрасываем таймер, если он раньше
- @; был запущен, например, загрузчиком :
- @; WriteReg STK_CTRL, 0
- @; WriteReg STK_VAL, 0
- @; записываем в таймер время в микросекундах,
- @; как только таймер досчитает до 0, он начнёт сначала;
- @; максимум ~ 16 секунд (2^24 микросекунд) :
- WriteReg STK_LOAD, 1000 * LED_TOGGLE_TIME_ms
- @; запускаем таймер (если нужно прерывание,
- @; то запиши 3, а не 1) :
- WriteReg STK_CTRL, 1
- @; в данный момент прерывание таймера не используется
- @; и в основнм цикле мы росто проверяем состояние
- @; таймера. с прерыванием таймер не надо проверять:
- @; при его срабатывании контроллер сам выолнит
- @; функцию-обработчик прерывания (stk_int).
- @; в случае, когда используется прерывание,
- @; основной цикл может быть сокращён до
- @; main_loop:
- @; b main_loop
- main_loop:
- @; ждём пока таймер досчитает до 0 :
- ldr r0, =STK_CTRL
- ldr r0, [r0]
- tst r0, #COUNTFLAG
- beq main_loop
- @; досчиал, переключаем светодиод :
- ldr r0, =GPIOC_ODR
- ldr r1, [r0]
- eor r1, #PC13
- str r1, [r0]
- @; повторяем основной цикл :
- b main_loop
- .end
Advertisement
Add Comment
Please, Sign In to add comment