реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Keil Arm. Нарушена последовательность выполнения+++, Помогите новичку. Зешел в тупик - не работает UART
Димон Безпарольн...
сообщение Mar 5 2011, 09:10
Сообщение #1


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Есть нехитрый код

Цитата
int main (void) {
int i;
float F1, F2, F3;
1 *RSTC_MR = 0xA5000000;
2 *WDT_MR = 0x3FFF2FFF;
3 *CKGR_MOR = 0x0000ff01;
4 *MC_FMR = 0x00320100;
5 *PMC_MCKR = 0x13;
6 *CKGR_PLLR = 0x00ff3fff;
7 *PMC_PCER = 0x22
8 *PIO_PDR = 0x4
9 *US_CR = 0x8f9
10 *US_MR = 0xf152
11 *US_BRGR = 0x4;
12 *US_CR = 0xfae5


и так далее

В окне дизасемблирования по шагам (включен Assebly Mode)
Строки 1 и 2 выполняются последовательно. Но

Инструкция *WDT_MR = 0x3FFF2FFF; состоит из одной загрузки: LDR R0,[PC,#0x00D8] Т.е. сохранения STR нет.

Дальше выполняется почему - то строка 10, потом 3, потом программа прыгает вообще в цикл и сбрасывает WDT, потом 4, потом снова в цикл и выполняет *PIO_CODR = led_mask[i];, потом строки 5, 6, 7.

Команда
Цитата
*US_CR = (0x1 << 2) | //Reset Receiver
(0x1 << 3) | //Reset Transmitter
(0x1 << 5) | //Receiver Disable
(0x1 << 7); //Transmitter Disable


Интерпретируется как SUB R0,R3,R0,ASR #12

Где я напортачил? Черт, второй день бьюсь - почему не работает UART0 - а тут вообще странно что что - то работает.

Помогите! Закипел!

Сообщение отредактировал Димон Безпарольный - Mar 5 2011, 09:12
Go to the top of the page
 
+Quote Post
Dima_G
сообщение Mar 5 2011, 09:29
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699



Цитата(Димон Безпарольный @ Mar 5 2011, 15:10) *
Есть нехитрый код

На самом деле, код очень хитрый - через месяц вы не поймете, что он делает.
По теме: оптимизация выключена?
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Mar 5 2011, 10:43
Сообщение #3


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Dima_G @ Mar 5 2011, 12:29) *
На самом деле, код очень хитрый - через месяц вы не поймете, что он делает.
По теме: оптимизация выключена?

Стоит Default и Enable ARM / Thumb. Последнюю сейчас попробую выключить...

Странно, но код загрузки регистров

Цитата
AT91C_BASE_US0->US_CR = 0x0 | //Normal Mode
(0x0 << 4)| //Clock = MCK
(0x3 << 6)| //8-bit Data
(0x4 << 9)| //No Parity
(0x0 << 12); //1 Stop Bit

AT91C_BASE_SYS ->WDTC_WDMR = 0x3FFF2FFF;
AT91C_BASE_CKGR->CKGR_MOR = 0x0000ff01;
AT91C_BASE_SYS ->RSTC_RMR = 0xA5000000;


Совершенно иной, чем если пользоваться типа такого: *WDT_MR1 = 0x3FFF2FFF;

И выполняется последовательно. Похоже на долбаную оптимизицию. Наверно прийдется просто переписать код...
Go to the top of the page
 
+Quote Post
Dron_Gus
сообщение Mar 5 2011, 13:12
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861



А регистры у Вас как определены? Явно без volatile.


--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Mar 5 2011, 14:34
Сообщение #5


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(Dron_Gus @ Mar 5 2011, 16:12) *
А регистры у Вас как определены? Явно без volatile.

Точно. Регистры у меня поределены так:
Цитата
#define PIO_PER1 ((unsigned int *) 0xFFFFF400) //Запрещение периферии, разрешение PIO
#define PIO_PDR1 ((unsigned int *) 0xFFFFF404) //Запрещение PIO, разрешение периферии
#define PIO_PSR1 ((unsigned int *) 0xFFFFF408) //Запрещение PIO, разрешение периферии

#define PIO_OER1 ((unsigned int *) 0xFFFFF410) //Разрешение PIO управлять выходом
#define PIO_ODR1 ((unsigned int *) 0xFFFFF414) //
#define PIO_OSR1 ((unsigned int *) 0xFFFFF418) //

#define PIO_SODR1 ((unsigned int *) 0xFFFFF430) //Установка в 1 выводов PIO
#define PIO_CODR1 ((unsigned int *) 0xFFFFF434) //Сброс в 0 выводов PIO
#define PIO_ODSR1 ((unsigned int *) 0xFFFFF438) //
#define PIO_PDSR1 ((unsigned int *) 0xFFFFF43C) //

#define PIO_MDER1 ((unsigned int *) 0xFFFFF450) //
#define PIO_MDDR1 ((unsigned int *) 0xFFFFF454) //
#define PIO_MDSR1 ((unsigned int *) 0xFFFFF458) //

#define PIO_PUDR1 ((unsigned int *) 0xFFFFF460) //Включение подтягивающих резисторов
#define PIO_PUER1 ((unsigned int *) 0xFFFFF464) //
#define PIO_PUSR1 ((unsigned int *) 0xFFFFF468) //

#define PIO_ASR1 ((unsigned int *) 0xFFFFF470) //
#define PIO_BSR1 ((unsigned int *) 0xFFFFF474) //Выбор периферии В
#define PIO_ABSR1 ((unsigned int *) 0xFFFFF478) //

#define PMC_SCER1 ((unsigned int *) 0xFFFFFC00) //Разрешение тактирования процессора и выводов PCKx
#define PMC_SCDR1 ((unsigned int *) 0xFFFFFC04) //
#define PMC_SCSR1 ((unsigned int *) 0xFFFFFC08) //

#define PMC_PCER1 ((unsigned int *) 0xFFFFFC10) //Регистр тактирования периферии
#define PMC_PCDR1 ((unsigned int *) 0xFFFFFC14) //
#define PMC_PCSR1 ((unsigned int *) 0xFFFFFC18) //

#define CKGR_MOR1 ((unsigned int *) 0xFFFFFC20) //Main Oscillator Register
#define CKGR_MCFR1 ((unsigned int *) 0xFFFFFC24) //

#define CKGR_PLLR1 ((unsigned int *) 0xFFFFFC2C) //Регистр режима PLL
#define PMC_MCKR1 ((unsigned int *) 0xFFFFFC30) //Регистр выбора источника тактовых импульсов процессора и делитель

#define PMC_PCK01 ((unsigned int *) 0xFFFFFC40) //Регистр режима выходов PCK0
#define PMC_PCK11 ((unsigned int *) 0xFFFFFC44) //Регистр режима выходов PCK1

#define RSTC_MR1 ((unsigned int *) 0xFFFFFD08) //Регистр режима сброса

#define WDT_CR1 ((unsigned int *) 0xFFFFFD40) //Регистр сброса Watchdog Timer
#define WDT_MR1 ((unsigned int *) 0xFFFFFD44) //Регистр режима Watchdog Timer
#define WDT_SR1 ((unsigned int *) 0xFFFFFD48) //Регистр статуса Watchdog Timer

#define MC_FMR1 ((unsigned int *) 0xFFFFFF60) //Регистр режима флэш контроллера

#define US_CR1 ((unsigned int *) 0xFFFC0000) // (US_CR) Control Register
#define US_MR1 ((unsigned int *) 0xFFFC0004) // (US_MR) Mode Register
#define US_IER1 ((unsigned int *) 0xFFFC0008) // (US_IER) Interrupt Enable Register
#define US_IDR1 ((unsigned int *) 0xFFFC000C) // (US_IDR) Interrupt Disable Register
#define US_IMR1 ((unsigned int *) 0xFFFC0010) // (US_IMR) Interrupt Mask Register
#define US_CSR1 ((unsigned int *) 0xFFFC0014) // (US_CSR) Channel Status Register
#define US_RHR1 ((unsigned int *) 0xFFFC0018) // (US_RHR) Receiver Holding Register
#define US_THR1 ((unsigned int *) 0xFFFC001C) // (US_THR) Transmitter Holding Register
#define US_BRGR1 ((unsigned int *) 0xFFFC0020) // (US_BRGR)Baud Rate Generator Register
#define US_RTOR1 ((unsigned int *) 0xFFFC0024) // (US_RTOR)Receiver Time-out Register
#define US_TTGR1 ((unsigned int *) 0xFFFC0028) // (US_TTGR)Transmitter Time-guard Register
#define US_FIDI1 ((unsigned int *) 0xFFFC0040) // (US_FIDI)FI_DI_Ratio Register
#define US_NER1 ((unsigned int *) 0xFFFC0044) // (US_NER) Nb Errors Register
#define US_IF1 ((unsigned int *) 0xFFFC004C) // (US_IF) IRDA_FILTER Register


Единица на конце - чтобы имена не пересекались.
Go to the top of the page
 
+Quote Post
hlebn
сообщение Mar 6 2011, 09:30
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 131
Регистрация: 22-10-04
Пользователь №: 963



у меня была такая же засада только на stm32
оптимизация меняла порядок действий
лечилось описанием адресов регистров не как просто переменная в памяти а именно как регистр ввода вывода
(16 *) xxx - описание переменной в памяти (оптимизация полная вплоть до выброса из проекта если не используется по мнению компилятора)
__IO (u16 *) xxx - описание регистра ввода вывода (без оптимизации и пере упорядочения)

для AT91 было
__iomem (u16 *) xxx - описание регистра ввода вывода

а volatile - вроде требует от компилятора только обязательной перезагрузки переменной перед использованием и на глубокую оптимизацию не влияет(но я могу ошибаться так как не программист)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Mar 6 2011, 09:39
Сообщение #7


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Посмотрите определения __IO и __iomem и убедитесь, что они содержат volatile.
Go to the top of the page
 
+Quote Post
hlebn
сообщение Mar 6 2011, 09:51
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 131
Регистрация: 22-10-04
Пользователь №: 963



Цитата(IgorKossak @ Mar 6 2011, 12:39) *
Посмотрите определения __IO и __iomem и убедитесь, что они содержат volatile.

да посмотрел. так и есть.
извиняюсь
просто почему то был уверен что volatile не помогал
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Mar 9 2011, 12:01
Сообщение #9


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Прошу прощения - прервался.

Оптимизатор действительно выкидывает строки. Например, если писать:
Цитата
*PIO_PDR1 = (1 << 5) | //Enable RxD0 Pin
(1 << 6); //Enalbe TxD0 Pin


То соответствующей строки в дизасемблере просто не будет.

Если писать
Цитата
AT91C_BASE_PIOA->PIO_PDR = (1 << 5) | //Enable RxD0 Pin
(1 << 6); //Enalbe TxD0 Pin

То пара строк LDR, STR появляется. Результат - в первом случае на запускается UART. Сие для меня пока загадка.

Цитата(hlebn @ Mar 6 2011, 12:30) *
у меня была такая же засада только на stm32
оптимизация меняла порядок действий
лечилось описанием адресов регистров не как просто переменная в памяти а именно как регистр ввода вывода
(16 *) xxx - описание переменной в памяти (оптимизация полная вплоть до выброса из проекта если не используется по мнению компилятора)
__IO (u16 *) xxx - описание регистра ввода вывода (без оптимизации и пере упорядочения)

для AT91 было
__iomem (u16 *) xxx - описание регистра ввода вывода

а volatile - вроде требует от компилятора только обязательной перезагрузки переменной перед использованием и на глубокую оптимизацию не влияет(но я могу ошибаться так как не программист)

Было бы неплохо иметь возможность описывать регистры как регистры, а не ячейки памяти.

Но я в С новичок. Пробовал гуглить __iomem и iomem - без результата. В хелпе Keil тоже ничего. Синтаксис подобрать не смог.

Может ткнете меня где почитать?
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 9 2011, 12:27
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Найдите, где у вас в .h файле определен PIO_PDR1. Должно быть, что-то типа:

typedef volatile unsigned int AT91_REG;
#define PIO_PDR1 ((AT91_REG *) 0xFFFFА04) // AT91C_BASE_PIOA->PIO_PDR
Go to the top of the page
 
+Quote Post
Димон Безпарольн...
сообщение Mar 9 2011, 12:38
Сообщение #11


Знающий
****

Группа: Участник
Сообщений: 734
Регистрация: 29-11-10
Пользователь №: 61 247



Цитата(sergeeff @ Mar 9 2011, 15:27) *
Найдите, где у вас в .h файле определен PIO_PDR1. Должно быть, что-то типа:

typedef volatile unsigned int AT91_REG;
#define PIO_PDR1 ((AT91_REG *) 0xFFFFА04) // AT91C_BASE_PIOA->PIO_PDR

Да, полегчало сразу как определил:

Цитата
#define PIO_PDR1 ((volatile unsigned int *) 0xFFFFF404) //Запрещение PIO, разрешение периферии


Спасибо.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 16:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01443 секунд с 7
ELECTRONIX ©2004-2016