Перейти к содержанию
    

Минимальный код для работы с портом AT91SAM7

Всем доброго времени суток! Возникла необходимость перейти с AVR на ARM-ы. Вот тут сразу незадачка вышла. Прочитал, пересмотрел, перелопатил достаточно большое количество примеров программ, литературы (Бедного редькина и Англ даташит). Купил отладочную платку, SAM7-P64, Wiggler программаторик. "Стянул" IAR с интернета, "вылечил" его и приступил к работе. Для начала решил определиться, какой же минимум подключаемых файлов необходим, ибо все примеры пестрят ТАКИМ их количеством, что порой черт ногу сломит.

Вроде подразобрался, написал первую прогу и тут же сел в лужу :wacko:

 

Как и водится, решил "поиграть" ножками для начала. Но перед тем как "зашивать", как водится запустил прогу в эмуляторе.

Эмулятор работает, прога на первый взгляд выполняется. НО!!!! В регистре PMC_SCSR после сброса (Выполнение программы только начинается) ВСЕ НУЛИ!! Когда флаг PCK (состояние тактирования процессора) должен быть установлен! И многие остальные регистры, так же не выходят на свое первоначальное состояние.

После выполнения записи в регистр PIO_SODR, как я полагаю, должны установиться соответствующие биты и в регистре PIO_ODSR. (а в PIO_SODR сброситься в окне эмулятора ????) Этого не происходит!!! Что за ерунда? Что я не правильно делаю? То же самое происходит и с остальными регистрами. Скажем при установки PIO_OER, не меняется PIO_OSR.... Программировать контроллер не программировал. Думал может надо разрешить тактирование PIO и процессора, дописал соответствующие команды, нифига. Пробовал записывать регистры состояния в отдельный регистр (считывал), думал может тут баг, ведь вроде они для чтения, но умом то понимал, что блин эмулятор должен показывать, как и ожидалось, ничего не произошло :) считались НУЛИ :)

 

Вот пример программы: (прошу не критиковать код ибо все получилось в результате безрезультатных попыток на скорую руку запустить эмулятор из имеющихся под рукой программ)

 

// *******************************************************

// Header Files

// *******************************************************

#include "AT91SAM7S256.h"

 

unsigned int a;

 

int main (void) {

 

while (1)

{

 

volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; // pointer to PIO data structure

volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;

 

pPMC->PMC_PCER = 1 << AT91C_ID_PIOA;

pPMC->PMC_SCER = 1 << 0;

 

pPIO->PIO_PER = 4; // PIO Enable Register - allow PIO to control pins

pPIO->PIO_OER = 0xFFFF; // PIO Output Enable Register

pPIO->PIO_SODR = 12; // PIO Set Output Data Register

pPIO->PIO_CODR = 4;

 

a = pPIO->PIO_ODSR;

// a = pPIO->PIO_CODR;

 

}

 

 

 

 

}

 

 

 

 

 

 

Прошу помощи!!!!! HELP!!!

Чего не хватает, где упущение, если можно , то образец минимального набора прикрипляемых файлов и кода программы хотелось бы посмотреть для управления ножками контроллера

Изменено пользователем Vinterman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как и водится, решил "поиграть" ножками для начала. Но перед тем как "зашивать", как водится запустил прогу в эмуляторе.

...

Программировать контроллер не программировал.

Т.е. запустили в симуляторе, а не под эмуляцией. Бросьте это дело и забудьте про симуляцию периферии на ARM.

 

 

pPMC->PMC_SCER = 1 << 0;

Это явно лишнее, остального достаточно для ногодрыганья.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Т.е. запустили в симуляторе, а не под эмуляцией. Бросьте это дело и забудьте про симуляцию периферии на ARM.

Это явно лишнее, остального достаточно для ногодрыганья.

 

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

 

Сегодня вечером попробую "подрыгать лапкой". И если успеется, то опробую прерывание от таймера использовать, для тренировки и освоения работы с прерываниями. Ждите развития темы и новых вопросов :)

 

Один из всплывших вопросов. Почему я вынужден из-за, на мой взгляд, корявого файла описателя "AT91SAM7S256.h" писать такие строки:

 

volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;

pPIO->PIO_OER = 0xFFFF;

 

Есть в нете, более грамотные описатели, чтобы можно было указывать сразу понравившийся регистр, в следующем формате:

 

PIO_OER = 0xFFFF;

 

Или в ручную придется перелопачивать все ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Один из всплывших вопросов. Почему я вынужден из-за, на мой взгляд, корявого файла описателя "AT91SAM7S256.h" писать такие строки:

 

volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA;

pPIO->PIO_OER = 0xFFFF;

 

Есть в нете, более грамотные описатели, чтобы можно было указывать сразу понравившийся регистр, в следующем формате:

 

PIO_OER = 0xFFFF;

 

Или в ручную придется перелопачивать все ?

А зачем так сложно? Можно написать:

AT91C_BASE_PIOA->PIO_OER = 0xffff;

или

*AT91C_PIOA_OER = 0xffff;

 

Можно перелопатить хидер, чтобы писать просто PIOA_OER = 0xffff. Поиск->замена рулит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем так сложно? Можно написать:

AT91C_BASE_PIOA->PIO_OER = 0xffff;

или

*AT91C_PIOA_OER = 0xffff;

 

Можно перелопатить хидер, чтобы писать просто PIOA_OER = 0xffff. Поиск->замена рулит.

 

Ну просто с одной стороны лень каждый раз писать "приставку" AT91C_BASE_ или *AT91C_, да и код более ляпистый получается, хочется красоты в програмке хоть какой-то :) Регистры же все равно не повторяются, поэтому я не понимаю зачем такую сложность ввели, вот в AVR-ках в этом отношении было просто, в прочем как и с установками флагов в регистрах. Тоже, понапридумывали по 3 регистра, 2 из которых управляют флагами, а результат и текущий статус вообще в 3-ем смотрится. По мне так не очень как то такие перемены. Вот и ищу более простые пути. С другой стороны с установкой флагов меньше мороки. Но стоит ли овчинка выделки ?

Изменено пользователем Vinterman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже, понапридумывали по 3 регистра, 2 из которых управляют флагами, а результат и текущий статус вообще в 3-ем смотрится. По мне так не очень как то такие перемены. Вот и ищу более простые пути. С другой стороны с установкой флагов меньше мороки. Но стоит ли овчинка выделки ?

В многозадачной системе стоит без вариантов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В многозадачной системе стоит без вариантов.

 

Возможно вы правы. И пока сам не напорюсь не удостоверюсь в собственном неведении :)

А как проще и прозрачнее со стороны "бывалого" обрабатывать прерывания. Структурку накидать можно? :)))))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

КУЛ!!! Вчера таки запустил Внутрисхемный отладчик!! Все работает, программа пашет. Правда покаааааа настройки все настроил..... В общем забыл про "линковщик", попарился.

Теперь вот следующая трабла возникла, как запрограммировать с помощью Wiggler Флэш память контроллера????? Чтобы не в дебугере проект свой тестить, а уже в независимом не от кого железе.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как проще и прозрачнее со стороны "бывалого" обрабатывать прерывания. Структурку накидать можно? :)))))

Есть два варианта - с использоавнием вложенных прерываний и без него.

 

В любом случае ставим загрузку PC из AIC_IVR непосредственно на векторе:

0x18        ldr        pc, [pc, #-0xf20]    ; IRQ

 

Если не использовать вложения, то дальше все просто (на примере таймера PIT):

#define    PIT_HZ        1000
#define    PIT_PERIOD    ((mck + PIT_HZ * 8) / (PIT_HZ * 16))

int main(void)
{
    // Install System interrupt handler
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (u_int)sys_irq_handler;
    AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_SYS);

    AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | (PIT_PERIOD - 1);
}

__irq void sys_irq_handler(void)
{
    AT91C_BASE_PITC->PITC_PIMR;
    ...
    // Что-то еще делаем
    ...
    AT91C_BASE_AIC->AIC_EOICR = 0;
}

 

С вложением придется добавить еще один уровень на асме:

        GET at91sam7x128.inc
        GET arm.inc

; ***************************************************************************
; *
        IMPORT    sys_irq_handler

        EXPORT    sys_irq_wrapper

; ***************************************************************************
; *
        AREA    code0, CODE, READONLY

; ***************************************************************************
; *

sys_irq_wrapper
;- Adjust and save LR_irq mode in IRQ stack
        sub        r14, r14, #0x04
        stmfd    sp!, {r14}

;- Save SPSR and r0 in IRQ stack
        mrs        r14, SPSR
        stmfd    sp!, {r0, r14}

;- Enable Interrupt and Switch in SYS Mode
        mrs        r14, CPSR
        bic        r14, r14, #I_BIT
        orr        r14, r14, #ARM_MODE_SVC
        msr        CPSR_c, r14

;- Save scratch/used registers and LR in User Stack
        stmfd    sp!, {r1-r4, r12, r14}

        bl        sys_irq_handler

;- Restore scratch/used registers and LR from User Stack
        ldmfd    sp!, {r1-r4, r12, r14}

;- Disable Interrupt and switch back in IRQ mode
        mrs        r0, CPSR
        bic        r0, r0, #ARM_MODE_SYS
        orr        r0, r0, #I_BIT :OR: ARM_MODE_IRQ
        msr        CPSR_c, r0

;- Mark the End of Interrupt on the AIC
        ldr        r0, =AT91C_BASE_AIC
        str        r0, [r0, #AIC_EOICR]

;- Restore SPSR_irq and r0 from IRQ stack
        ldmfd    sp!, {r0, r14}
        msr        SPSR_cxsf, r14

;- Restore ajusted LR_irq from IRQ stack directly in the PC
        ldmfd    sp!, {pc}^

        END

#define    PIT_HZ        1000
#define    PIT_PERIOD    ((mck + PIT_HZ * 8) / (PIT_HZ * 16))

int main(void)
{
    // Install System interrupt handler
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = PRIOR_SYSTEM;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (u_int)sys_irq_wrapper;
    AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_SYS);

    AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | (PIT_PERIOD - 1);
}

void sys_irq_handler(void)
{
    AT91C_BASE_PITC->PITC_PIMR;
    ...
    // Что-то еще делаем
    ...
}

 

Примеры для RealView, для IAR'а придется доработать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Огромное спасибо за разъяснения! Сегодня разгреб время для дальнейшего освоения контроллера! Буду дальше разбираться !:)))

И чтоб я без вас делал?

:cheers:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Замучали меня уже эти прерывания! ПОМОГИТЕ !!!

Как в "сях" вставить асмовый код, да еще к тому же и по нужному нам вектору

Ведь данную строчку то надо написать:

0x18 ldr pc, [pc, #-0xf20] ; IRQ

 

Я ее пытался написать, а IAR в свою очередь ругается на саму строчку. пишет "Синтаксическая ошибка операнда", но перед этим ругался на "метку" (думал что адрес - это метка), я использовал директиву org. После этого он стал выдавать мне синтаксическую ошибку, что незнает такой команды. Я уже и мытьем и катаньем эти прерывания... А они не сдаются. Помогите победить! Просто не хочу подключать кучу файлов типа cstartup и board, ведь проект то будет не на отладочную плату. К томуже я не очень то силен в том, что написано в асмовском файле стартапника, отчего и не могу доконца сам разобраться что к чему....

Мне надо либо образец, либо книгу нормальную, гдеб правильно были и грамотно расписаны функции, которые приводят к обработке прерываний, либо помощ... :help:

 

Уже многое из периферии попробовал, а вот прерывания так и не могу "осилить"...... :cranky:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде разобрался с кодом на асме. Компилит сам код без ошибок вышеописанных, но блин, выдаются следующие ошибки:

post-35572-1227065078_thumb.jpg

даже когда код на асме урезаю до

 

PROGRAM ?RESET

RSEG INTRAMSTART_REMAP

RSEG INTRAMEND_REMAP

 

RSEG ICODE:CODE:ROOT(2)

CODE32 ; Always ARM mode after reset

 

reset

org 0x18

ldr pc,[pc,#-0xF20];

 

org 0x1c

ldr pc,[pc,#-0xF20];

 

 

ENDMOD

 

END

 

усе равно ошибка эта вылазит. Как только асмовский файл убиваю, так все тип топ и нормально дебугерется. :(

:help:

 

 

 

и еще, что означают вот эти строки ?

 

//* open FIQ interrupt

AT91F_PIO_CfgPeriph(AT91D_BASE_PIO_SW,AT91B_SW1,0);

AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_FIQ, FIQ_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE, FIQ_init_handler);

AT91F_AIC_EnableIt (pAic, AT91C_ID_FIQ);

 

Скачал примеры от атмела. плин, черт ногу сломит. Компилю их же пример, ошибка:

Fatal Error[e72]: Segment INTRAMEND_REMAP must be defined in a segment definition option (-Z, -b or -P)

что это, и где ее исправлять ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Компилит сам код без ошибок вышеописанных, но блин, выдаются следующие ошибки:

Ну так добавьте этот самый entry point в стартап:

 

    PUBLIC __program_start

__program_start:
InitReset:

 

что означают вот эти строки ?

Эти строки конфигурируют PIO и AIC через бредовую атмеловскую библиотеку.

Правильным решением будет изучить самостоятельно архитектуру процессора и

никогда не пользоваться AT91F_*.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде разобрался с кодом на асме. Компилит сам код без ошибок вышеописанных, но блин, выдаются следующие ошибки:
А что вас заставило вставлять в проект именно этот файл, именно с таким названием модуля и описывать в нем вектор ресета, который и так есть в библиотеке? Ведь именно на это и ругается линкер, но вы почему-то это предупреждение игнорируете. Для вашей одной единственной команды надо было создать файл с именем вроде irq_handler.s79 и таким содержимым:

    COMMON INTVEC:CODE:ROOT
    CODE32; Always ARM mode after reset 
    org 0x1c
    ldr pc,[pc,#-0xF20];
    END

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну так добавьте этот самый entry point в стартап:

 

    PUBLIC __program_start

__program_start:
InitReset:

Эти строки конфигурируют PIO и AIC через бредовую атмеловскую библиотеку.

Правильным решением будет изучить самостоятельно архитектуру процессора и

никогда не пользоваться AT91F_*.

 

Сенкс за ответ! :) Архитектуру то я уже изучил, а вот что это за функции, описанные, как оказалось в библиотеке я знать не знал, пока саму оную не посмотрел. Все просто оказалось. Млин, Атмеловские коды написаны мягко говоря через одно место. Вектора обработчиков прерываний, в процессе инициализации в примерах атмела, модифицируются ДВА!!! раза. Каламбур да и только. лишняя перестраховка от ложных срабатываний кристалла.

 

Насколько я разобрался, ругался IAR из-за того, что небыл описан путь в опциях проекта - вкладках препроцесоров для Си и АСМА. Такое может быть? Ибо одно единственное различие между моим кодом и кодом атмеля осталось только в этом :)))) Пойду домой проверять. Спасибо за ответы и советы! :a14:

 

А что вас заставило вставлять в проект именно этот файл, именно с таким названием модуля и описывать в нем вектор ресета, который и так есть в библиотеке? Ведь именно на это и ругается линкер, но вы почему-то это предупреждение игнорируете. Для вашей одной единственной команды надо было создать файл с именем вроде irq_handler.s79 и таким содержимым:

    COMMON INTVEC:CODE:ROOT
    CODE32; Always ARM mode after reset 
    org 0x1c
    ldr pc,[pc,#-0xF20];
    END

 

 

А заставило то, что я знать не знал как правильно код на асме в проекте записать. Теперь благодаря вам, - знаю :) Мне еще много предстоит изучить и сделать ошибок. Примного благодарен! :)

Изменено пользователем Vinterman

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...