Использование К1921ВК01Т и 1508ПЛ8Т

32-разрядные микроконтроллеры разработки АО "НИИЭТ"

Модераторы: ea, dav, bkolbov, Alis, pip, _sva_

Аватара пользователя
kirra
Сообщения: 5
Зарегистрирован: 21 янв 2016, 16:56
Предприятие: ЗАО "НПЦ "Алмаз-Фазотрон"
Откуда: Саратов

Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение kirra »

Здравствуйте!
Планируется использовать К1921ВК01Т и возникло пару вопросов.
Первый заключается в том, что использовать МК будем для управления двумя DDS 1508ПЛ8Т.
Для этого, разработана следующая схема включения (см. вложение). Схема весьма условная, но основные моменты, затронутые в вопросе на ней указаны.
Подключаем две DDS к шине как внешнюю память к выводам контроллера использующих третью альтернативную функцию (в соответствии с таблицей 7.6 из технического описания).
Тогда DDS отобразятся на адресное пространство 0x40000000 (исходя из таблицы 6.7). Т.к. запись в 1508ПЛ8Т происходит, если сначала указывается на шине адрес внутреннего регистра (при этом бит ADR в 0), потом значение для него (бит ADR в 1), то вполне логично, что записать данные data по адресу address можно следующим образом:

Код: Выделить всё

/** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
(*(volatile uint16_t *)0x40000000) = address_DDS0;
(*(volatile uint16_t *)0x40000001) = data_DDS0;

/** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
(*(volatile uint16_t *)0x40000000) = address_DDS1;
(*(volatile uint16_t *)0x40000002) = data1_DDS1;
Верно ли мое предположение?

И ещё, сейчас мне не совсем ясно назначение линий RAM_Ubn и RAM_Lbn. Рискну предположить, что это разрешение на работу старших 8-линий RAM_ADDR15RAM_ADDR8 (бит RAM_Ubn) и младших 8-линий RAM_ADDR7RAM_ADDR0 (бит RAM_Lbn), и если в моём случае используется все 16 разрядов, то есть смысл эти биты держать всего в активном состоянии.

Также хотелось, в дополнение к первому вопросу ещё узнать, можно ли использовать оставшиеся биты адреса по своему усмотрению? Например, как GPIO или использовать их с другой альтернативной функцией. Просто, даже если используется две DDS, то они займут всего 2 линии адреса (например RAM_ADDR0 и RAM_ADDR1), а остальные 10 линий получается остаются незадействованными.
И ещё по этому же вопросу, хотелось бы узнать временные характеристики работы внешней шины, на какую пропускную способность можно рассчитывать?

И второй небольшой вопрос заключается в следующем: например, у STM32 есть контроллер внешних прерываний, который может ловить прерывания по фронту/спаду и пр. В МК от ПКК «Миландр» внешние прерывания адекватно обработать можно было лишь используя таймер в режиме захвата. Тут, если опять же, все верно понимаю, для этих целей можно использовать блоки захвата (которых аж 6 штук), и заводить нужный сигнал на один из 4-х вход блока. Всего получается можно обработать 24 внешних прерываний (6 блоков по 4 входа в каждом). Могу ли я, использую блок захвата, например, на первом входе обработать прерывание переднего фронта и заднего фронта, а на втором входе, просто задний фронт сигнала? Или можно ещё какими-нибудь способами отрабатывать прерывания?
Аватара пользователя
kirra
Сообщения: 5
Зарегистрирован: 21 янв 2016, 16:56
Предприятие: ЗАО "НПЦ "Алмаз-Фазотрон"
Откуда: Саратов

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение kirra »

UPD
Добавил схему, которую хотел выложить в первом сообщении.
Вложения
test_dds.sch.rar
Схема в Eagle CAD
(26.66 КБ) 237 скачиваний
test_dds.pdf
Схема подключения 1508ПЛ8Т к 1921ВК01Т
(38.79 КБ) 338 скачиваний
R Max
Сообщения: 48
Зарегистрирован: 28 ноя 2015, 19:44

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение R Max »

kirra писал(а): И второй небольшой вопрос заключается в следующем: например, у STM32 есть контроллер внешних прерываний, который может ловить прерывания по фронту/спаду и пр. В МК от ПКК «Миландр» внешние прерывания адекватно обработать можно было лишь используя таймер в режиме захвата. Тут, если опять же, все верно понимаю, для этих целей можно использовать блоки захвата (которых аж 6 штук), и заводить нужный сигнал на один из 4-х вход блока. Всего получается можно обработать 24 внешних прерываний (6 блоков по 4 входа в каждом). Могу ли я, использую блок захвата, например, на первом входе обработать прерывание переднего фронта и заднего фронта, а на втором входе, просто задний фронт сигнала? Или можно ещё какими-нибудь способами отрабатывать прерывания?
Как я понял из ТО
| Показать
TO_K1921VK01T_Страница_073.jpg
TO_K1921VK01T_Страница_073.jpg (265.81 КБ) 5534 просмотра
TO_K1921VK01T_Страница_075.jpg
TO_K1921VK01T_Страница_075.jpg (235.48 КБ) 5534 просмотра
Схема вывода позволяет также осуществлять гибкое управление прерываниями и
задавать, по какому аппаратному событию генерировать прерывание (по какому фронту
или уровню). При возникновении прерывания в регистре INTSTATUS устанавливается
соответствующий флаг, и выставляется прерывание в контроллере прерываний Энвик.
Прерывание может быть сгенерировано программно записью единицы в соответствующий
бит регистра INTSTATUS.
Прерывание может быть сброшено программно записью единицы в
соответствующий бит регистра INTCLEAR. Для разрешения прерывания вывода порта
следует записать единицу в соответствующий выводу бит регистра INTENSET, а для
запрета прерывания – единицу в бит регистра INTENCLR.
Для задания события, по которому генерируется прерывание, используются
регистры INTTYPESET и INTPOLSET, а для сброса настроек – INTTYPECLR и
INTPOLCLR, соответственно.
Итого ~ 7*16+8 = 120 внешних прерываний портов GPIO
bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение bkolbov »

Добрый день!
Тогда DDS отобразятся на адресное пространство 0x40000000 (исходя из таблицы 6.7). Т.к. запись в 1508ПЛ8Т происходит, если сначала указывается на шине адрес внутреннего регистра (при этом бит ADR в 0), потом значение для него (бит ADR в 1), то вполне логично, что записать данные data по адресу address можно следующим образом:

Код: Выделить всё

    /** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
    (*(volatile uint16_t *)0x40000000) = address_DDS0;
    (*(volatile uint16_t *)0x40000001) = data_DDS0;

    /** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
    (*(volatile uint16_t *)0x40000000) = address_DDS1;
    (*(volatile uint16_t *)0x40000002) = data1_DDS1;
Верно ли мое предположение?
Не совсем верно.
В вашем случае необходимо выравнять адреса по 16-битному слову, т.е. использовать 1-ый и 2-ой биты адреса для подключения DDS.
Судя по схеме, вы используете разные сигналы OE и СE для каждой из микросхем, поэтому вам надо настроить их мультиплексирование, разделив адресное пространство по маске.
Допустим, можно установить самый старший бит поля CE_MASK в регистре EXT_MEM_CFG, таким образом включив мультеплексирование сигналов CSn и OEn по 19 биту адреса.
В итоге получается, что интерфейс внешней памяти дает доступ к общему 1МБ пространству, поделенному на 2 подпространства по 512К. Следовательно, CS0 и OE0 будут использоваться для доступа к первым 512К, CS1 и OE1 - ко вторым 512К.
Используя абсолютные адреса внешней памяти, можно сказать что:
0x40000000 - 0x400FFFFF общее пространство
0x40000000 - 0x4007FFFF RAM0
0x40080000 - 0x400FFFFF RAM1

В результате получим примерно такой код:

Код: Выделить всё

   
    /** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
    (*(volatile uint16_t *)0x40000000) = address_DDS0;
    (*(volatile uint16_t *)0x40000002) = data_DDS0;

    /** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
    (*(volatile uint16_t *)0x40080000) = address_DDS1;
    (*(volatile uint16_t *)0x40080004) = data1_DDS1;
Если я все правильно понимаю, то использование двух линий адреса будет даже избыточным - хватит и одной (например, первого бита), т.к. адресные пространства и так разделены, а OE и CS мультеплексированы.
И ещё, сейчас мне не совсем ясно назначение линий RAM_Ubn и RAM_Lbn. Рискну предположить, что это разрешение на работу старших 8-линий RAM_ADDR15 — RAM_ADDR8 (бит RAM_Ubn) и младших 8-линий RAM_ADDR7 — RAM_ADDR0 (бит RAM_Lbn), и если в моём случае используется все 16 разрядов, то есть смысл эти биты держать всего в активном состоянии.
UBn и LBn - это выходные сигналы, часто необходимые для подключения ОЗУ. В вашем случае они не нужны. Эти пины можно использовать как порты ввода-вывода.
Также хотелось, в дополнение к первому вопросу ещё узнать, можно ли использовать оставшиеся биты адреса по своему усмотрению?
Да, можно. Просто не включайте альтернативную функцию на этих пинах.
И ещё по этому же вопросу, хотелось бы узнать временные характеристики работы внешней шины, на какую пропускную способность можно рассчитывать?
На частотах примерно до 30МГц проблем возникнуть не должно.
Могу ли я, использую блок захвата, например, на первом входе обработать прерывание переднего фронта и заднего фронта, а на втором входе, просто задний фронт сигнала? Или можно ещё какими-нибудь способами отрабатывать прерывания?
Вообще, конечно можете и блок захвата использовать. Но необходимый вам функционал присутствует в контроллере GPIO. R Max уже подробно расписал об этом выше.
Аватара пользователя
kirra
Сообщения: 5
Зарегистрирован: 21 янв 2016, 16:56
Предприятие: ЗАО "НПЦ "Алмаз-Фазотрон"
Откуда: Саратов

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение kirra »

R Max писал(а): Итого ~ 7*16+8 = 120 внешних прерываний портов GPIO
Судя по тому, что на каждый порт один вектор прерывания, то определить, на какую именно ножку пришёл импульс, это можно прочитав лишь соотвествующий регистр. Таким образом для всех ножек одного порта (например для A0-A15) будет вызываться одно и тоже прерывание.

Код: Выделить всё

прерывание_от_порта_А
{
  если от_А0 { что-то делаем }
  если от_А1 { что-то делаем }
  ***
  если от_А15 { что-то делаем }
}
если я не прав, то поправьте меня пожалуйста.
bkolbov писал(а):Если я все правильно понимаю, то использование двух линий адреса будет даже избыточным - хватит и одной (например, первого бита), т.к. адресные пространства и так разделены, а OE и CS мультеплексированы.
если всё верно понял, то бит адреса у DDS будет один и тот же (например ADDR1), и тогда для доступа к DDS можно использовать ваш код таким образом:

Код: Выделить всё

/** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
(*(volatile uint16_t *)0x40000000) = address_DDS0;
(*(volatile uint16_t *)0x40000002) = data_DDS0;

/** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
(*(volatile uint16_t *)0x40080000) = address_DDS1;
(*(volatile uint16_t *)0x40080002) = data1_DDS1;
bkolbov писал(а):Вообще, конечно можете и блок захвата использовать. Но необходимый вам функционал присутствует в контроллере GPIO. R Max уже подробно расписал об этом выше.
А известно, сколько тактов микроконтроллер будет заходить в прерывание? И какой способ будет более производительный: использование блока захвата или использование контроллера GPIO?
R Max
Сообщения: 48
Зарегистрирован: 28 ноя 2015, 19:44

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение R Max »

Судя по тому, что на каждый порт один вектор прерывания, то определить, на какую именно ножку пришёл импульс, это можно прочитав лишь соотвествующий регистр. Таким образом для всех ножек одного порта (например для A0-A15) будет вызываться одно и тоже прерывание.
Я к тому, что количество входных выводов до 120, а так да - накладывать маску в прерывании и смотреть на каком выводе событие.
А известно, сколько тактов микроконтроллер будет заходить в прерывание? И какой способ будет более производительный: использование блока захвата или использование контроллера GPIO?
Я думаю, это только эксперимент покажет, потому что в арм кортекс-M есть конвейер.
prostoRoman
Сообщения: 57
Зарегистрирован: 11 июл 2014, 15:06

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение prostoRoman »

R Max писал(а):
А известно, сколько тактов микроконтроллер будет заходить в прерывание? И какой способ будет более производительный: использование блока захвата или использование контроллера GPIO?
Я думаю, это только эксперимент покажет, потому что в арм кортекс-M есть конвейер.
ИМХО абсолютно одинаково с этой точки зрения.
R Max
Сообщения: 48
Зарегистрирован: 28 ноя 2015, 19:44

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение R Max »

Кстати да, это же всё можно замерить https://community.арм.com/docs/DOC-2607
Debug Support
The кортекс-M processors support comprehensive debug support features. The кортекс-M3 and кортекс-M4 processors also offer exception trace support which allows the capture and examination of the exception/interrupt history and timing information in a debugger. The trace information can be captured using a single pin trace interface called Serial Wire Viewer (SWV), or a multi-bit trace port interface, which has higher trace bandwidth for supporting full instruction trace with an ETM (Embedded Trace Macrocell). The trace information can be very useful for debugging.
на 1986ВЕ9х от Миландра вроде и ITM хватало http://forum.milandr.ru/download/file.p ... &mode=view
bkolbov
Сообщения: 248
Зарегистрирован: 14 дек 2015, 11:37
Предприятие: АО НИИЭТ
Откуда: Воронеж

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение bkolbov »

Судя по тому, что на каждый порт один вектор прерывания, то определить, на какую именно ножку пришёл импульс, это можно прочитав лишь соотвествующий регистр. Таким образом для всех ножек одного порта (например для A0-A15) будет вызываться одно и тоже прерывание.

Код: Выделить всё

    прерывание_от_порта_А
    {
      если от_А0 { что-то делаем }
      если от_А1 { что-то делаем }
      ***
      если от_А15 { что-то делаем }
    }
если я не прав, то поправьте меня пожалуйста.
Все верно.
если всё верно понял, то бит адреса у DDS будет один и тот же (например ADDR1), и тогда для доступа к DDS можно использовать ваш код таким образом:

Код: Выделить всё

    /** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
    (*(volatile uint16_t *)0x40000000) = address_DDS0;
    (*(volatile uint16_t *)0x40000002) = data_DDS0;

    /** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
    (*(volatile uint16_t *)0x40080000) = address_DDS1;
    (*(volatile uint16_t *)0x40080002) = data1_DDS1;
Верно.
А известно, сколько тактов микроконтроллер будет заходить в прерывание?
Это величина непостоянная, для прикидочных расчетов её можно считать равной 12. Разработчики ядра здесь, довольно подробно осветили этот вопрос.
И какой способ будет более производительный: использование блока захвата или использование контроллера GPIO?
GPIO, но разница здесь в единицы тактов. Архитектура построения пути: изменение логического уровня -> синхронизация с внутренней тактовой частотой -> выделение фронта -> генерация сигнала прерывания к контроллеру Энвик, в этих блоках немного разная, и в GPIO этот путь несколько короче.
Аватара пользователя
kirra
Сообщения: 5
Зарегистрирован: 21 янв 2016, 16:56
Предприятие: ЗАО "НПЦ "Алмаз-Фазотрон"
Откуда: Саратов

Re: Использование К1921ВК01Т и 1508ПЛ8Т

Сообщение kirra »

Спасибо большое за столь подробные ответы.
В дополнении вопроса про адресацию, хотел ещё уточнить следующее. Допустим, что помимо двух DDS к микроконтроллеру подключена ещё микросхема внешнего ОЗУ (1645РУ6) емкостью 2Мб (1Мх16).
Используется первая альтернативная функцию для шины в микроконтроллере, и CS0,OE0 подключены к каждой из DDS, а CS1,OE1 к микросхеме RAM. Разделяю адресное пространство по маске (по ADDR18), получаю два подпространства по 512Кб.
Тогда получается следующее.
Первые 512Кб делят две DDS (0x40000000 - 0x4007FFFF). Бит ADDR1 подключен к DDS0, ADDR2 - к DDS1.

Код: Выделить всё

    /** в первую DDS записываем данные data_DDS0 по адресу address_DDS0 */
    (*(volatile uint16_t *)0x40000000) = address_DDS0;
    (*(volatile uint16_t *)0x40000002) = data_DDS0;

    /** во вторую DDS записываем данные data_DDS1 по адресу address_DDS1 */
    (*(volatile uint16_t *)0x40000000) = address_DDS1;
    (*(volatile uint16_t *)0x40000004) = data1_DDS1;
Второе подпростанство на 512Кб достается микросхеме RAM (0x40080000 - 0x400FFFFF)

Код: Выделить всё

    /** в RAM, в первый сектор на 512Кб, записываем данные data_RAM0 */
    RAM_BANK = 0;
    (*(volatile uint16_t *)0x40080000) = data_RAM0;
    /** в RAM, в второй сектор на 512Кб, записываем данные data_RAM1 */
    RAM_BANK = 1;
    (*(volatile uint16_t *)0x40080000) = data_RAM1;
Но в 1645РУ6 20 линий адреса, и меняя ADDR19 (который есть в 1645РУ6, но нет в 1921ВК01) битом RAM_BANK (который просто как GPIO) я могу переключать адресные пространства RAM. Таким образом получается, что 1645РУ6 делится битом RAM_BANK на два банка памяти (которые по идее по 1МБ, но доступно из них лишь по 512Кбб из-за того, что ADDR18 не доступен для использования).
В итоге, я могу использовать из RAM всего 1Мб, а 1Мб окажется незадействованным. Так ли всё это? Если да, то есть ли способ обойти данное ограничение?

Также, хотел узнать, есть ли разница, какой из наборов CS/OE выбирать для памяти, для которой задействованы биты RAM_Ubn и RAM_Lbn? И есть ли возможность не делить адресное пространство между CS0/OE0 и CS1/OE1 если используется просто микросхема памяти, без двух DDS?

Для ясности вопроса прикрепил электрическую схему.
Вложения
test_dds.rar
Схема в Eagle CAD
(32.8 КБ) 187 скачиваний
test_dds.pdf
Измененная схема включения
(52.02 КБ) 237 скачиваний
Ответить

Вернуться в «32-разрядные микроконтроллеры»