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

Посоветуйте пожалуйста, ввязываться ли

они выстроили протокол над CAN-контроллером, где имеют место быть квитанции (ACK).

 

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

В сеть то гарантирует, но неизвестно есть ли в сети в данный момент нужное устройство.

Вот еще вопрос про физическую топологию. Хочу в один кабель запхать и CAN, и питание. Тянуть чистую "шину" не получается, "звезда" в моем случае оптимальна. Т.е. есть плата-дистрибьютор с кучей разъемов, например, DB-9. Максимальное расстояние от дистрибьютора до узла - метра три. Вопрос - а где ставить терминаторы?

Нужно проложить пару туда-сюда к каждому девайсу. Всё равно наверняка лишние пары будут. А по другому никак. Усы 3 метра - это уже перебор.

Ну или по стандарту J1708 сделать. Там как раз звезда.

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


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

Усы 3 метра - это уже перебор.

Это зависит от битовой скорости. На 50 kbit отводы по 3-и метра несогласованным кабелем вполне работают.

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


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

Стандарт лезу читать.

 

Про ошибки опять. Правильно ли я понимаю, что в полном контроллере (хм, не уверен, что это термин из какого-то стандарта, но CAN-контроллер AT90CAN именно так зовется) передатчик будет биться за арбитраж, пока таймаут не пройдет?

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

 

И еще вопрос про RTR. Правильно ли я разумею, что это - заложенный в стандарт механизм опроса узлов, а как он (опрос и соответствующая реакция, т.е. что будет послано в ответ) будет реализован - отдано на откуп дизайнеру?

 

P.S. Извините пожалуйста за возможно глупые вопросы, я когда USB изучал, мозг на место вставал недели две ;)

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


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

Добрый день!

 

Ввязался ;)

 

Сейчас имеет место быть стенд из двух CAN-AVR от Olimex (at90can128 на борту).

Одна постоянно шлёт пакетики, другая - принимает и отправляет дебаг в RS-232, плюс отсылает пакетик регулярно.

 

Обнаружились забавные особенности.

Во-первых, пока плата была одна, и шины как таковой не было (и терминатор был только один), не работало вообще ничего - контроллер выдавал ошибку, и по таймауту передача накрывалась.

 

Во-вторых, но это возможно софтовый глюк, приемник принимает все пакеты передатчика по два раза, примерно вот так:

 

Rcvd: 0x153 8 8e1000000

Rcvd: 0x153 8 8e1000000

Rcvd: 0x153 8 8f1000000

Rcvd: 0x153 8 8f1000000

 

Ну и в третьих, если снять питание с передатчика, то приемник может совершить отсылку одного-двух пакетов, после чего ситуация повторяет обрыв линии, т.е. ошибка передачи.

 

Вопрос: а это правильно? Терминатор-то установлен вне зависимости от питания.

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


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

Всем привет опять!

 

Бьюсь, обессилил.

 

Со стороны передатчика - FreeRTOS и два таска:

 

/* continuously send CAN packets ID 0x151 with max speed (approx 1000Hz) */
static void send_function2( void *x)
{
(void)x;
static CAN_packet packet={0x151, 8, "\0\0\0\0\0\0\0\0"};
    
for(;; )
  {
   can_send( &packet, 10, 10);
   packet.data[1]++;
   vTaskDelay(500);
  }
}

/* periodically send CAN packet ID 0x150 */
static void send_function( void *x)
{
(void)x;
static CAN_packet packet;

packet.id=0x150;
packet.length=2;
packet.data[0]=0x00;
packet.data[1]=0xaa;
    
for(;; )
  {
   can_send( &packet, 13, 500);        
   packet.data[0]++;
   vTaskDelay(1000);
  }
}

 

Приемник - без изменений echo & spy из Атмеловских библиотек:

-0- RxCAN @ C20C: 0x00000150(Ext.), L=2, 81-AA
-0- RxCAN @ 047D: 0x00000151(Ext.), L=8, 00-03-00-00-00-00-00-00
-0- RxCAN @ 4686: 0x00000150(Ext.), L=2, 82-AA
-0- RxCAN @ 88FB: 0x00000151(Ext.), L=8, 00-05-00-00-00-00-00-00
-0- RxCAN @ CAFD: 0x00000150(Ext.), L=2, 83-AA
-0- RxCAN @ 0D72: 0x00000151(Ext.), L=8, 00-07-00-00-00-00-00-00
-0- RxCAN @ 4F75: 0x00000150(Ext.), L=2, 84-AA
-0- RxCAN @ 91EB: 0x00000151(Ext.), L=8, 00-09-00-00-00-00-00-00
-0- RxCAN @ D3EC: 0x00000150(Ext.), L=2, 85-AA
-0- RxCAN @ 1663: 0x00000151(Ext.), L=8, 00-0B-00-00-00-00-00-00

Т.е. каждый второй фрейм более "частого" таска - теряется. Ошибок нет, смотрел через JTAG регистры.

Вот теперь я гадаю, где теряется фрейм - на приемнике, или на передатчике.

 

Может кто-нибудь сталкивался?

 

Update: Вот еще глюк, это уже серьезно ИМХО:

-0- RxCAN @ E373: 0x00000151(Ext.), L=8, 00-0F-00-00-00-00-00-00
-0- TxCAN @ B704: 0x00000152(Ext.), L=8, 00-0F-00-00-00-00-E3-73
-0- RxCAN @ 2579: 0x00000150(Ext.), L=2, 08-AA
-0- TxCAN @ D47F: 0x00000151(Ext.), L=8, 08-AA-00-00-00-00-25-79
-0- RxCAN @ 67EB: 0x00000151(Ext.), L=8, 00-11-00-00-00-00-00-00

 

Отсюда видно, что пакетик в D47F есть суперпозиция пересылки пакета 2579 и D47F (08-AA и 00-10-00...). Где же гарантированная целостность? ;)

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


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

Про ошибки опять. Правильно ли я понимаю, что в полном контроллере (хм, не уверен, что это термин из какого-то стандарта, но CAN-контроллер AT90CAN именно так зовется) передатчик будет биться за арбитраж, пока таймаут не пройдет?

Нет. Каждый передатчик когда передает одновременно слушает линию. В CANе передатчики дерутся только в момент передачи ID пакета. В этот момент если один передатчик передаст 1 в линию а другой 0, то изза доминанты 0 в линии установится 0 и первый передатчик поймет, что арбитраж потерян и переключится на прием этого самого пакета от второго передатчика, то есть пакет не будет потерян. Так обеспечивется в CAN приоритет сообщений с более низким ID. Если же уровни не совпадут уже в теле сообщения - то это уже коллизия и будет ошибка. Обычно так бывает если два контроллера шлют сообщение с одним и тем же ID.

И еще вопрос про RTR. Правильно ли я разумею, что это - заложенный в стандарт механизм опроса узлов, а как он (опрос и соответствующая реакция, т.е. что будет послано в ответ) будет реализован - отдано на откуп дизайнеру?

Да. В атмелах помоему даже заложена возможность автоматической отправки ответа на RTR если пакет с соответсвующим адресом уже готов. По крайней мере в CC01 02 так.

Во-первых, пока плата была одна, и шины как таковой не было (и терминатор был только один), не работало вообще ничего - контроллер выдавал ошибку, и по таймауту передача накрывалась.

Конечно. Читайте внимательно спецификацию CAN. В сети должно быть как минимум 2 устройства изза того, что прием каждого сообщения приемником подтверждается установкой бита ACK в соответсвующий момент передачи. Так как у вас не было второго контроллера то первый не получал ACK и передача накрывалась.

Т.е. каждый второй фрейм более "частого" таска - теряется. Ошибок нет, смотрел через JTAG регистры.

Вот теперь я гадаю, где теряется фрейм - на приемнике, или на передатчике.

Не знаю, что у вас в can_send - проверьте там есть ли у вас поллинг окончания передачи. Может быть что запись нового сообщения в регистры происходит до окончания передачи предыдущего. А вообще лучше очередь сообщений организовать и использовать CAN_send в отдельном таске.

Последний глюк похоже тоже с этим связан.

Плюс, забыл, - не забывайте прерывания отключать в CAN_send - а то ваш FreeRTOS может переключиться на другой таск в самый неподходящий момент.

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


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

Читаю документец про сеть на борту наноспутника (http://etd.sun.ac.za/handle/10019/858 ) и удивляюсь: они выстроили протокол над CAN-контроллером, где имеют место быть квитанции (ACK).

 

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

 

Вот еще вопрос про физическую топологию. Хочу в один кабель запхать и CAN, и питание. Тянуть чистую "шину" не получается, "звезда" в моем случае оптимальна. Т.е. есть плата-дистрибьютор с кучей разъемов, например, DB-9. Максимальное расстояние от дистрибьютора до узла - метра три. Вопрос - а где ставить терминаторы?

 

Смотря от задачи могли скоректировать под себя протокол.

 

Протокол избыточен очень. Часть проверок можно опустить в пользу скорости. Мне как-то нужна была скорость максимальная. так вот: мне оказалось более выгодна 7бит адресация с передачей 8 байт без подтверждения для всех узлов сразу, чем деления на группы через фильтры.

 

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

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


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

Не знаю, что у вас в can_send - проверьте там есть ли у вас поллинг окончания передачи. Может быть что запись нового сообщения в регистры происходит до окончания передачи предыдущего. А вообще лучше очередь сообщений организовать и использовать CAN_send в отдельном таске.

Последний глюк похоже тоже с этим связан.

Плюс, забыл, - не забывайте прерывания отключать в CAN_send - а то ваш FreeRTOS может переключиться на другой таск в самый неподходящий момент.

 

Мысли мои читаете, или я - Ваши ;) Втыкал ночью в код и понял, что на самом деле вообще нигде не проверяю завершение передачи.

Про отдельную очередь на передачу тоже мысль родилась, вечером попробую.

 

Про остальные моменты - понял, я как-то не учел, что передатчик сам себя слушает, но Ack не доминантит ;)

 

Еще напоролся у атмела на некоторый TTC mode, использующий таймер CAN-контроллера. Пока не нашел, что это такое.

 

cant

спасибо за опыт, посчитал потребление конечных устройств и понял, что питание будет отдельными проводами ;)

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


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

Чисто полтергейст.

Функция отсылки фрейма, низкоуровневая:

BOOL can_tx( char mob,  CAN_packet *packet)
{
        unsigned short cnt;

        cli();//portENTER_CRITICAL();
        /* Select page (MOB 1) */
        CANPAGE = 1 << 4; 
        /* Setup DLC and IDE */
        CANCDMOB = (packet->length) | (1<<IDE);
        /* Setup ID */
        CANIDT1=0;
        CANIDT2=packet->id >>13;
        CANIDT3=packet->id >>5;
        CANIDT4=packet->id <<3;
        /* Load data to FIFO, byte index is autoincremented */
        for (cnt=0; cnt<8; ++cnt)
         CANMSG = packet->data[cnt];

        /* Debug counter */
        cnt=0;
        /* Start transmittion */
        CANCDMOB|=(1<<CONMOB0); //enable TX FIXME!!!
        /* Wait until TXOK is raised */
        while (!(CANSTMOB & (1<<TXOK))) {cnt++;}
        /* Reset TXOK by  read-modify-write */
        CANSTMOB &= ~(1<<TXOK);                              
        /* Reset (disable) MOB */
        CANCDMOB = 0x00;
        /* Finita */
        sei();
        return (TRUE);
}

 

Единственное место, где вызывается can_tx:

/* Task for CAN transmittion */
void can_tx_task(void *x)
{
(void)x;

static unsigned portCHAR mob;
static CAN_packet packet;
static unsigned portCHAR cnt;
static portCHAR retv=FALSE;

/* Create Tx queue */
CANTxQueue = xQueueCreate( 16, sizeof( CAN_packet));
ASSERT(CANTxQueue != 0);

/* Find free MOB, die if no free channel found */
/* FIXME!!! MOB #0 used by Dump queue */
cli();
for( mob=1; mob < NO_MOBS; ++mob)
  {
   if( channels[mob]==0)
                        break;
  }

ASSERT(mob != NO_MOBS);
channels[mob]=(CAN_cbf)0xffff;
sei();

/* Main loop */
while(1)
  {
   /* Receive packet to send */
   xQueueReceive( CANTxQueue, &packet, portMAX_DELAY);
   cnt=50;
   retv=TRUE;
   while( cnt--)
    {
     retv=can_tx( mob, &packet);
     if( retv==TRUE) // transmission succsessful
      {
       break;
      }
         vTaskDelay(1);
        }
  }
}

 

Многозадачность - кооперативная, не вытесняющая.

Если в дебаггере, с остановкой на sei() can_tx - все отлично, пакеты улетают друг за другом, все работает как задумано.

Без дебаггера - 2-байтовый пакет "затирает" длинный. Но не всегда Когда счетчик в первом байте длинного пакета (не ID, а payload) достигает 0x2a, все начинает работать как задумано ;) Эффект постоянный.

 

Что это???

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


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

Отвечу себе сам.

 

Это - криво написанная функция приема фреймов в Атмеловском примере.

Приемник не справляется и молча теряет пакеты.

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


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

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

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

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

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

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

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

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

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

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