Странная работа STM32f103c8

Все о микроконтроллерах: AVR, PIC, STM8, STM32, Arduino, Altera, Xilinx, все что угодно. Этот раздел для всего что клацает байтиками.
Wypuk
Сообщения: 4

Сообщение Wypuk » 25 ноя 2013, 19:55

Начал осваивать stm32. По традиции решил с портом побаловаться.
Написал простенькую програмку: пустой цикл, раз в секунду прерывание таймера... в его обработчике считываю состояние порта А, прибавляю +1, вывожу результат обратно в порт... использую первые 8 выводов 0-7.
В результате должно получиться что-то вроде этого:
анимация1.gif
анимация1.gif (28.99 КБ) 9985 просмотров
- правильная работа
Но получается вот это:
анимация2.gif
анимация2.gif (27.71 КБ) 9985 просмотров
- неправильнаяработа
Запускаю в симуляторе - выполняет правильно. Запускаю от 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

Аватара пользователя
BSVi
Адепт
Сообщения: 3576
Откуда: Киев

Сообщение BSVi » 26 ноя 2013, 00:19

Честно-говоря, врядле тут очень много любителей асма под ARMы. Да и вообще, очень странный выбор. Может таки стоит на сях переписать, хоть другие понять смогут.

tomatniy
Сообщения: 70
Откуда: Киев

Сообщение tomatniy » 26 ноя 2013, 02:03

Лень вспоминать назначение регистров, а темболее перепроверять ваши адресса регистров в коде, но я бы посоветовал все-таки не писать в резервные биты. Вы это делаете, кода инкрементируете порт и когда сбрасываете таймер, а в даташите не говорится о том, что в резервных битах нули. Перепроверте все-таки инициализацию и сброс таймера, больше нигде ошибок быть не должно. А также что для PA0 не включена альтернативная функция, что может каким-то образом держать этот бит всегда в еденице.

Wypuk
Сообщения: 4

Сообщение Wypuk » 26 ноя 2013, 06:36

На Си я еще не умею. А с ассемблером все просто и ясно, поэтому пока на нем.
tomatniy писал(а):я бы посоветовал все-таки не писать в резервные биты. Вы это делаете, кода инкрементируете порт и когда сбрасываете таймер... А также что для PA0 не включена альтернативная функция, что может каким-то образом держать этот бит всегда в еденице.

Что касается не писать в резервные биты - я туда и не пишу: использую команду STRB а не STR. А флаг прерывания таймера я сбрасываю bit-band-ингом вообще. И вряд ли это связано с альтернативной функцией - ведь с SysTick таймером все правильно работает. Поэтому подозреваю, что это связано с какими-то особенностями таймеров.

Wypuk
Сообщения: 4

Сообщение Wypuk » 28 ноя 2013, 06:39

Меня один граммотный человек на одну правильную мысль навел. Контроллер походу 2 раза подряд вызывал программу обработки прерывания. Скорее всего, когда я сбрасываю флаг прерывания он попросту не успевает сбрасываться и обратно в это же прерывание заходит. Я вставил 8 NOP после того как флаг сбрасываю и стало нормально. Нужно еще немного поэкспериментировать, чтобы наверняка удостовериться, что дело в этом.
Тут я походу немного не понимаю, как контроллер узнает, что из прерывания вышел? По идее для выхода из прерывания используется просто комманда перехода, так какая процессору нахрен разница? Может после использования регисра ссылки LR коммандой BX у него внутри как-то сбрасывается признак нахождения в прерывании? Можно этот момент пояснить? И еще, лучше наверное флаг прерывания сбрасывать сразу же в начале обработчика, чтобы лишними NOP память не забивать? И еще интересно как такая проблемка в СИ обходится?

Аватара пользователя
N1X
Сообщения: 321
Откуда: Беларусь, Гомель

Сообщение N1X » 28 ноя 2013, 21:24

Выход из прерывания используется команда возврата из прерывания, которую отличает от команды возврата из подпрограммы как раз то, что размаскируется соответствующее/группа прерываний...

Аватара пользователя
BSVi
Адепт
Сообщения: 3576
Откуда: Киев

Сообщение BSVi » 29 ноя 2013, 00:11

Наверное, у автора получилось то-же, что и в совсем соседнем топике.

uschema.com
Сообщения: 162

Сообщение uschema.com » 12 дек 2013, 10:11

Wypuk писал(а):На Си я еще не умею. А с ассемблером все просто и ясно, поэтому пока на нем.

Данное предложение вызвало длинную улыбку.
Я бы эту фразу даже в мэмы занёс. ;)

Вернуться в «Микроконтроллеры и ПЛИС»



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей