Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Миландр 1986ВЕ1Т
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Captain
Всех приветствую. Работал ли кто с Миландрами? Никак не могу настроить прерывания от таймера (ни одного). Код такой:

CODE
int cnt1, cnt2, cnt3;

/*
* Прерывание таймера 1 (14)
* Смещение в таблице векторов 0x40 + 14 * 4 = 0x78
*/
void Vector78(void) {

cnt1 += 1;

MDR_TIMER1->STATUS = (uint32_t) 0;

}

/*
* Прерывание таймера 2 (15)
* Смещение в таблице векторов 0x40 + 15 * 4 = 0x7C
*/
void Vector7C(void) {

cnt2 += 1;

MDR_TIMER2->STATUS = (uint32_t) 0;

}

/*
* Прерывание таймера 3 (16)
* Смещение в таблице векторов 0x40 + 16 * 4 = 0x80
*/
void Vector80(void) {

cnt3 += 1;

MDR_TIMER3->STATUS = (uint32_t) 0;

}

int main(void) {

int cnt4 = 0;
cnt1 = cnt2 = cnt3 = 0;

... Код включения тактирования ядра и таймеров в другом модуле ...

MDR_TIMER1->CNTRL = (uint32_t) 0;
MDR_TIMER1->CNT = (uint32_t) 0;
MDR_TIMER1->PSG = (uint32_t) 0;
MDR_TIMER1->ARR = (uint32_t) 4095;
MDR_TIMER1->IE = TIMER_IE_CNT_ARR_EVENT_IE | TIMER_IE_CNT_ZERO_EVENT_IE;
MDR_TIMER1->STATUS = (uint32_t) 0;
MDR_TIMER1->CNTRL = (uint32_t) 1;

MDR_TIMER3->CNTRL = (uint32_t) 0;
MDR_TIMER3->CNT = (uint32_t) 0;
MDR_TIMER3->PSG = (uint32_t) 0;
MDR_TIMER3->ARR = (uint32_t) 4095;
MDR_TIMER3->IE = TIMER_IE_CNT_ARR_EVENT_IE | TIMER_IE_CNT_ZERO_EVENT_IE;
MDR_TIMER3->STATUS = (uint32_t) 0;
MDR_TIMER3->CNTRL = (uint32_t) 1;

MDR_TIMER2->CNTRL = (uint32_t) 0;
MDR_TIMER2->CNT = (uint32_t) 0;
MDR_TIMER2->PSG = (uint32_t) 0;
MDR_TIMER2->ARR = (uint32_t) 4095;
MDR_TIMER2->IE = TIMER_IE_CNT_ARR_EVENT_IE | TIMER_IE_CNT_ZERO_EVENT_IE;
MDR_TIMER2->STATUS = (uint32_t) 0;
MDR_TIMER2->CNTRL = (uint32_t) 1;

NVIC_EnableIRQ(TIMER1_IRQn);
NVIC_EnableIRQ(TIMER2_IRQn);
NVIC_EnableIRQ(TIMER3_IRQn);

while (true) {
cnt4 += 1;
}
}


Смотрю по GDB - МК в прерывания не заходит, счетчики cnt1..3 не инкриментируются ни разу.
Что уже проверял:
1. Все таймеры точно затактировались и считают:
Код
(gdb) p *0x40070000 // Регистр TIMER1->CNT
$82 = 3285
$83 = 1406
$84 = 2573
$85 = 1891


2. Вектора в таблице правильные:
Код
(gdb) p Vector78
$86 = {void (void)} 0x300 <Vector78>
(gdb) p *0x00000078
$87 = 769 // 0x300 == (769 & 1)


3. Флаги статуса прерываний подняты:
Код
(gdb) p *0x40070058 // Регистр TIMER1->IE
$88 = 3 // Прерывания по 0 и по ARR разрешены
(gdb) p *0x40070054 // Регистр TIMER1->STATUS
$89 = 3 // Оба события


4. В NVIC прерывания разрешены:
Код
(gdb) p *0xE000E100
$90 = 114688 // Биты 14,15,16


5. Всяко пробовал таскать строку включения прерывания таймера (до включения счетчика и после). Безрезультатно.

6. Что я упускаю?
adnega
Цитата(Captain @ Mar 23 2017, 12:55) *
Код
int cnt1, cnt2, cnt3;

6. Что я упускаю?

volatile ?
HardEgor
Цитата(Captain @ Mar 23 2017, 16:55) *
Смотрю по GDB - МК в прерывания не заходит, счетчики cnt1..3 не инкриментируются ни разу.

Лучше в прерывании инвертировать состояние какой-нибудь ноги GPIO и смотреть осциллографом - тогда железно видно, входит в прерывание или нет.
А так, да видимо volatile не хватает.
Captain
Спасибо за ответы. Могу, конечно ошибаться, но volatile не имеет смысла при -O0. Как водится, только написал пост - и сразу нашел проблему - прерывания были просто замаскированы. Установил PRIMASK =0 и все завертелось.
novikovfb
Цитата(Captain @ Mar 23 2017, 14:26) *
Спасибо за ответы. Могу, конечно ошибаться, но volatile не имеет смысла при -O0. Как водится, только написал пост - и сразу нашел проблему - прерывания были просто замаскированы. Установил PRIMASK =0 и все завертелось.

а чем форум Миландра то не устроил? http://forum.milandr.ru/viewforum.php?f=22
AVR
Рад что вопрос темы успешно решен.
Я работаю сейчас с одним Миландром, пытаюсь настроить SSP в режиме SPI, Вам приходилось работать с этим интерфейсом? Есть вопросы.
Captain
Цитата(AVR @ Mar 23 2017, 15:34) *
Рад что вопрос темы успешно решен.
Я работаю сейчас с одним Миландром, пытаюсь настроить SSP в режиме SPI, Вам приходилось работать с этим интерфейсом? Есть вопросы.

Да я по сути ни с чем еще и не работал на нем. Был приказ импортозамещать - вот и развлекаюсь rolleyes.gif . Сейчас портирую драйвера для ChibiOS HAL (ибо вся прикладуха под ней), но до spi пока не добрался. Но Вы спрашивайте - хотя бы будет ясно какими граблями по лбу получать.
KRS
Цитата(AVR @ Mar 23 2017, 15:34) *
Миландром, пытаюсь настроить SSP в режиме SPI

там вроде не должно быть проблем! именно этот модуль у них стандартный...
(такой же, как например, у LPC)
AVR
Цитата(Captain @ Mar 24 2017, 10:39) *
до spi пока не добрался. Но Вы спрашивайте - хотя бы будет ясно какими граблями по лбу получать.

Не, там всё в принципе работает как надо, не сложно. Однако я не могу понять как убрать задержку между словами при выдаче данных SSP/SPI. Я засунул несколько 16-битных слов в FIFO, но они вылазят с некой паузой, не знаю как ее занулить, и можно ли в принципе? Устройству требуется жесткие соотношения единиц и нулей и их длительность, пытаюсь заменить ПЛИС (где всё работает).
adnega
Цитата(AVR @ Mar 25 2017, 18:33) *
Устройству требуется жесткие соотношения единиц и нулей и их длительность,

О каких примерно скоростях идет речь?
Если используется DMA (что вероятно), то между DMA-запросом и DMA-транзакцией в Cortex-M может быть
порядка 12 тактов (насколько я помню), поэтому правильно, что записываете по 16-бит.
AVR
Цитата(adnega @ Mar 25 2017, 19:23) *
О каких примерно скоростях идет речь?

один бит 450 нс (это ~2.2 МГц)
adnega
Цитата(AVR @ Mar 25 2017, 19:26) *
один бит 450 нс (это ~2.2 МГц)

Это мало. Я сталкивался с проблемой на максимальной скорости SPI (правда, на STM32F1).
У миландров есть предделитель частоты для блоков. Например, у таймеров нужно вставлять NOP-ы,
чтобы дать время на запись регистров, если частота тактирования таймера ниже процессорной.
Код можете показать?
AVR
Цитата(adnega @ Mar 25 2017, 19:57) *
Код можете показать?
Нажмите для просмотра прикрепленного файла
Был бы рад не видеть осциллографом паузы между SSP_SendData(MDR_SSP2, 0x5555), ведь всё идет через FIFO...
jcxz
Цитата(AVR @ Mar 25 2017, 17:33) *
Не, там всё в принципе работает как надо, не сложно. Однако я не могу понять как убрать задержку между словами при выдаче данных SSP/SPI.

Если модуль там (как тут писали) подобен LPC-шному, то никак. В LPC, с которыми я имел дело, это никак не убирается.
И DMA или не-DMA тут не при чём. Пауза между словами вносится самой схемой SSP вне зависимости от загрузки FIFO.
AVR
Цитата(jcxz @ Mar 26 2017, 12:34) *
Если модуль там (как тут писали) подобен LPC-шному, то никак. В LPC, с которыми я имел дело, это никак не убирается
Спасибо за информацию, а то я бился головой в стену. Если задержка фиксированная, то я смогу подгадать, чтобы ноль приходился на эту паузу...
jcxz
Цитата(AVR @ Mar 26 2017, 11:39) *
Спасибо за информацию, а то я бился головой в стену. Если задержка фиксированная, то я смогу подгадать, чтобы ноль приходился на эту паузу...

Ну я это говорю про LPC17... Но если говорят что там всё так же....
Нетрудно самому проверить и убедиться: запретить прерывания, загрузить FIFO полностью и посмотреть осциллограмму.
Сделать это лучше на малой частоте SCLK. И повторить в разных режимах.
adnega
Цитата(jcxz @ Mar 26 2017, 12:34) *
Пауза между словами вносится самой схемой SSP вне зависимости от загрузки FIFO.

Это как? На сколько тактов задержка?

В Документации есть
Цитата
Так в режиме ведущего устройства для обеспечения максимальной скорости обмена 1.8432 Мбит/с

Видимо, ~2.2МГц низя...
jcxz
Цитата(adnega @ Mar 26 2017, 23:09) *
Это как? На сколько тактов задержка?

Не знаю. Я её зрительно на осциллограммах видел. Мне в принципе она никогда критична не была.
Так на глаз - примерно 0.5...1 клока SCLK насколько помню.
adnega
Цитата(jcxz @ Mar 27 2017, 00:27) *
Не знаю. Я её зрительно на осциллограммах видел. Мне в принципе она никогда критична не была.
Так на глаз - примерно 0.5...1 клока SCLK насколько помню.

По осциллограмме зрительно можно и ошибиться (я, например, не различаю длительности 2 или 3 бита).
Использовал SPI для генерации видео и задержка даже в 0.5 бита была бы видна.
Дык, это на STM32 с его "полутораземлекоповским" буфером, а тут полноценный FIFO.
Вряд ли инженеры настолько плохо все спроектировали, что задержка должна быть принципиально.
jcxz
Ещё раз повторю - дело не в фифо (естественно он полностью загружен) и не в плохом проектировании (думаю это было сделано специально).
Различить 2 и 3 бита может и сложно, но вот 0.5 и 0 бит - совершенно чётко различаются на глаз.
Но правда я уже давно не работал с LPC17xx, так что может быть путаю их с Tiva (с которыми работал не так давно).
Да, и я говорю не про SPI, а про SSP. Если Вы работали с LPC17xx, то должны понимать разницу.
KRS
пауза из-за CS
посмотрите на картинку SPI там видно.
И в стандартной реализации которую использует milandr (так же NXP, кстати описание можно на роlном сайте ARM найти) эти паузы между словами не убрать.
jcxz
Цитата(KRS @ Mar 27 2017, 14:52) *
пауза из-за CS

Вот и у меня сложилось впечатление, что быстрей всего по этой причине.
AVR
Цитата(adnega @ Mar 27 2017, 00:09) *
В Документации есть
Видимо, ~2.2МГц низя...

Очень даже ЗЯ wink.gif Максимальная это F_CPU / 12 для слейва ~6.7 МГц, но кажется предел для мастера F_CPU / 2, если не ошибаюсь.
Осциллографу я верю - вижу 2.2 МГц.

Цитата
пауза из-за CS, эти паузы между словами не убрать

Я понимаю задержку CS перед первым словом, но между - обидно... Я обойду это тем, что подмухлюю ноль на эту паузу, так подгадаю делители. Но вот есть ли там другая периферия без этого недостатка?
Так бы ПЛИС можно было бы заменить в каких-то применениях, где нужна точность тайминга. Да вообще я бы увешал МК кучей подобных универсальных полезняшек, чтобы заменять ПЛИСы в каких-то случаях.
jcxz
Цитата(AVR @ Mar 27 2017, 15:12) *
Я понимаю задержку CS перед первым словом, но между - обидно... Я обойду это тем, что подмухлюю ноль на эту паузу, так подгадаю делители. Но вот есть ли там другая периферия без этого недостатка?

Если так критично, можно попробовать сделать так:
SSP - в режим слэйва, запрограммировать любой таймер на желаемую SCLK, подать эту SCLK на вход своего SSP и её-же - удалённому устройству, так же сгенерить CS (себе на вход SP и его-же - удалённому устройству), не забыть поменять местами MISO/MOSI. Оба устройства буду работать в режиме слэйва.
Хотя, если на то пошло, то лучше не проектировать так устройство, чтобы оно было чувствительно к непрерывности клока.
KRS
Цитата(AVR @ Mar 27 2017, 16:12) *
Я понимаю задержку CS перед первым словом, но между - обидно...

Так откуда контроллер знает где первое слово, где последнее...
В данной реализации CS дергается между словами, длина слова в конфигурационном регистре (до 16 бит).

Вот у Atmelовских ARM - навороченная реализация... там даже можно несколькими CS аппаратно управлять...


jcxz
Цитата(KRS @ Mar 28 2017, 06:09) *
Вот у Atmelовских ARM - навороченная реализация... там даже можно несколькими CS аппаратно управлять...

У Infineon-а ещё навороченней: кроме нескольких CS, можно произвольно (в тактах) задать длительность паузы в начале передачи (между CS=0 и первым SCLK), в конце и между словами, и длина слова произвольная - от 1-го до 16 бит wink.gif
У OMAP L-137/L-138 тоже есть управление несколькими CS.
Captain
Вот дошли руки до ДМА и что-то второй день ни в какую не могу заставить это работать. Кое-как из того, что написано в документации (а написано, надо сказать коряво) родил такой код:
CODE
static dmaCtrlData_t dmaCtrlData[16]
__attribute__((aligned(512), section("ahb_lite")));
volatile char tmp1[] = "DMA test string.";
volatile char tmp2[20];

int main(void) {

... инициализация клоков ...

memset(dmaCtrlData, 0x0, sizeof(dmaCtrlData));

// Reset to the initial state.
MDR_DMA->CTRL_BASE_PTR = (uint32_t) dmaCtrlData;
MDR_DMA->CFG = 1U;
MDR_DMA->CHNL_SW_REQUEST = 0U;
MDR_DMA->CHNL_PRI_ALT_CLR = 0xFFFFFFFF;
MDR_DMA->CHNL_PRIORITY_CLR = 0xFFFFFFFF;
MDR_DMA->CHNL_REQ_MASK_SET = 0xFFFFFFFF;
MDR_DMA->CHNL_USEBURST_CLR = 0xFFFFFFFF;
MDR_DMA->CHNL_ENABLE_CLR = 0xFFFFFFFF;
MDR_DMA->ERR_CLR = 1U;

// Configure DMA_CH0
dmaCtrlData[0].dmaSrcEndAddr = (uint32_t) tmp1 + sizeof(tmp1) - 1;
dmaCtrlData[0].dmaDstEndAddr = (uint32_t) tmp2 + sizeof(tmp1) - 1;
dmaCtrlData[0].dmaControl = (0x00 << 30) | // One byte destination increment;
(0x00 << 28) | // Destination transfer unit size;
(0x00 << 26) | // One byte source increment;
(0x00 << 24) | // Source transfer unit size;
(0U << 21) | // dst_prot_ctrl (whatever this is - let it be 0);
(0U << 18) | // src_prot_ctrl;
(15U << 14) | // Acquire the bus and do not release until the transfer complete;
((sizeof(tmp1) - 1) << 4) |
// Transfers count - 1.
(0U << 3) | // next_useburst ??
(1U << 0); // Simple request mode. Auto-request mode does not work either.
MDR_DMA->CHNL_REQ_MASK_CLR = 1U;
MDR_DMA->CHNL_ENABLE_SET = 1U;
MDR_DMA->CHNL_SW_REQUEST = 1U;

... зацикливаемся ...
}

Здесь пытаюсь скопировать строку из tmp1 в tmp2. Собственно для проверки, что все заполнилось правильно:
1. Значения регистров MDR_DMA и dmaCtrlData для 1 канала ДО запуска передачи (MDR_DMA->CHNL_SW_REQUEST = 1U):
CODE
{ STATUS = 0x101f0001,
CFG = 0x0,
CTRL_BASE_PTR = 0x20100000,
ALT_CTRL_BASE_PTR = 0x20100200,
WAITONREQ_STATUS = 0x7fffffff,
CHNL_SW_REQUEST = 0x0,
CHNL_USEBURST_SET = 0x0,
CHNL_USEBURST_CLR = 0x0,
CHNL_REQ_MASK_SET = 0xfffffffe,
CHNL_REQ_MASK_CLR = 0xfffffffe,
CHNL_ENABLE_SET = 0x1,
CHNL_ENABLE_CLR = 0x1,
CHNL_PRI_ALT_SET = 0x0,
CHNL_PRI_ALT_CLR = 0x0,
CHNL_PRIORITY_SET = 0x0,
CHNL_PRIORITY_CLR = 0x0,
RESERVED0 = {0x0, 0x0, 0x0},
ERR_CLR = 0x0 }

{ dmaSrcEndAddr = 0x20000614,
dmaDstEndAddr = 0x20005588,
dmaControl = 0x3c101,
dmaUnused = 0x0 }

2. И ПОСЛЕ:
CODE
{ STATUS = 0x101f0001,
CFG = 0x0,
CTRL_BASE_PTR = 0x20100000,
ALT_CTRL_BASE_PTR = 0x20100200,
WAITONREQ_STATUS = 0x7fffffff,
CHNL_SW_REQUEST = 0x0,
CHNL_USEBURST_SET = 0x0,
CHNL_USEBURST_CLR = 0x0,
CHNL_REQ_MASK_SET = 0xfffffffe,
CHNL_REQ_MASK_CLR = 0xfffffffe,
CHNL_ENABLE_SET = 0x0,
CHNL_ENABLE_CLR = 0x0,
CHNL_PRI_ALT_SET = 0x0,
CHNL_PRI_ALT_CLR = 0x0,
CHNL_PRIORITY_SET = 0x0,
CHNL_PRIORITY_CLR = 0x0,
RESERVED0 = {0x0, 0x0, 0x0},
ERR_CLR = 0x0 }

{ dmaSrcEndAddr = 0x20000614,
dmaDstEndAddr = 0x20005588,
dmaControl = 0x3c000,
dmaUnused = 0x0 }

И казалось бы ДМА отработал (dmaControl перешел в режим "Стоп" и счетчик обнулился, а также сбросился Enable на первом канале)... но фиг там, содержимое tmp2 - как были нули так и остались. Для проверки - адреса:
Код
(volatile char (*)[17]) 0x20000604 <tmp1>
(volatile char (*)[20]) 0x20005578 <tmp2>
(dmaCtrlData_t (*)[16]) 0x20100000 <dmaCtrlData>

Что я забыл/не учел?

bb-offtopic.gif Из так называемого даташита - не смог понять что за передачи с кэшированием/буферизацией и как это использовать. Аналогично - не понятно в чем разница между режимами "Основной" и "Авто-запрос".
HardEgor
Там на форуме есть ссылки на SPL с готовыми примерами.
Потом появился pack для Keil - Milandr.MDR1986BExx.1.4.2.pack, там тоже примеры есть.
Еще на форуме выкладывали, как я понял, тестовые программы без SPL, называются так Examples_for_1986VE1_31_01_2012.rar или так 1986VE1T_demoprogramms___part1.rar

Правда у меня DMA в режиме ping-pong так и не заработал и я плюнул на него.
Если что, могу ссылочкой на свой архив с упомянутыми файлами поделиться.
Captain
Цитата(HardEgor @ Apr 6 2017, 12:56) *
Там на форуме есть ссылки на SPL с готовыми примерами.
Потом появился pack для Keil - Milandr.MDR1986BExx.1.4.2.pack, там тоже примеры есть.
Еще на форуме выкладывали, как я понял, тестовые программы без SPL, называются так Examples_for_1986VE1_31_01_2012.rar или так 1986VE1T_demoprogramms___part1.rar

Правда у меня DMA в режиме ping-pong так и не заработал и я плюнул на него.
Если что, могу ссылочкой на свой архив с упомянутыми файлами поделиться.

Да, нашел эти примеры. Там ДМА работает с УАРТом, но не суть. Проблема в том, что написано РОВНО то же самое, что и у меня... прямо строка в строку. Я сейчас даже порядок инициализации такой же как там сделал.
HardEgor
Цитата(Captain @ Apr 6 2017, 17:50) *
Да, нашел эти примеры. Там ДМА работает с УАРТом, но не суть. Проблема в том, что написано РОВНО то же самое, что и у меня... прямо строка в строку. Я сейчас даже порядок инициализации такой же как там сделал.

Также пробовал примеры с ДМА использовать, но не заработало. Так как не очень критично было - копать не стал.
Там вообще похоже документацию студенты писали - где-то прямой перевод документации ARM, где-то собственное творчество и в общем оно между собой не всегда стыкуется sad.gif
Например про Ethernet написано что прерывания есть, а по факту, в чипе они не подключены к NVIC, про прерывания написано что бывают по уровню и по фронту, но по факту все прерывания NVIC работают по уровню, а если надо по фронту - то используйте таймер и его прерывание, и т.д. и т.п
.
У них работает саппорт, и даже отвечает на технические вопросы. Поэтому засылайте им запрос с исходником и обязательно приложите реквизиты своей фирмы.
Captain
Цитата(HardEgor @ Apr 6 2017, 14:25) *
Также пробовал примеры с ДМА использовать, но не заработало. Так как не очень критично было - копать не стал.
Там вообще похоже документацию студенты писали - где-то прямой перевод документации ARM, где-то собственное творчество и в общем оно между собой не всегда стыкуется sad.gif
Например про Ethernet написано что прерывания есть, а по факту, в чипе они не подключены к NVIC, про прерывания написано что бывают по уровню и по фронту, но по факту все прерывания NVIC работают по уровню, а если надо по фронту - то используйте таймер и его прерывание, и т.д. и т.п
.
У них работает саппорт, и даже отвечает на технические вопросы. Поэтому засылайте им запрос с исходником и обязательно приложите реквизиты своей фирмы.

Похоже, что так и придется сделать. А эзернет я вроде раскурил, там тоже плохо с документацией, но он по крайней мере работает. Прерывания, кстати, тоже работают, но тут может быть дело в ревизии МК. Там с прерываниями другая проблема - пока мк в обработчике прерывания - приходят новые кадры и заново прерывание само собой не срабатывает.
AVR
Цитата(HardEgor @ Apr 6 2017, 14:25) *
Там вообще похоже документацию студенты писали - где-то прямой перевод документации ARM, где-то собственное творчество и в общем оно между собой не всегда стыкуется sad.gif
Например про Ethernet написано что прерывания есть, а по факту, в чипе они не подключены к NVIC, про прерывания написано что бывают по уровню и по фронту, но по факту все прерывания NVIC работают по уровню, а если надо по фронту - то используйте таймер и его прерывание, и т.д. и т.п

Эррата?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.