Миландр

Ключевым подразделением нашей компании
является Центр Проектирования интегральных микросхем
Текущее время: 2019-ноя-15 02:36

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 28 ]  На страницу Пред.  1, 2 Все
Автор Сообщение
СообщениеДобавлено: 2019-апр-23 12:59 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1374
Откуда: Тула
Vasiliy писал(а):
Кнопка такая у меня есть, но с ней другая проблема. Прочитав "unreadposts" сообщение и не ответив сразу, сообщение из списка пропадает. А найти его заново очень не просто.

Это я предлагал как профилактику
Vasiliy писал(а):
... наткнулся случайно и впервые.

А в остальном - всё тоже самое, что и с электронной почтой - всё равно же как-то следите: или в блокнотик с карандашом, или "система тикетов", или другие варианты - как принято?

С учётом специфики форума, можно предложить просто открывать "долгоиграющий" тред в новой вкладке - она всегда будет на виду.
Вложение:
Комментарий к файлу: ;)
2019-04-23_12-58-53.png
2019-04-23_12-58-53.png [ 32.23 КБ | Просмотров: 1156 ]

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-апр-24 09:19 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 455
Откуда: ПКК "Миландр"
prostoRoman писал(а):
Это я предлагал как профилактику

Спасибо!

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-апр-26 11:34 
Не в сети

Зарегистрирован: 2014-дек-12 11:03
Сообщения: 15
Vasiliy писал(а):
LecOsget писал(а):
Ни в Errata, ни в документации это не описано. Хотя на мой взгляд поведение крайне неожиданное и стоило бы его описать.

При отсутствии ответа CAN непрерывно шлет сообщения, так положено по стандарту CAN. Мне нравится эта статья по CAN - http://www.micromax.ru/solution/theory- ... cles/2160/


К этому вопросов нет. Проблема, на мой взгляд, проявляется следующим образом:
1. На шине CAN одно устройство и некому выдать подтверждение на получение
2. Помещается сообщение на отправку и контроллер исправно непрерывно шлёт это сообщение пытаясь его доставить.
3. Выключается контроллера CAN. После этого контроллер, как и ожидается, перестаёт отправлять сообщение.
4. Через какое-то время контроллер переинициализируется и очищаются буфера на отправление и получение.
5. При включении после этого контроллера снова продолжает слать тоже самое сообщение, которое он слал до выключения/сброса контроллера. Даже если после переинициализации ничего не отправляется. Вот это, на мой взгляд, является ошибочным поведением.

Похоже, что сообщение сохраняется в теневом буфере контроллера CAN и этот буфер не сбрасывается при выключении/сбросе контроллера шины CAN.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-апр-29 09:38 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 455
Откуда: ПКК "Миландр"
Все верно, есть такая особенность поведения.
Хотелось бы конечно чтобы передатчик тоже сбрасывался, но тут другой вопрос - а зачем выключать блок CAN? Какой в этом практический смысл?

Мне не доводилось работать с CAN, но на сколько могу судить, типовое применение заключается в том, чтобы конечное устройство на базе микроконтроллера включилось и работало на шину CAN. Нужен перезапуск - есть питание и reset, в данном случае ничего вторично слаться в сеть не будет. Отвалилась сеть - блок работает по стандарту.

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-апр-29 11:34 
Не в сети

Зарегистрирован: 2014-дек-12 11:03
Сообщения: 15
Vasiliy писал(а):
Все верно, есть такая особенность поведения.
Хотелось бы конечно чтобы передатчик тоже сбрасывался, но тут другой вопрос - а зачем выключать блок CAN? Какой в этом практический смысл?


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


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-апр-29 14:04 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 455
Откуда: ПКК "Миландр"
После праздников проверю, как лучше погасить посылку и внесем уточнение в спецификацию.
Спасибо за пояснение.

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-май-08 13:32 
Не в сети

Зарегистрирован: 2017-апр-26 14:51
Сообщения: 455
Откуда: ПКК "Миландр"
По предварительным результатам, погасить зацикливание передачи в пустую линию можно, если CAN выключать такой функцией:

Код:
void CAN_Stop(MDR_CAN_TypeDef* CANx)
{
  if ((CANx->STATUS & CAN_STATUS_ERR_STATUS_Msk) != 0)
  {
    CANx->CONTROL = 0;
    CANx->CONTROL = CAN_CONTROL_STM | CAN_CONTROL_SAP | CAN_CONTROL_ROP | CAN_CONTROL_CAN_EN;
    while ((CANx->STATUS & 0xFFFFFFF2) != CAN_STATUS_TX_READY);
  }

  CANx->CONTROL = 0;
}


Как собственно в этой ветке и написано. Факт выхода из ошибок отслеживается по биту TX_READY, но чтобы он выставлялся необходимо чтобы в инициализации блока CAN в регистре INT_TX было разрешено событие по передаче. Сами же прерывания могут быть как включены, так и выключены. Т.е. если брать пример из Pack для Keil (C:\Keil_v5\ARM\PACK\Keil\MDR1986BExx\1.51\Examples\MDR1986VE1T\CAN\LoopBack_Interrupt), то инициализация такая:

Открыть
Код:
void CAN_InitEx(void)
{
  CAN_InitTypeDef  sCAN;
 
  /* Set the HCLK division factor = 1 for CAN1*/
  CAN_BRGInit(MDR_CAN1,CAN_HCLKdiv1);

  /* CAN register init */
  CAN_DeInit(MDR_CAN1);

  /* CAN cell init */
  CAN_StructInit (&sCAN);

  sCAN.CAN_ROP  = DISABLE; //ENABLE;  // Прием своих пакетов
  sCAN.CAN_SAP  = DISABLE;  // Подтверждение своих пакетов
  sCAN.CAN_STM  = DISABLE;  // Самотестирование
  sCAN.CAN_ROM  = DISABLE;  // Только на прием
  sCAN.CAN_PSEG = CAN_PSEG_Mul_2TQ;
  sCAN.CAN_SEG1 = CAN_SEG1_Mul_3TQ;
  sCAN.CAN_SEG2 = CAN_SEG2_Mul_2TQ;
  sCAN.CAN_SJW  = CAN_SJW_Mul_2TQ;
  sCAN.CAN_SB   = CAN_SB_3_SAMPLE;
  sCAN.CAN_BRP  = 1;
  CAN_Init (MDR_CAN1,&sCAN);

  CAN_Cmd(MDR_CAN1, ENABLE);

  /* Enable CAN1 interrupt */
  NVIC_EnableIRQ(CAN1_IRQn);

  /* Прерывания могут не включаться */
  //  CAN_ITConfig( MDR_CAN1, CAN_IT_GLBINTEN | CAN_IT_RXINTEN, ENABLE);
  //  CAN_RxITConfig( MDR_CAN1 ,(1<<rx_buf), ENABLE);
  /* Как и сам приемный буфер */
  //  CAN_Receive(MDR_CAN1, rx_buf, DISABLE);

  /* НО Без этого флаг TX_READY не выставится */
  CAN_TxITConfig( MDR_CAN1 ,(1<<tx_buf), ENABLE);
}

void CAN_Send(void)
{
  CAN_TxMsgTypeDef TxMsg;
   
  /* transmit */
  TxMsg.IDE     = CAN_ID_EXT;
  TxMsg.DLC     = 0x04;
  TxMsg.PRIOR_0 = DISABLE;
  TxMsg.ID      = 0x15555555;
  TxMsg.Data[1] = 0;
  TxMsg.Data[0] = 0x12345678;

  CAN_Transmit(MDR_CAN1, tx_buf, &TxMsg);
}
Закрыть


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

_________________
Отдел технической поддержки support@milandr.ru


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июн-29 13:53 
Не в сети

Зарегистрирован: 2018-янв-05 23:41
Сообщения: 101
Вопросы по работе CAN-контроллеров
1. Не нашел в спецификации описания процесса установки и сброса флагов ошибок в регистре MDR_CANx->STATUS:
Ошибки аппаратно только устанавливаются, а сбрасывать их надо программно? Или они и сбрасываются аппаратно если в последнем переданном/принятом CAN-кадре нет ошибок?
Например, останется ли выставленным в 1 флаг ACK_ERR после того, как контроллер послал в линию кадр, а подтверждение приёма пришло лишь с 4-го раза?
Понятно, что после отправки кадра в первый раз этот флаг выставится в 1 и останется таковым вплоть до окончания передачи кадра в 4-й раз. Но вот с 4-го раза от какого-то CAN-узла пришло подтверждение приёма, контроллер CAN это увидел. Вопрос: сбросит ли он флаг ACK_ERR в 0? Или это должна делать программа?
То же касается и всех прочих ошибок:
- FRAME_ERR
- CRC_ERR
- BIT_STUFF_ERR
- BIT_ERR
Надо бы добавить разъяснение в спецификацию.

2. Когда именно устанавливается флаг TX_READY в регистре MDR_CANx->STATUS? В момент окончания первой попытки передачи кадра CAN? Или только по окончании той попытки передачи, в которой было зафиксировано подтверждение приёма? В ситуации из предыдущего примера: этот флаг выставится сразу после первой попытки передачи, или только после 4-й?

3. Как себя ведёт передатчик CAN при проигрыше арбитража на шине? Сам аппаратно через какое-то время предпринимает попытку повторной передачи кадра? Или надо в программе опрашивать флаг IDLOWER и из программы пытаться ещё раз отправить кадр по-новой? Когда установится флаг TX_READY: после той попытки передачи, при которой не было проигрыша арбитража и весь CAN-кадр ушел в линию?

4. Посмотрел пример LoopBack_Polling (для 1986ВЕ1)
не понял, для чего там разрешать прерывания от приёмного и передающего буферов?
Код:
  /* Enable CAN1 interrupt from receive buffer */
  CAN_RxITConfig( MDR_CAN1 ,(1<<rx_buf), ENABLE);
  /* Enable CAN1 interrupt from transmit buffer */
  CAN_TxITConfig( MDR_CAN1 ,(1<<tx_buf), ENABLE);

Прерывания ведь не используются, да и в NVIC оно по-умолчанию запрещено и не разрешается.
Понял, это чтобы разрешить выставление флагов TX_READY и RX_READY в регистре STATUS по событиям завершения передачи и приёма - см. картинку в главе про прерывания.

5. А вот это что значит?
Код:
  /* receive buffer enable */
  CAN_Receive(MDR_CAN1, rx_buf, DISABLE);

Судя по комментарию, прием сообщений разрешается. А фактически запрещается. Зачем запрещать приём, если по-логике работы программы нам как раз и нужно принять данные из CAN-шины в этот буфер?
Тоже понял, третий аргумент - это разрешение/запрет перезаписи принятых данных.

6. Кроме того, не увидел там нигде настройки маски и фильтров для приёмного буфера. Это как? В спецификации сказано, что значения этих регистров после включения питания или/и сброса неопределённые (безобразие, конечно). Значит они требуют обязательной ручной настройки перед приёмом. Иначе сообщения будут хаотично отфильтровываться.
И что-то не смог найти этих самых регистров маски и фильтра в спецификации ни на 1986ВЕ9х, ни на 1986ВЕ1. Да, они есть в общей таблице со всеми регистрами блока CAN, но детального описания на них нет.


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июл-02 07:58 
Не в сети

Зарегистрирован: 2010-авг-30 19:12
Сообщения: 457
Цитата:
И что-то не смог найти этих самых регистров маски и фильтра в спецификации ни на 1986ВЕ9х, ни на 1986ВЕ1. Да, они есть в общей таблице со всеми регистрами блока CAN, но детального описания на них нет.

Смотрите внимательно спецификацию.
Например на 1986ВЕ91
Цитата:
21.14.11 MDR_CANx->RXID
MDR_CANx->TXID
MDR_CANx->CAN_BUF[x].ID
MDR_CANx->CAN_BUF_FILTER[x].MASK
MDR_CANx->CAN_BUF_FILTER[x].FILTER


Фактически регистр ID сообщения и регистр ID/маски фильтра имеют одинаковый формат (вот их в кучу и свалили).

_________________
О сколько нам открытий чудных
Готовит просвященья дух,
И опыт - сын ошибок трудных ... (Пушкин)

Пергаменты не утоляют жажду ("Фауст",Гете)


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июл-02 21:19 
Не в сети

Зарегистрирован: 2018-янв-05 23:41
Сообщения: 101
редактор писал(а):
Смотрите внимательно спецификацию.
Например на 1986ВЕ91
Цитата:
21.14.11 MDR_CANx->RXID
MDR_CANx->TXID
MDR_CANx->CAN_BUF[x].ID
MDR_CANx->CAN_BUF_FILTER[x].MASK
MDR_CANx->CAN_BUF_FILTER[x].FILTER


Фактически регистр ID сообщения и регистр ID/маски фильтра имеют одинаковый формат (вот их в кучу и свалили).

В спецификации на 1986ВЕ1 такого нет.
Там есть только:
Открыть
Цитата:
20.14.11 CANx_RXID
20.14.12 CANx_TXID
20.14.13 CANx_BUF_xx_ID
Закрыть


Вот фрагмент кода из примера Examples\MDR1986VE1T\CAN\LoopBack_Polling
Открыть
Код:
  CAN_Transmit(MDR_CAN1, tx_buf, &TxMsg);

  i = 0;
  while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY) != RESET) && (i != 0xFFF))
  {
    i++;
  }
  CAN_ITClearRxTxPendingBit(MDR_CAN1, tx_buf, CAN_STATUS_TX_READY);

  i = 0;
  while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_RX_READY) == RESET) && (i != 0xFFF))
  {
    i++;
  }
Закрыть


Там есть ошибка
Имеется:
while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY) != RESET) && (i != 0xFFF))
Должно быть:
while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY) == RESET) && (i != 0xFFF))


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июл-06 11:17 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1374
Откуда: Тула
Professor Chaos писал(а):
... Там есть ошибка
Имеется:
while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY) != RESET) && (i != 0xFFF))
Должно быть:
while(((CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY) == RESET) && (i != 0xFFF))

MDR32F9Qx_StdPeriph_Driver/src/MDR32F9Qx_can.c
Код:
#define CAN_STATUS_TX_READY         (((uint32_t)0x1) <<  1) /*!< Flag indicating that there are buffers for transmitting */

CMSIS/CM3/DeviceSupport/MDR32F9Qx/inc/MDR32Fx.h
Код:
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus, BitStatus;

так что "оба хуже".

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июл-06 11:49 
Не в сети

Зарегистрирован: 2009-июл-21 14:13
Сообщения: 1374
Откуда: Тула
Си++-way...
Код:
inline enum FlagStatus CAN_StatusTxReady(CAN_Typedef *CANx) {
  if(CANx->Status & CAN_STATUS_TX_READY) {
    return SET;
  } else {
    return RESET;
  }
}

или
Код:
inline bool CAN_ifStatusTxReady(CAN_Typedef *CANx) {
  if(CANx->Status & CAN_STATUS_TX_READY) {
    return true;
  } else {
    return false;
  }
}

тогда
Код:
while( !CAN_ifStatusTxReady(MDR_CAN1) && (i != 0xFFF))


ну и если i - счётчик цикла, то
Код:
i = 0; TIMEOUT = 0xfff; // а лучше TIMEOUT = 5000;
......
while( !CAN_ifStatusTxReady(MDR_CAN1) &&  i<TIMEOUT)


А то такая зубодробилка в SPL....

_________________
сочувствующий…


Вернуться к началу
 Профиль  
 
СообщениеДобавлено: 2019-июл-07 15:37 
Не в сети

Зарегистрирован: 2018-янв-05 23:41
Сообщения: 101
Сделал
Код:
while( !(CAN_GetStatus(MDR_CAN1) & CAN_STATUS_TX_READY)  || ( i>TIMEOUT)));


В моей программе два одинаковых устройства (CAN-узла) посылали в шину кадр, ждали окончания его передачи и ожидали приёма кадра от соседнего узла, после чего отключали блок CAN:
- узел 1 посылал в шину кадр данных и ожидал приёма кадра от узла 2, после чего отключал CAN;
- узел 2 посылал в шину кадр данных и ожидал приёма кадра от узла 1, после чего отключал CAN;
Оба узла независимы и несинхронизированы между собой. Получалась ситуация, что на шине я видел кадр лишь от одного из узлов. Кадра другого не было, хотя бит подтверждения приёма он корректно выставлял. У одного из узлов стабильно взводилась ошибка: не дождался приёма кадра по CAN от "соседа". Дело, как оказалось, было как раз в этом некорректном условии в цикле ожидания завершения передачи. Узел, начинавший передачу позже благополучно проскакивал этот цикл ожидания завершения передачи и переходил к приёму. В приёмном буфере к тому моменту у него уже был принятый кадр "соседа". Он его считывал, обрабатывал и выключал блок CAN, так и не успев начать передачу (в это время его блок CAN ждал освобождения линии и выдерживал межкадровый интервал перед началом передачи). Второй же узел видел подтверждение приёма своего кадра, но не дожидался приёма кадра "соседа" и взводил ошибку.
Ну и вместо простого инкрементного счётчика i я использовал функцию проверки на истечение интервала времени. Сделал по образу и подобию этого, с небольшими доработками.
Такая вот ситуация.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 28 ]  На страницу Пред.  1, 2 Все

Часовой пояс: UTC + 3 часа


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
cron
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB