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

jcxz

Свой
  • Постов

    13 478
  • Зарегистрирован

  • Посещение

  • Победитель дней

    34

Весь контент jcxz


  1. Зачем? У меня эти 16 адресов использовались всеми участниками CAN-сети. Типа - как параллельная шина. Самый старший адрес (базовый_CAN_ID + 15) - для передачи кадров управления (заголовки мультикадров и различные команды управления этой "шиной"). Точнее - старший адрес у каждого устройства был свой, а вот остальные 15 адресов - общие (для передачи тела данных мультикадров). Хотя наверное всё-таки = было 16 адресов для тела данных, а адреса управления - отдельно, у каждого устройства свой. У меня в сети были мастер и много слэйвов. Инициатива обмена мультикадром (на ввод или вывод) - всегда по инициативе мастера. Поэтому все слэйвы по дефолту держат свои 16 MO тела данных в режиме приёма; мастер - в режиме передачи. В прерывании выигрыша арбитража (вроде так) адреса управления мастер переключает свои 16 MO данных на приём (так как в этот момент все MO данных гарантированно уехали в шину); потом передаётся собственно кадр из MO управления. Один из слэйвов (который получил в свой адрес управления) финальный управляющий кадр; перед ответом переключает 16 MO данных на передачу; передаёт ответный мультикадр (или короткий ACK через адрес управления; если тело данных не нужно) и также в прерывании выигрыша арбитража на передачу заголовка переключает свои 16 MO данных на приём. Так нет коллизий (нет двух наборов MO данных одновременно настроенных на передачу в разных устройствах). Вобщем - такая себе полудуплексная квази-параллельная шина из 16 MO данных и одного MO управления. С одним прерыванием на передачу мультикадра и одним - на приём. Всего у нас устройств в шине планировалось - до 33 шт. Значит для всего интерфейса нужно: 16+33 шт. адресов. Вроде как не особо много. Требования по ресурсу CPU - очень низкие получились, практически незаметные на общей загрузке CPU Cortex-M4 144MHz. Только надо добавить небольшие защитные паузы перед переключением MO данных на передачу. Чтобы другая сторона гарантированно успела переключить свои на приём. Чтобы не мешали задержки входа в ISR на разных участниках обмена. ЗЫ: Глянул в исходники: всё-таки наврал - ширина шины у меня == 8 MO. Но задаётся дефайном, так что можно поменять в любой момент. #define CAN_NSLAVES 32 //макс.кол-во слэйвов #define CAN_UG_D_WIDTH 8 //кол-во MO (и адресов) используемых для отправки тела UG-кадра //Распределение адресов (11-битных) на внутренней CAN-шине. Адрес == смещению от начала ICanAddrSpace. struct ICanAddrSpace { char unuse0[16]; char obReset; //адрес сброс-сообщения (протокол обзора + UG) char unuse1[15]; char torque; //адрес рассылки задания крутящего момента char unuse2[32]; char obData; //протокол обзора. данные char obCmd; //протокол обзора. команды char obGarbage; //протокол обзора. сбор мусора char obScan[4]; //протокол обзора. сканирование серийных номеров char obInfo; //протокол обзора. информация о совместимости прошивок char unuse3[7]; char ugData[CAN_UG_D_WIDTH]; //адреса тела UG-кадра struct { char master; //адрес UG-master char slave[CAN_NSLAVES]; //адрес UG-slave } ugCtl; }; //Распределение CAN.MO. Номер MO == смещению от начала CanMoSpace. //Чем больше смещение - тем ниже приоритет при отправке на передачу. struct CanMoSpace { struct T_ug { //MO UG-протокола. Использование мастером и слэйвом: char data[CAN_UG_D_WIDTH]; //все: приём/передача тела UG-кадра char ctlRx; //все: приём заголовков char ctlTx; //все: отправка заголовков; мастер: отправка сброс-сообщений struct Observe { //MO протокола обзора. Использование MO мастером и слэйвом: char data; //мастер: отправка тела команды (свой UID); слэйв: приём тела команды (UID мастера) char cmd; //мастер: отправка заголовка команды; слэйв: приём заголовка команды char scanRx; //мастер: приём ответов от слэйва на проверку живости UID (в OBF_DELAY3); слэйв: приём RTR-запросов сканирования char scanTx; //слэйв: отправка ответов на RTR-запросы сканирования char misc; //мастер: приём информационных кадров (в OBF_SCAN0); слэйв: отправка ответов на проверки живости UID } observe; char reset; //все: приём сброс-сообщения } ug; struct T_ecan { char tele[CfgTele::STREAM_N]; //телеметрия char remote[CfgRemote::ITEM_n]; //дистанционное управление } ecan; }; ICanAddrSpace::ugCtl - как раз адреса интерфейса передачи мультикадров. CanMoSpace::data, CanMoSpace::ctlRx, CanMoSpace::ctlTx - MO этого протокола. Как видно - ресурсов шины он требует немного.
  2. Так вы же вроде свой протокол ваяете? Почему тогда для передачи мультикадров выделили только один адрес (CAN-ID)? Почему не выделить например - 16 последовательных адресов? Когда-то также пилил свой протокол поверх CAN. С передачей мультикадров. Просто выделил для него 16 последовательных адресов (CAN-ID). И передавал мультикадр так: вырезАл очередные <=8*15 байт данных (из передаваемого массива данных); пристыковывал к нему заголовок мультикадра (с необходимой инфой: индексом мультикадра в потоке, количеством кадров в мультикадре, CRC и т.п.). Затем нарезал тело мультикадра по 8 байт и передавал начиная от хвоста с нарастающим адресом: В таком случае FIFO не нужно - каждый кадр попадает в свой MO. И для отправки не нужна возможность в МК задавать порядок отправки: можно по порядку CAN-ID передавать - заголовочный CAN-ID всегда придёт последним. И прерывание нужно только одно - для заголовочного (последнего кадра); кадры тела принимаются/передаются без прерываний. Так сделал на всякий случай - хотя у меня был XMC4700 с аппаратными FIFO и множеством MO, но на всякий случай, если нужно будет подключать к шине МК с CAN-контроллером послабее.
  3. Судя по сообщениям ТС, он изобретает свой велосипед. И ему все эти канопены с их проблемами - не указ. Вот уж точно - такое есть не в каждом МК. Тем более. Не то что FIFO..... А ещё можно - часть ID под данные кадра. И тем - повысить плотность потока. Хотя степени двойки конечно уже не будет....
  4. Почему не помогает? Если в МК имеется 2+ шт. MO для приёма, то этого достаточно для двойной буферизации. И если не пропускать прерывания, то порядок приёма не будет нарушен.
  5. Тогда: не пропуская прерываний. Или вместо прерываний - DMA. Ну или действительно - выделить часть CAN-ID под индекс кадра внутри мульти-кадра.
  6. Зависит от конкретного МК и от протокола. Могу сказать как в XMC4xxx. Надо? В XMC4xxx достаточно для каждого mailbox-а указать маску адреса - какие CAN-ID в него принимать. А если все кадры - с одинаковыми CAN-ID, то можно например соединить mailbox-ы в цепочку FIFO. Которое будет заполняться по порядку. Ну и другие способы можно придумать.... например - при помощи DMA и FIFO уже в общей памяти. Хотя для XMC4700, с его 256 майлбоксами, это не нужно. Это уж не говоря о том, что можно просто тупо реагировать на каждое прерывание о приёме каждого нового кадра. И делать всё программно. А как в жизни - расскажете? У вас биты по CAN гуляют сами по себе, куда вздумается? Кроме пустых общих фраз, есть что по делу сказать?
  7. В смысле? А почему они должны приняться не в том порядке, в котором следуют по шине? Никаких роутеров, с ретрансляцией очевидно у ТС-а на шине нет.
  8. Можно выделять можно и не выделять. Так как при отправке хвостовой (или головной) кадр пакета кадров можно отправить последним. Сам делал такой протокол. Без дополнительных счётчиков.
  9. А кто мешает? Не очень понятно - что мешает отправить в нужном порядке? Приёмная сторона примет их точно в том порядке, в котором они будут передаваться по шине. Ибо - другое невозможно по определению.
  10. Ну тогда - для XMC4xxx: раздел "Transmit Acceptance Filtering". Но вкратце - нет никакой обязательной связи CAN-ID с порядком выставления на арбитраж. Порядок задаётся другими инструментами.
  11. Из исходного поста следует, что именно отправили: а не просто "положили в ящик". Почему я и попросил уточнения. Насчёт порядка отправки готовых для отправки MO, то в XMC4xxx вроде как порядок такой отправки (выхода MO на фазу TX-арбитража) вообще не зависит от CAN-ID кадра. А зависит только от положения MO в списке MO для данной ноды и поля приоритета, прописанного в свойствах MO. Нет такой гарантии. Или о чём вы тут говорите? Сам CAN описывает только фазу арбитража. А выставлять или нет на него кадр - решает CAN-контроллер МК. Решает в общем случае - никак не согласуясь с CAN-ID. Более того: CAN XMC4xxx позволяет программисту определять: участвовать ли готовому к отправке кадру в повторном TX-арбитраже, если он проиграл предыдущий арбитраж или нет? Программист может указать как действовать для каждого конкретного кадра.
  12. Если вы их уже отправили, то как они могут поменять порядок будучи уже отправленными? Странный вопрос.... Может вы всё-таки неверно сформулировали вопрос и он касается очередности выставления для участия в арбитраже для отправки на шину кадров из мэйл-боксов готовых к передаче? А не уже отправленных кадров. Порядок отправки зависит от вашего контроллера - он может отправлять как угодно, совершенно никак не связывая это с CAN-ID. Почитайте мануал на него. Для XMC4xxx например можно задать порядок отправки. И там есть несколько возможных режимов отправки. Постановка на арбитраж (для отправки) никак не связана с CAN-ID.
  13. Наверное всё-же - не в любых. IAR 7.80.4, си-файл: typedef unsigned char byte; byte PID_CODE[4]; void LongToBytes(long LG, char* BYTES, byte Index); void mm1(void); void LongToBytes(long LG, char* BYTES, byte Index) { byte i; for (i=0;i<4;i++) { BYTES[Index+i] = (*((unsigned char *)&(LG)+i)); } } void mm1(void) { LongToBytes(0x4445, PID_CODE, 0); LongToBytes(0x4445, (char *)&PID_CODE[0], 0); } результат: Warning[Pe167]: argument of type "byte *" is incompatible with parameter of type "char *" B:\TST\11.c 27 варнинг Pe167 на первую строку mm1(). Возможно вы правы. Не буду гадать - что там у автора, так как половину необходимой для понимания инфы он скрыл. Я просто говорил, что объявление функции нужно не такое, какое вы приводили. А с типом указателя byte *. Ну или добавить ещё приведение типа.
  14. При том, что неявное преобразование типа byte * -> char * компилятор автора видимо не умеет. Поэтому не может использовать имеющееся: void LongToBytes (long LG, char * BYTES, byte Index) без явного приведения типа. Имхо.
  15. Может здесь у автора также - есть халявный доступ к неограниченному количеству ионисторов? Как у автора недавней темы про "электровелосипед на ионисторах". И очень хочется их куда-нить пристроить. Не важно куда. Его ещё купить нужно. А ионисторы оне вот - в столе лежат... целой кучей... и "на халяву".
  16. Видимо - эффективные манагеры сократили всех дармоедов программеров и больше некому за "крайние 25-ть лет" переработать изделие на новую элементную базу.
  17. Имхо - рациональнее будет не мышь свою деревянную пилить, а сделать адаптер: USB-мышь -> КР580ВМ80. На любом МК с USB-хостом. Тогда можно будет (почти) любую современную USB-мышь использовать. Подходящую по руке например. Да и проще в изготовлении.
  18. Функцию объявленную как: void LongToBytes (long LG, char * BYTES, byte Index) Вызываете как: void LongToBytes (long LG, byte * BYTES, byte Index) И видимо определение типа byte у вас не эквивалентно типу char. Перепишите вызов так: LongToBytes (ADDRESS, (char *)&PID_CODE[0], 0); и тогда (возможно!) всё будет ок. ЗЫ: Зачем так громоздко копировать? У вас же Cortex-M3. Он умеет невыровненный доступ. А значит можно например так: Ну или как-то более компактно описать пакованный тип (если Keil позволяет). Будет всего одна команда записи в память, вместо функции и цикла. Автор вызывает как: void LongToBytes (long LG, byte * BYTES, byte Index) Что вроде как эквивалентно: void LongToBytes (long LG, uint8_t * BYTES, byte Index) И не эквивалентно: void LongToBytes (long LG, char * BYTES, byte Index) А прототипов, соответствующих первому и второму вариантам, в коде видимо нет. Отсюда и предупреждение.
  19. Глупее совета для производителя устройств трудно придумать. И во вторых: если просто сгенерить MAC от фонаря, генератором случайных чисел, то вероятность встречи устройства ТС с клоном будет гораздо ниже, чем если клонировать соседей. Многократно ниже. Это вроде как должно быть очевидно. И кратно меньше геморроя. Потому что - почитайте про структуру MAC. Из чего он состоит и как строится. Пруфы? Где такое вычитали? ссылка?
  20. Не может быть такого. Так как это противоречит структуре MAC. Почитайте как он строится и из чего состоит. PS: Сколько, однако, мифов и легенд ходит о MAC... Просто не читай документацию, и весь мир программирования будет полон для тебя чудес и магии!
  21. "Базовые" - это какие? Насколько помню - CCS ("Code Composer Studio" от TI) как раз прибегает. Фрагмент "Linker command file" для ARM- и DSP-ядер OMAP L-137, описывающий регистры периферии: MEMORY { ... PAGE 2: //!<peripheral memory MMR_INTCD (RWI): o = 0x01800000 l = 0x0200 MMR_PDC (RWI): o = 0x01810000 l = 0x0200 MMR_IDMA (RWI): o = 0x01820000 l = 0x0200 MMR_CACHE (RWI): o = 0x01840000 l = 0x8400 //!<only DSP-accessable MMR_EDMA3CC (RWI): o = 0x01C00000 l = 0x5000 MMR_EDMA3TC (RWI): o = 0x01C08000 l = 0x0800 MMR_PSC0 (RWI): o = 0x01C10000 l = 0x1000 MMR_PLL (RWI): o = 0x01C11000 l = 0x0200 MMR_SYSCFG (RWI): o = 0x01C14000 l = 0x0200 MMR_TMR (RWI): o = 0x01C20000 l = 0x2000 MMR_I2C0 (RWI): o = 0x01C22000 l = 0x1000 MMR_RTC (RWI): o = 0x01C23000 l = 0x1000 MMR_PRU (RWI): o = 0x01C37000 l = 0x1000 MMR_SPI0 (RWI): o = 0x01C41000 l = 0x1000 MMR_UART0 (RWI): o = 0x01C42000 l = 0x1000 MMR_MCASP (RWI): o = 0x01D00000 l = 0xC000 MMR_UART1 (RWI): o = 0x01D0C000 l = 0x1000 MMR_UART2 (RWI): o = 0x01D0D000 l = 0x1000 MMR_USB0 (RWI): o = 0x01E00000 l = 0x7000 MMR_SPI1 (RWI): o = 0x01E12000 l = 0x1000 MMR_MPU1 (RWI): o = 0x01E14000 l = 0x1000 MMR_MPU2 (RWI): o = 0x01E15000 l = 0x1000 MMR_GPIO (RWI): o = 0x01E26000 l = 0x1000 MMR_PSC1 (RWI): o = 0x01E27000 l = 0x1000 MMR_I2C1 (RWI): o = 0x01E28000 l = 0x1000 MMR_EMIFB (RWI): o = 0xB0000000 l = 0x8000 MMR_INTCA (RWI): o = 0xFFFEE000 l = 0x2000 } //!Maps the shared memory and peripherals memory to the memory areas. SECTIONS { ... .mmrSyscfgRegs > MMR_SYSCFG, PAGE 2 .mmrPsc0Regs > MMR_PSC0, PAGE 2 .mmrPsc1Regs > MMR_PSC1, PAGE 2 .mmrPllcRegs > MMR_PLL, PAGE 2 .mmrPrussRegs > MMR_PRU, PAGE 2 .mmrDintcRegs > MMR_INTCD, PAGE 2 .mmrAintcRegs > MMR_INTCA, PAGE 2 .mmrIdmaRegs > MMR_IDMA, PAGE 2 .mmrEdma3ccRegs > MMR_EDMA3CC, PAGE 2 .mmrEdma3tcRegs > MMR_EDMA3TC, PAGE 2 .mmrGpioRegs > MMR_GPIO, PAGE 2 .mmrTmrRegs > MMR_TMR, PAGE 2 .mmrRtcRegs > MMR_RTC, PAGE 2 .mmrMcaspRegs > MMR_MCASP, PAGE 2 .mmrSpi0Regs > MMR_SPI0, PAGE 2 .mmrSpi1Regs > MMR_SPI1, PAGE 2 .mmrI2c0Regs > MMR_I2C0, PAGE 2 .mmrI2c1Regs > MMR_I2C1, PAGE 2 .mmrUart0Regs > MMR_UART0, PAGE 2 .mmrUart1Regs > MMR_UART1, PAGE 2 .mmrUart2Regs > MMR_UART2, PAGE 2 .mmrUsb0Regs > MMR_USB0, PAGE 2 .mmrMpu1Regs > MMR_MPU1, PAGE 2 .mmrMpu2Regs > MMR_MPU2, PAGE 2 .mmrEmifbRegs > MMR_EMIFB, PAGE 2 .mmrCacheRegs > MMR_CACHE, PAGE 2 //!<only DSP-accessable .mmrPdcRegs > MMR_PDC, PAGE 2 } Как видно - привязка каждого блока периферии к его базовому абсолютному адресу производится именно в командном файле компоновщика. Распределение регистров внутри каждого из этих блоков - описывается си-структурой в .h-файле. PS: Я бы не стал говорить за все инструменты в мире, основываясь на опыте только с одним.... Как решит компоновщик в соответствии с действующими у него в данный момент правилами. Это не так. К тому же - плохой способ. Чаще всего компоновщики компонуют секции в порядке уменьшения их размера. Потому так - меньше вероятность проблем. Сами подумайте почему. Например: Если компоновка идёт в два региона памяти размерами: 64КБ + 32КБ, и в программе есть множество переменных (общим размером ==20КБ), кроме которых также имеется массив размером ==50КБ. Подумайте - что будет если следовать вашему правилу? В этом случае компоновка по уменьшению размера секций более безопасна.
  22. "Как повезёт" относилось к вашей фразе: Вот именно поэтому. Если секции описаны не как оверлейные, то все переменные размещаемые внутри региона SECTOR_1_2 будут иметь разные стартовые адреса. И только одна из этих переменных будет иметь стартовый адрес == 0x08004000. Какая именно - как повезёт. Поэтому и: "будет ли иметь массив __PLC_params адрес == 0x08004000" - как повезёт. PS: Это конечно не относится к оверлейным секциям. В оверлейных все переменные будут иметь одинаковые стартовые адреса.
  23. Почему "фантазировать"? писал-же - "на основе собственного опыта". Только не как пользователя такого девайса, а когда мы в процессе разработки устанавливали левые MAC и IP на свои устройства и втыкали их в корпоративную сеть. Не согласовав с отделом АСУ. Потом АСУшники из нашей же конторы, нам это долго припоминали. Лучше найти в списке организаций OUI дохлую (про которую никогда не слышали) и нагенерить глобальных MAC с её OUI.
  24. Не факт. Только если нигде в программе больше нет секций ".plc_params". Иначе - как повезёт.
  25. Параноик тут не нужен. Достаточно одного ленивого сисадмина. Вот предположим - в организации возникает проблема: У одного из сотрудников иногда начинает глючить девайс: проблемы со связью. Не важно - из-за кривого MAC или одной из 100500 других причин. Что он делает? Правильно - идёт к сисадмину. Сисадмин как правило - скотина ленивая. Предпочитает тратить минимум усилий. Чтобы не увеличивать энтропию во Вселенной Сисадмин смотрит в сеть и на проблемный девайс, видит что у него local-MAC и первый же вопрос к пришедшему сотруднику: "Какого х* вы воткнули в сеть девайс, у которого local-MAC, не пришедши предварительно ко мне, не получив от меня выделенный MAC (который я внесу в нашу базу данных) и не установив этот MAC в свой девайс?" Сотрудник говорит: "Так невозможно там его поменять, гвоздями прибит". После чего сисадмин ему скажет, что проблема именно из-за этого кривого MAC. И даже не станет отрывать жопу от стула и искать истинную проблему в своей сети. Зачем? И ещё и докладную накатает на такого сотрудника. И повесит на него всех собак за все проблемы в сети, которые были у него за последнее время - скажет всё из-за этого негодяя. Так бывает реально. Сам сталкивался с таким.
×
×
  • Создать...