Написал простенькую програмку: пустой цикл, раз в секунду прерывание таймера... в его обработчике считываю состояние порта А, прибавляю +1, вывожу результат обратно в порт... использую первые 8 выводов 0-7.
В результате должно получиться что-то вроде этого:
- правильная работа
Но получается вот это:
- неправильнаяработа
Запускаю в симуляторе - выполняет правильно. Запускаю от JTAG в пошаговом режиме "step" - все работает как и должно (как на 1й анимации)... жму кнопку "run" - опять неправильно работает (как на 2й анимации). Жму ресет - работает неправвильно. Перепробовал с таймерами general purpose 2-4. Один хрен неправильно работает. Попробовал убрать прерывание таймера и в главном цикле с задердкой сделать то же самое - в порт выводит все правильно. Попробовал сделать на прерывании SysTick - на мое удивление заработала правильно.
Кто-нибудь сталкивался с таким? Может как-то не так настраиваю таймеры general purpose 2-4?
Пишу на ассемблере в Keil. Плата easyelectronics.
Код: Выделить всё
AREA |PROGRAMMA|, CODE, READONLY
INCLUDE RCC.S
GPIOA_BASE EQU 0x40010800
GPIOB_BASE EQU 0x40010C00
GPIOC_BASE EQU 0x40011000
AFIO_BASE EQU 0x40010000
GPIOx_CRL EQU 0x00
GPIOx_CRH EQU 0x04
GPIOx_IDR EQU 0x08
GPIOx_ODR EQU 0x0C
GPIOx_BSRR EQU 0x10
GPIOx_BRR EQU 0x14
GPIOx_LCKR EQU 0x18
AFIO_EVCR EQU 0x00
AFIO_MAPR EQU 0x04
AFIO_EXTICR1 EQU 0x08
AFIO_EXTICR2 EQU 0x0C
AFIO_EXTICR3 EQU 0x10
AFIO_EXTICR4 EQU 0x14
AFIO_MAPR2 EQU 0x1C
TIM1_BASE EQU 0x40012C00
TIM2_BASE EQU 0x40000000
TIM3_BASE EQU 0x40000400
TIM4_BASE EQU 0x40000800
TIMx_CR1 EQU 0x00
TIMx_CR2 EQU 0x04
TIMx_SMCR EQU 0x08
TIMx_DIER EQU 0x0C
TIMx_SR EQU 0x10
TIMx_EGR EQU 0x14
TIMx_CCMR1 EQU 0x18
TIMx_CCMR2 EQU 0x1C
TIMx_CCER EQU 0x20
TIMx_CNT EQU 0x24
TIMx_PSC EQU 0x28
TIMx_ARR EQU 0x2C
TIMx_RCR EQU 0x30
TIMx_CCR1 EQU 0x34
TIMx_CCR2 EQU 0x38
TIMx_CCR3 EQU 0x3C
TIMx_CCR4 EQU 0x40
TIMx_BDTR EQU 0x44
TIMx_DCR EQU 0x48
TIMx_DMAR EQU 0x4C
SysTick_BASE EQU 0xE000E010
STC_CTRL EQU 0x00
STC_LOAD EQU 0x04
STC_VAL EQU 0x08
STC_CALIB EQU 0x0C
NVIC_BASE EQU 0xE000E100
NVIC_ISER0 EQU 0x000
NVIC_ISER1 EQU 0x004
NVIC_ISER2 EQU 0x008
NVIC_ICER0 EQU 0x080
NVIC_ICER1 EQU 0x084
NVIC_ICER2 EQU 0x088
NVIC_ISPR0 EQU 0x100
NVIC_ISPR1 EQU 0x104
NVIC_ISPR2 EQU 0x108
NVIC_ICPR0 EQU 0x180
NVIC_ICPR1 EQU 0x184
NVIC_ICPR2 EQU 0x188
NVIC_IABR0 EQU 0x200
NVIC_IABR1 EQU 0x204
NVIC_IABR2 EQU 0x208
NVIC_IPR0 EQU 0x300
NVIC_IPR1 EQU 0x304
NVIC_IPR2 EQU 0x308
NVIC_IPR3 EQU 0x30C
NVIC_IPR4 EQU 0x310
NVIC_IPR5 EQU 0x314
NVIC_IPR6 EQU 0x318
NVIC_IPR7 EQU 0x31C
NVIC_IPR8 EQU 0x320
NVIC_IPR9 EQU 0x324
NVIC_IPR10 EQU 0x328
NVIC_IPR11 EQU 0x32C
NVIC_IPR12 EQU 0x330
NVIC_IPR13 EQU 0x334
NVIC_IPR14 EQU 0x338
NVIC_IPR15 EQU 0x33C
NVIC_IPR16 EQU 0x340
NVIC_IPR17 EQU 0x344
NVIC_IPR18 EQU 0x348
NVIC_IPR19 EQU 0x34C
NVIC_IPR20 EQU 0x350
NVIC_STIR EQU 0xE00
TIM4_UIF_BB EQU 0x42000000 + TIMx_SR * 32
; Сектор прерываний
TIM4_IRQHandler PROC ; Прерывание TIM4
EXPORT TIM4_IRQHandler
MOV32 R0, #GPIOA_BASE
LDRB R1, [R0, #GPIOx_ODR]
ADD R1, #1
STRB R1, [R0, #GPIOx_ODR]
MOV32 R0, #TIM4_UIF_BB
MOV R1, #0
STR R1, [R0]
BX LR
ENDP
SysTick_Handler PROC
EXPORT SysTick_Handler
MOV32 R0, #GPIOA_BASE
LDRB R1, [R0, #GPIOx_ODR]
ADD R1, #1
STRB R1, [R0, #GPIOx_ODR]
BX LR
ENDP
; Inicialisation Code
System_Init PROC
EXPORT System_Init
MOV R0, #0
MOV R1, #0
MOV R2, #0
MOV R3, #0
MOV R4, #0
MOV R5, #0
MOV R6, #0
MOV R7, #0
MOV R8, #0
MOV R9, #0
MOV R10, #0
MOV R11, #0
MOV R12, #0
MOV32 R0, #HSEON_BB ; В R0 помещам адрес бита HSEON в bit band alias
MOV R1, #1
STR R1, [R0] ; Переключаемся на внешний кварц, устанавливая бит HSEON
MOV32 R0, #HSERDY_BB
M1 LDR R1, [R0] ; Читаем бит HSERDY по адресу в bit band region
ADD R2, #1
CMP R2, #0x000000FF ; если досчитали до конца и флаг HSERDY не установился, то переходим на обработку ошибки на M397
BEQ.W M397 ; Ждем пока внешний генератор не выйдет в рабочий режим, т.е. пока не установится бит HSERDY
CMP R1, #0 ; Проверяем флаг готовности
BEQ M1 ; если флаг не установился ждем пока он установится
MOV32 R0, #FLASH_BASE ; Теперь настраиваем предвыборку Flash, т.к. планируем работать на 72 МГц
MOV R1, #(PRFTBE + LATENCY1)
STR R1, [R0, #FLASH_ACR] ; Включили буфер предвыборки и настроили на 2 цикла ожидания
MOV32 R0, #RCC_BASE
MOV32 R1, #(PLLMUL2 + PLLSRC + PPRE12)
STR R1, [R0, #RCC_CFGR] ; Сохраняем настройки в RCC_CFGR
MOV32 R0, #PLLON_BB ; Запускаю схему PLL в регистре RCC_CR
MOV R1, #1
STR R1, [R0]
MOV32 R0, #PLLRDY_BB
M2 LDR R1, [R0] ; читаем флаг готовности PLL
CMP R1, #0 ; Проверяем флаг готовности
BEQ M2 ; пока не установится в 1
MOV32 R0, #SW1_BB
MOV R1, #1
STR R1, [R0] ; Выбираем тактовый сигнал Sysclk от PLL
MOV32 R0, #SWS1_BB ; ожидаем пока Sysclck не переключится на PLL
M3 LDR R1, [R0] ; читаем флаг готовности SWS1
CMP R1, #0 ; Проверяем флаг готовности
BEQ M3 ; ждем пока не установится в 1
; Инициализация портов ввода-вывода
MOV32 R0, #RCC_BASE
MOV32 R1, #IOPAEN
STR R1, [R0, #RCC_APB2ENR]
MOV32 R0, #GPIOA_BASE
MOV32 R1, #0x22222222 ; PUSH-PULL 2МГц
STR R1, [R0, #GPIOx_CRL]
MOV32 R1, #0x88888888 ; PULL-UP/PULL-DOWN 2МГц
STR R1, [R0, #GPIOx_CRH]
MOV32 R1, #0x000000FF
STR R1, [R0, #GPIOx_BSRR] ; Установить биты 0-7 в порту А
; Инициализация таймера TIM4
; MOV32 R0, #RCC_BASE
; MOV32 R1, #TIM4EN
; STR R1, [R0, #RCC_APB1ENR]
; MOV32 R0, #TIM4_BASE
; MOV R1, #0x0CA0
; STR R1, [R0, #TIMx_PSC]
; MOV R1, #0x1DD0
; STR R1, [R0, #TIMx_ARR]
; MOV R1, #0x0000
; STR R1, [R0, #TIMx_CNT]
; MOV R1, #0x0001
; STR R1, [R0, #TIMx_DIER]
; MOV R1, #0x0005
; STR R1, [R0, #TIMx_CR1]
; Инициализация системного таймера SysTick
MOV32 R0, #SysTick_BASE
MOV R1, #0
STR R1, [R0, #STC_CTRL]
MOV32 R1, #0x4FFFFF
STR R1, [R0, #STC_LOAD]
STR R1, [R0, #STC_VAL]
MOV R1, #3
STR R1, [R0, #STC_CTRL]
; Разрешение прерываний в NVIC
; CPSIE I
; MOV32 R0, #NVIC_BASE
; MOV32 R1, #0x40000000
; STR R1, [R0, #NVIC_ISER0]
BX LR
M397 ; где-то здесь нужно что-то сделать
; дабы обработать отказ HSE
B .
ENDP
; My Appication
Main PROC
EXPORT Main
B Main
ENDP
END