![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_pattern.png)
![](https://electronix.ru/forum/uploads/set_resources_23/84c1e40ea0e759e3f1505eb1788ddf3c_default_photo.png)
jcxz
Свой-
Постов
13 478 -
Зарегистрирован
-
Посещение
-
Победитель дней
34
Весь контент jcxz
-
Зачем? У меня эти 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 этого протокола. Как видно - ресурсов шины он требует немного.
-
Так вы же вроде свой протокол ваяете? Почему тогда для передачи мультикадров выделили только один адрес (CAN-ID)? Почему не выделить например - 16 последовательных адресов? Когда-то также пилил свой протокол поверх CAN. С передачей мультикадров. Просто выделил для него 16 последовательных адресов (CAN-ID). И передавал мультикадр так: вырезАл очередные <=8*15 байт данных (из передаваемого массива данных); пристыковывал к нему заголовок мультикадра (с необходимой инфой: индексом мультикадра в потоке, количеством кадров в мультикадре, CRC и т.п.). Затем нарезал тело мультикадра по 8 байт и передавал начиная от хвоста с нарастающим адресом: В таком случае FIFO не нужно - каждый кадр попадает в свой MO. И для отправки не нужна возможность в МК задавать порядок отправки: можно по порядку CAN-ID передавать - заголовочный CAN-ID всегда придёт последним. И прерывание нужно только одно - для заголовочного (последнего кадра); кадры тела принимаются/передаются без прерываний. Так сделал на всякий случай - хотя у меня был XMC4700 с аппаратными FIFO и множеством MO, но на всякий случай, если нужно будет подключать к шине МК с CAN-контроллером послабее.
-
Судя по сообщениям ТС, он изобретает свой велосипед. И ему все эти канопены с их проблемами - не указ. Вот уж точно - такое есть не в каждом МК. Тем более. Не то что FIFO..... А ещё можно - часть ID под данные кадра. И тем - повысить плотность потока. Хотя степени двойки конечно уже не будет....
-
Почему не помогает? Если в МК имеется 2+ шт. MO для приёма, то этого достаточно для двойной буферизации. И если не пропускать прерывания, то порядок приёма не будет нарушен.
-
Тогда: не пропуская прерываний. Или вместо прерываний - DMA. Ну или действительно - выделить часть CAN-ID под индекс кадра внутри мульти-кадра.
-
Зависит от конкретного МК и от протокола. Могу сказать как в XMC4xxx. Надо? В XMC4xxx достаточно для каждого mailbox-а указать маску адреса - какие CAN-ID в него принимать. А если все кадры - с одинаковыми CAN-ID, то можно например соединить mailbox-ы в цепочку FIFO. Которое будет заполняться по порядку. Ну и другие способы можно придумать.... например - при помощи DMA и FIFO уже в общей памяти. Хотя для XMC4700, с его 256 майлбоксами, это не нужно. Это уж не говоря о том, что можно просто тупо реагировать на каждое прерывание о приёме каждого нового кадра. И делать всё программно. А как в жизни - расскажете? У вас биты по CAN гуляют сами по себе, куда вздумается? Кроме пустых общих фраз, есть что по делу сказать?
-
В смысле? А почему они должны приняться не в том порядке, в котором следуют по шине? Никаких роутеров, с ретрансляцией очевидно у ТС-а на шине нет.
-
Можно выделять можно и не выделять. Так как при отправке хвостовой (или головной) кадр пакета кадров можно отправить последним. Сам делал такой протокол. Без дополнительных счётчиков.
-
А кто мешает? Не очень понятно - что мешает отправить в нужном порядке? Приёмная сторона примет их точно в том порядке, в котором они будут передаваться по шине. Ибо - другое невозможно по определению.
-
Ну тогда - для XMC4xxx: раздел "Transmit Acceptance Filtering". Но вкратце - нет никакой обязательной связи CAN-ID с порядком выставления на арбитраж. Порядок задаётся другими инструментами.
-
Из исходного поста следует, что именно отправили: а не просто "положили в ящик". Почему я и попросил уточнения. Насчёт порядка отправки готовых для отправки MO, то в XMC4xxx вроде как порядок такой отправки (выхода MO на фазу TX-арбитража) вообще не зависит от CAN-ID кадра. А зависит только от положения MO в списке MO для данной ноды и поля приоритета, прописанного в свойствах MO. Нет такой гарантии. Или о чём вы тут говорите? Сам CAN описывает только фазу арбитража. А выставлять или нет на него кадр - решает CAN-контроллер МК. Решает в общем случае - никак не согласуясь с CAN-ID. Более того: CAN XMC4xxx позволяет программисту определять: участвовать ли готовому к отправке кадру в повторном TX-арбитраже, если он проиграл предыдущий арбитраж или нет? Программист может указать как действовать для каждого конкретного кадра.
-
Если вы их уже отправили, то как они могут поменять порядок будучи уже отправленными? Странный вопрос.... Может вы всё-таки неверно сформулировали вопрос и он касается очередности выставления для участия в арбитраже для отправки на шину кадров из мэйл-боксов готовых к передаче? А не уже отправленных кадров. Порядок отправки зависит от вашего контроллера - он может отправлять как угодно, совершенно никак не связывая это с CAN-ID. Почитайте мануал на него. Для XMC4xxx например можно задать порядок отправки. И там есть несколько возможных режимов отправки. Постановка на арбитраж (для отправки) никак не связана с CAN-ID.
-
Наверное всё-же - не в любых. 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 *. Ну или добавить ещё приведение типа.
-
При том, что неявное преобразование типа byte * -> char * компилятор автора видимо не умеет. Поэтому не может использовать имеющееся: void LongToBytes (long LG, char * BYTES, byte Index) без явного приведения типа. Имхо.
-
Может здесь у автора также - есть халявный доступ к неограниченному количеству ионисторов? Как у автора недавней темы про "электровелосипед на ионисторах". И очень хочется их куда-нить пристроить. Не важно куда. Его ещё купить нужно. А ионисторы оне вот - в столе лежат... целой кучей... и "на халяву".
-
Линия автоматического монтажа
jcxz ответил inmatened тема в Пайка и монтаж
Видимо - эффективные манагеры сократили всех дармоедов программеров и больше некому за "крайние 25-ть лет" переработать изделие на новую элементную базу. -
Прошу помощи в разработке энкодера колеса мыши
jcxz ответил Darmok тема в Схемотехника
Имхо - рациональнее будет не мышь свою деревянную пилить, а сделать адаптер: USB-мышь -> КР580ВМ80. На любом МК с USB-хостом. Тогда можно будет (почти) любую современную USB-мышь использовать. Подходящую по руке например. Да и проще в изготовлении. -
Функцию объявленную как: 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) А прототипов, соответствующих первому и второму вариантам, в коде видимо нет. Отсюда и предупреждение.
-
Глупее совета для производителя устройств трудно придумать. И во вторых: если просто сгенерить MAC от фонаря, генератором случайных чисел, то вероятность встречи устройства ТС с клоном будет гораздо ниже, чем если клонировать соседей. Многократно ниже. Это вроде как должно быть очевидно. И кратно меньше геморроя. Потому что - почитайте про структуру MAC. Из чего он состоит и как строится. Пруфы? Где такое вычитали? ссылка?
-
Не может быть такого. Так как это противоречит структуре MAC. Почитайте как он строится и из чего состоит. PS: Сколько, однако, мифов и легенд ходит о MAC... Просто не читай документацию, и весь мир программирования будет полон для тебя чудес и магии!
-
"Базовые" - это какие? Насколько помню - 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КБ. Подумайте - что будет если следовать вашему правилу? В этом случае компоновка по уменьшению размера секций более безопасна.
-
"Как повезёт" относилось к вашей фразе: Вот именно поэтому. Если секции описаны не как оверлейные, то все переменные размещаемые внутри региона SECTOR_1_2 будут иметь разные стартовые адреса. И только одна из этих переменных будет иметь стартовый адрес == 0x08004000. Какая именно - как повезёт. Поэтому и: "будет ли иметь массив __PLC_params адрес == 0x08004000" - как повезёт. PS: Это конечно не относится к оверлейным секциям. В оверлейных все переменные будут иметь одинаковые стартовые адреса.
-
Почему "фантазировать"? писал-же - "на основе собственного опыта". Только не как пользователя такого девайса, а когда мы в процессе разработки устанавливали левые MAC и IP на свои устройства и втыкали их в корпоративную сеть. Не согласовав с отделом АСУ. Потом АСУшники из нашей же конторы, нам это долго припоминали. Лучше найти в списке организаций OUI дохлую (про которую никогда не слышали) и нагенерить глобальных MAC с её OUI.
-
Не факт. Только если нигде в программе больше нет секций ".plc_params". Иначе - как повезёт.
-
Параноик тут не нужен. Достаточно одного ленивого сисадмина. Вот предположим - в организации возникает проблема: У одного из сотрудников иногда начинает глючить девайс: проблемы со связью. Не важно - из-за кривого MAC или одной из 100500 других причин. Что он делает? Правильно - идёт к сисадмину. Сисадмин как правило - скотина ленивая. Предпочитает тратить минимум усилий. Чтобы не увеличивать энтропию во Вселенной Сисадмин смотрит в сеть и на проблемный девайс, видит что у него local-MAC и первый же вопрос к пришедшему сотруднику: "Какого х* вы воткнули в сеть девайс, у которого local-MAC, не пришедши предварительно ко мне, не получив от меня выделенный MAC (который я внесу в нашу базу данных) и не установив этот MAC в свой девайс?" Сотрудник говорит: "Так невозможно там его поменять, гвоздями прибит". После чего сисадмин ему скажет, что проблема именно из-за этого кривого MAC. И даже не станет отрывать жопу от стула и искать истинную проблему в своей сети. Зачем? И ещё и докладную накатает на такого сотрудника. И повесит на него всех собак за все проблемы в сети, которые были у него за последнее время - скажет всё из-за этого негодяя. Так бывает реально. Сам сталкивался с таким.