yanvasilij
-
Постов
321 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные yanvasilij
-
-
Кроме всего прочего, имейте в виду, что нормальный сигнал в кабеле появляется только после процедуры Autonegatiation. До этого Вы будете видеть только link-импульсы, короткие и редкие. После того, как две физики договариваются, начинается нормальный обмен. Протокол описан в стандарте.
Спасибо! Именно то, что мне нужно. На осциллографе, получается, мы видели только link-импульсы, короткие и редкие. Следовательно что-то неладное на стороне микросхемы PHY. Начали проверять - выяснилось непропай на ноге генератора тактовой частоты. Пропаяли - все заработало.
-
что-то не понимаю, в чём вопрос.
Создать цель сборки, состоящую из двух зависимостей - исполняемого файла и либы.
Вызывать эту цель сборки, соберётся и то, и то.
Ну вот как указать, чтобы либа собиралась arm-none-eabi-gcc-ar?
-
Доброго времени суток!
Ситуация такая. Компилирую проект через make полученный cmake. Когда мне нужен просто исполняемый файл(alf, hex и т.п.) или просто статическая библиотека проблем нет, но мне нужно получать одновременно и статическую библиотеку и hex. Как выяснилось линковка статических либ осуществляется arm-none-eabi-gcc-ar, а линковка исполняемого файла arm-none-eabi-gcc. Как же сделать так, чтобы на выходе получать и то и то?
-
А менять трансформатор пробовали? Может, в нем КЗ или обрыв?
Пробовали, не помогло.
-
А эти две разные микросхемы PHY точно расчитаны на работу с одинаковыми трансформаторами? Не зря же выпускается великое множество трансформаторов с различными схемами соединения обмоток и различными коэффициентами трансформации.
Микросхемы KSZ8721 и KSZ8863. Обе могут работать с этим трасформатором, но у нас работает только KSZ8863, а вот KSZ8721 почему то не хочет. Скажите можно ли проверять работу трасформатора осциллографа так, как это делаем мы? Если нужно могу полностью подключение выложить, но надо ли?
-
Вопрос вероятно идиотский, но ответа самостоятельно я так и не нашел. Есть две схемы с одинаковыми трансформаторами, но с разными микросхемами PHY. Первая схема работает отлично, моргают светодиоды link, есть пинги и т.п. На второй схеме нет ни линка ни пинга. Начали тыкать осциллографом и дошли в итоге до следующего: после траснформатора на ногах TPTX и TPRX на работающей схеме наблюдаем активную цифровую движуху (при подключенном сетевом кабеле разумеется); а на второй схеме после того же трасформатора нет никакого движения. Чтобы проверить, где проблема в физике или в трасформаторе решили поднять микросхему физики и посмотреть на особняком стоящем трансформаторе сигналы при подключенном сетевом кабеле. Так вот сигналы так и не появились (на неработающей схеме). Корректна ли такая проверка? Схему подключения трансформатора привожу ниже.
-
Да, там обычно много чего ходит broadcast'ом.
Просто именованы на схеме странно: получились группы "RXDx и TX_EN" и "TXDx CRS_DV".
Вообщем еще раз перепроверил - действительно пины перепутаны! Перепаял и все заработало - пинги есть, как свитч все прекрасно работает. Спасибо Вам огромное!
-
Вообщем есть у меня проект под eval c KSZ8721 со стеком RL TCPnet. На eval все пингуется и работает. Начал переносить все тоже самое на KSZ8863, разница там только в микросхеме физики и схеме ее подключения (используются другие "ремапные" ноги). Переделал инициализацию EMAK по аналогии с тем, что было для KSZ8721, вот что получилось (тут с подсветкой):
void init_ethernet (void) { /* Включаю тактирование на порты в.в. */ ... /* Initialize the ETH ethernet controller. */ U32 regv,tout,id1,id2,conn; /* Enable System configuration controller clock */ RCC->APB2ENR |= (1 << 14); /* Reset Ethernet MAC */ RCC->AHB1RSTR |= 0x02000000; SYSCFG->PMC |= (1 << 23); RCC->AHB1RSTR &= ~0x02000000; RCC->AHB1ENR |= 0x1E000047; /* Configure Port A ethernet pins (PA.1, PA.2, PA.7) */ GPIOA->MODER &= ~0x0000C03C; GPIOA->MODER |= 0x00008028; /* Pins to alternate function */ GPIOA->OTYPER &= ~0x00000086; /* Pins in push-pull mode */ GPIOA->OSPEEDR |= 0x0000C03C; /* Slew rate as 100MHz pin */ GPIOA->PUPDR &= ~0x0000C03C; /* No pull up, no pull down */ GPIOA->AFR[0] &= ~0xF0000FF0; GPIOA->AFR[0] |= 0xB0000BB0; /* Pins to AF11 (Ethernet) */ /* Configure Port C ethernet pins (PC.1, PC.4, PC.5) */ GPIOC->MODER &= ~0x00000F0C; GPIOC->MODER |= 0x00000A08; /* Pins to alternate function */ GPIOC->OTYPER &= ~0x00000032; /* Pins in push-pull mode */ GPIOC->OSPEEDR |= 0x00000F0C; /* Slew rate as 100MHz pin */ GPIOC->PUPDR &= ~0x00000F0C; /* No pull up, no pull down */ GPIOC->AFR[0] &= ~0x00FF00F0; GPIOC->AFR[0] |= 0x00BB00B0; /* Pins to AF11 (Ethernet) */ /* Configure Port B ethernet pins (PB.12, PB.13) */ GPIOB->MODER &= ~0x0F000000; GPIOB->MODER |= 0x0A000000; /* Pin to alternate function */ GPIOB->OTYPER &= ~0x00003000; /* Pin in push-pull mode */ GPIOB->OSPEEDR |= 0x0F000000; /* Slew rate as 100MHz pin */ GPIOB->PUPDR &= ~0x0F000000; /* No pull up, no pull down */ GPIOB->AFR[1] &= ~0x00FF0000; GPIOB->AFR[1] |= 0x00BB0000; /* Pin to AF11 (Ethernet) */ /* Configure Port B ethernet pins (PB.11) */ GPIOB->MODER &= ~0x00C00000; GPIOB->MODER |= 0x00800000; /* Pins to alternate function */ GPIOB->OTYPER &= ~0x00000800; /* Pins in push-pull mode */ GPIOB->OSPEEDR |= 0x00C00000; /* Slew rate as 100MHz pin */ GPIOB->PUPDR &= ~0x0FF00000; /* No pull up, no pull down */ GPIOB->AFR[1] &= ~0x0000F000; GPIOB->AFR[1] |= 0x0000B000; /* Pins to AF11 (Ethernet) */ ETH->DMABMR |= DBMR_SR; while (ETH->DMABMR & DBMR_SR); conn = 0; /* HCLK Clock range 100-120MHz. */ ETH->MACMIIAR = 0x00000004; /* Put the LAN8700 in reset mode */ write_PHY (PHY_REG_BCR, 0x8000); /* Wait for hardware reset to end. */ for (tout = 0; tout < 0x100000; tout++) { regv = read_PHY (PHY_REG_BCR); if (!(regv & 0x8000)) { /* Reset complete */ break; } } /* Check if this is a KSZ8863 PHY. */ id1 = read_PHY (PHY_REG_PID1); id2 = read_PHY (PHY_REG_PID2); if (((id1 << 16) | (id2 & 0xFFF0)) == 0x221430) { /* Use autonegotiation about the link speed. */ write_PHY (PHY_REG_BCR, PHY_AUTO_NEG); /* Wait to complete Auto_Negotiation. */ for (tout = 0; tout < 0x100000; tout++) { regv = read_PHY (PHY_REG_BSR); if (regv & 0x0020) { /* Autonegotiation Complete. */ break; } } } /* Check the link status. */ for (tout = 0; tout < 0x10000; tout++) { regv = read_PHY (PHY_REG_BSR); if (regv & 0x0004) { conn |= PHY_CON_SET_FULLD; /* Link is on. */ break; } } /* Initialize MAC configuration register */ ETH->MACCR = MCR_ROD; /* Configure Full/Half Duplex mode. */ if (regv & 0x0004) { /* Full duplex is enabled. */ conn |= PHY_CON_SET_FULLD; } else { /* Half duplex mode. */ } /* Configure 100MBit/10MBit mode. */ if (regv & 0x0002) { /* 10MBit mode. */ } else { /* 100MBit mode. */ conn |= PHY_CON_SET_100M; } /* Configure Full/Half Duplex mode. */ if (conn & PHY_CON_SET_FULLD) { /* Full duplex is enabled. */ ETH->MACCR |= MCR_DM; } /* Configure 100MBit/10MBit mode. */ if (conn & PHY_CON_SET_100M) { /* 100MBit mode. */ ETH->MACCR |= MCR_FES; } /* MAC address filtering, accept multicast packets. */ ETH->MACFFR = MFFR_HPF | MFFR_PAM; ETH->MACFCR = MFCR_ZQPD; /* Set the Ethernet MAC Address registers */ ETH->MACA0HR = ((U32)own_hw_adr[5] << 8) | (U32)own_hw_adr[4]; ETH->MACA0LR = ((U32)own_hw_adr[3] << 24) | (U32)own_hw_adr[2] << 16 | ((U32)own_hw_adr[1] << 8) | (U32)own_hw_adr[0]; /* Initialize Tx and Rx DMA Descriptors */ rx_descr_init (); tx_descr_init (); /* Flush FIFO, start DMA Tx and Rx */ ETH->DMAOMR = DOMR_FTF | DOMR_ST | DOMR_SR; /* Enable receiver and transmiter */ ETH->MACCR |= MCR_TE | MCR_RE; /* Reset all interrupts */ ETH->DMASR = 0xFFFFFFFF; /* Enable Rx and Tx interrupts. */ ETH->DMAIER = ETH_DMAIER_NISE | ETH_DMAIER_AISE | ETH_DMAIER_RBUIE | ETH_DMAIER_RIE; }
Не могу добиться пингов. Что я упускаю?
-
На вид все нормально (у меня, правда, была другая конфигурация с 25МГц входом). Посмотрите, есть ли импульсы на SMRXDV3 при внешнем пинге.
Да, у Вас CRS_DV и TX_EN на RMII не перепутаны случайно?
Движение на SMRXDV3 есть, даже без пингов (возможно потому, что железка подключена к локальной сети, где много чего ходит?). CRS_DV и TX_EN не перепутаны - проверил только что. А почему вы предположили, что они перепутаны, есть какие-то ньюансы?
-
-
Чтобы проверить связь с микросхемой я запросил Physical Identifier. По даташиту он должен быть 0x0022 страшем и 0x1430 в младшем -> при считывании так и оказалось. Связь по RMII есть я так понимаю.
HAL_ETH_ReadPHYRegister(&heth, 0x02, &high); HAL_ETH_ReadPHYRegister(&heth, 0x03, &low);
Между внешними портами связь есть. Попробовал через этот свитч соедининить комьютер и роутер - все работает.
Тактирование от внешнего кварца 25 МГц.
-
KSZ8863 - это свитч, поэтому вместо "драйвера" максимум нужна затычка, которая на все вопросы будет отвечать "Link up 100Mbit FDX", ибо других вариантов не предполагается.
Нет у KSZ8863 помимо свитча есть еще MII/RMII для подключения к ЕМАК контроллеру. Вот у меня не получается заставить работать как раз эту часть, не могу добиться хотябы пингов. Вот и подумал спросить может уже кто оживлял.
-
Вообщем проверил, как советовала Tanya - оказалась неверный тип термопары (я думал, что это тип K, а оказался тип E). Мне подогнали фирменный калибратор, который умеет эмулировать термопары, на нем все прекрасно работает. Спасибо всем за помощь!
-
Доброго времени суток!
Оживляю плату, у который в качестве физики эзернета заложена KSZ8863. Если у кого есть уже написанный драйвер для этой физики под RMII, поделитесь если не жалко. Буду очень признателен!
-
Если нет разности температуры между Г.С. и Х.С. то ТЭДС должна быть равна 0 (по вашим измерениям -0.182997 мВ)
Чтобы получить истинную температуру надо просто прибавить(вычесть) температуру холодного спая. (тут вроде все правильно)
Похоже ошибка в схемотехнике, не точно измеряется ТЭДС термопары. (т.к. 28,5 - 23,89 = 4,61 это примерно и есть те самые пересчетные в мВ -0.182997 мВ т.е. программа отрабатывает правильно)
Спасибо за подсказку! Действительно я совсем об это не подумал. Начал проверять и выяснил, что напряжение появлялось, как оказалось, из-за того, что сама плата слегка греется, нагревая тем самым Х.С., создавая разницу между Г.С. и Х.С. А когда я калибровал датчик холодного спая, то не поднес эталонный датчик вплотную к разъему. В результате датчик температуры ХС врал на 4-5 градусов. Это точно вносило погрешность в измерения.
Но вот беда: все равно результаты идут неверные. При комнаной температуре показания казались корректными (совпадали с эталоном). Но стоило мне бросить термопару в стакан с кипятком, как стало ясно что показания неверные - 130 градусов на кипящей воде. Чем выше температура тем больше разница между эталоном и моими измерения с термопарой. Например:
- Показания эталонного прибора - 35 C
- Моя программа показала 41,72
- Термоэдс при этом была 0.481197 мВ
- Температура холодного спая 30.04
Проверил градуировочную характеристку, зашитую в контроллер, - точно совпадает с ГОСТом. Что это может быть?
-
Спрошу в продолжении темы. Вообщем реализовал я вышеописанный алгоритм измерения. Вот только недавно у меня в руках оказалась реальная термопара и вот я пытаюсь добиться адекватных показаний от нее. Пока ничего толкового не выходит. Наблюдения следующие:
- Термоэдс измеряется точно, я подавал эталонное напряжение и оно совпадало с тем, что выдавал мой микроконтроллер (проверил несколькими приборами)
- Температура холодного спая тоже определяется точно (проверял датчиком PT100)
- Термопара тип K куплена вот тут
- Сама термопара и плата находятся в одном помещении при одной и той же температуре, но показания получаются следующие:
---- Температура в помещении и соотвественно холодного спая 28.5 С
---- Измеренное термоэдс -0.182997 мВ
---- Вычисленное значение температуры термопары 23.89
Код вычисления температуры и термоэдс (ВОТ ТУТ С ПОДСВЕТКОЙ СИНТАКСИСА):
/** * @brief Градуировочные значения для термопары типа K от -270 до 1370 с шагом 10. * Всего 153 точки */ static const float calibrationTable[] = { -6.458, -6.441, -6.404, -6.344, -6.262, -6.158, -6.035, -5.891, -5.73, -5.55, -5.354, -5.141, -4.913, -4.669, -4.411, -4.138, -3.852, -3.554, -3.243, -2.92, -2.587, -2.243, -1.889, -1.527, -1.156, -0.778, -0.392, 0.0, 0.397, 0.798, 1.203, 1.612, 2.023, 2.436, 2.851, 3.267, 3.682, 4.096, 4.509, 4.92, 5.328, 5.735, 6.138, 6.54, 6.941, 7.34, 7.739, 8.138, 8.539, 8.94, 9.343, 9.747, 10.153, 10.561, 10.971, 11.382, 11.795, 12.209, 12.624, 13.04, 13.457, 13.874, 14.293, 14.713, 15.133, 15.554, 15.975, 16.397, 16.82, 17.243, 17.667, 18.091, 18.516, 18.941, 19.366, 19.792, 20.218, 20.644, 21.071, 21.497, 21.924, 22.35, 22.776, 23.203, 23.629, 24.055, 24.48, 24.905, 25.33, 25.755, 26.179, 26.602, 27.025, 27.447, 27.869, 28.289, 28.71, 29.129, 29.548, 29.965, 30.382, 30.798, 31.213, 31.628, 32.041, 32.453, 32.865, 33.275, 33.685, 34.093, 34.501, 34.908, 35.313, 35.718, 36.121, 36.524, 36.925, 37.326, 37.725, 38.124, 38.522, 38.918, 39.314, 39.708, 40.101, 40.494, 40.885, 41.276, 41.665, 42.053, 42.44, 42.826, 43.211, 43.595, 43.978, 44.359, 44.74, 45.119, 45.497, 45.873, 46.249, 46.623, 46.995, 47.367, 47.737, 48.105, 48.473, 48.838, 49.202, 49.565, 49.926, 50.286, 50.644, 51.0, 51.355, 51.708, 52.06, 52.41, 52.759, 53.106, 53.451, 53.795, 54.138, 54.479, 54.819 }; float TermocoupleKProcessor::calcTemperature (float eds) { int t = MIN_T, i, dt = DT; if (eds > calibrationTable[i = 0]) while (MAX_T >= t) { if (eds < calibrationTable[++i]) return t + (eds - calibrationTable[i-1]) * dt / (calibrationTable[i] - calibrationTable[i-1]); t += dt; }; return t; } float TermocoupleKProcessor::calcEds (float t) { float eds = calibrationTable[CALIBRATION_TABLE_LEN - 1]; float dEds, t0 = MIN_T; int i = 0; if ( t > t0 ) { while ( calibrationTable[CALIBRATION_TABLE_LEN-1] >= eds ) { i++; if ( t < (t0 + DT) ) { dEds = calibrationTable[i] - calibrationTable[i-1]; eds = calibrationTable[i-1] + ((t - t0) * dEds / DT); return eds; } t0 += DT; } eds = calibrationTable[CALIBRATION_TABLE_LEN-1]; } return eds; }
Место, где это используется (C подсветкой синтаксиса):
/* Измеряю температуру холодного спая */ ... //Измерения температуры холодного спая обычным термодатчиком опускаю ... data->coldJuncT = calcColdJuncTemperature(rtd); /* Вычисляю ЭДС холодного спая в МИЛЛИВОЛЬТАХ! */ data->cjEds = calcEds (data->coldJuncT); /* Измеряю ЭДС термопары */ ... //Опускаю измерения термоэдс ... data->tEds = data->tEds * 1000; //перевожу в милливольты! /* Вычисляю значение температры */ data->temperature = calcTemperature(data->tEds + data->cjEds); conversationIsReady = 1; /**< @brief Считывание завершено */
Почему может быть такая большая погрешность? Что я упустил, подскажите пожалуйста?
-
Если Вы используете в своей программе имя массива ...
Так и было сделано, typeSCalibrationTable[]={ .... } и подобные ему массивы объявлены в отдельных *.c файлах, внутри класса TermocoupleSProcessor используются лишь указатель на этот массив.
extern const float *tcoupleScalibrationTable; //Таблица объявлена, где-то в другом месте class TermocoupleProcessorBase : public BarrierSensorProcessorBase { public: ... float const *tCoupleParams; /**< @brief Внутри класса лишь указатель на массив */ ... ... //В некотором месте программы происходит назначение этого указателя tCoupleParams = tcoupleScalibrationTable; ... };
-
как обход этой проблемы, могу предложить решение в лоб - сделать одну точку входа.
При RTOS это делается через очередь
Ну да, похоже придется так и сделать. Не очень красивый способ, как мне кажется, но когда я переделал таким образом потребление памяти уменьшилось в разы. У меня кстати нет ртос в этом проекте, слишком мало памяти у проца и слишком много всего надо впихнуть.
-
const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно.
В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия.
Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте.
Спасибо, теперь буду знать. Но я использую указатель на этот массив, разве это должно приводить к такому значительному увеличению потребления статически выделенной оперативной памяти?
-
по слову ZI-data определяется что это Keil
автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern
Да компилятор keil.
Моя вина - не сказал. Так и было с самого начала, в классе лишь указатель на этот массив.
-
А проц какой? Не AVR ли часом. Для него одного const мало. Надо еще __flash добавлять. Вроде так раньше было.
stm32f042
-
Покажите определение. Скорее всего не хватает ещё одного const.
static const float typeSCalibrationTable[] = { -0.226, -0.188, -0.145, -0.1, -0.051, 0, 0.054, 0.111, 0.171, 0.232, 0.296, 0.363, ... много много значений ... };
-
б-р-р-р, каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно
попробовать typeSCalibrationTable сделать как static const
Нет, в том то и дело, что работа со стеком это динамика, статически выделяемая память при компиляции тут не при чем (точнее она при чем только при указании размера стека). Я не спорю с тем фактом, что увеличением вызовов увеличит потребление стека, это я понимаю. Проблема в том, что у меня увеличивается объем выделенной статической памяти, на этапе компиляции (секция ZI-data), при увеличении точек входа в эту злосчастную функцию в программе.
typeSCalibrationTable уже как static const, я забыл это упомянуть.
-
Доброго времени суток!
Столкнулся с тем, что не хватает памяти на микроконтроллере. Начал копать и выяснил, что больше всего памяти потребляет вызов функции, которая у меня занимается вычислениями по калибровочным таблицам (кусочно-линейная аппроксимация). Поскольку мое устройство должно поддерживать большое количество датчиков, вызов этой функции осуществляется из разных мест программы. Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти. Я долго думал можно ли с этим что либо поделать, но так и не придумал. Ниже привожу примеры использования.\
Собственно сами функции:
float plaStraight (const float *calibrationTable, float delta, float minValue, float maxValue, float inValue) { int i; float outValue = minValue; if (inValue > calibrationTable[i = 0]) while (maxValue >= outValue) { if (inValue < calibrationTable[++i]) return outValue + (inValue - calibrationTable[i-1]) * delta / (calibrationTable[i] - calibrationTable[i-1]); outValue += delta; }; return outValue; } float plaStraight (const float *calibrationTable, float delta, float minValue, float maxValue, float inValue) { int i; float outValue = minValue; if (inValue > calibrationTable[i = 0]) while (maxValue >= outValue) { if (inValue < calibrationTable[++i]) return outValue + (inValue - calibrationTable[i-1]) * delta / (calibrationTable[i] - calibrationTable[i-1]); outValue += delta; }; return outValue; } float plaRevers (const float *calibrationTable, u32 len, float reversDelta, float minValue, float inValue) { float outValue = calibrationTable[len - 1]; float inValue0 = minValue; float straightDelta; int i = 0; outValue = calibrationTable[len - 1]; inValue0 = minValue; if ( inValue > inValue0 ) { while ( calibrationTable[len-1] >= outValue ) { i++; if ( inValue < (inValue0 + reversDelta) ) { straightDelta = calibrationTable[i] - calibrationTable[i-1]; outValue = calibrationTable[i-1] + ((inValue - inValue0) * straightDelta / reversDelta); return outValue; } outValue = calibrationTable[i]; inValue += reversDelta; } outValue = calibrationTable[len-1]; } return outValue; }
Пример класса, в котором используются эти функции
class TermocoupleSProcessor: public TermocoupleProcessorBase { public: virtual float calcTemperature (float eds) { return plaStraight (typeSCalibrationTable, 10.0, -50.0f, 1760.0f, eds); //<<<Добавления этой строчки приводит к большому выделению памяти } virtual float calcEds (float t) { return plaRevers(typeSCalibrationTable, CALIBRATION_TABLE_LEN, 10.0f, -50.0f, t);//<<<Добавления этой строчки приводит к большому выделению памяти } virtual void init (void) { sensorType = TermocoupleS; conversationIsReady = 0; } };
Объекты я объявляю статически. Для каждого типа термопары у меня по два объекта соответствующего класса. Добавления вызова plaStraight и plaStraight в каждом подобном классе приводит к резкому возрастанию выделения статической памяти. В итоге у меня ее просто не хватает. Что можно с этим поделать, есть идеи?
arm-none-eabi-gcc линковка статических бибилотек
в GNU/OpenSource средства разработки
Опубликовано · Пожаловаться
Снова вернулся к попыткам собрать статическую либу. Проблема так и не решилась. Достоверно выяснилось следующее:
1) Когда я добавляю syscalls.o в статическую библиотеку вместе со всем остальным, то при компиляции приложения с использованием этой либы вылазит ошибка:
Но все перечисленные функции реализованы в syscalls.c! Почему он их не видит?!
2) Когда я исключаю из библиотеки syscalls.o и приликовываю ее на этапе компиляции приложения вместе с библиотекой, все компилируется без ошибок и прекрасно работает.
Компилирую arm-none-eabi-gcc, линкую либу arm-none-eabi-gcc-ar, линкую приложение arm-none-eabi-gcc. Флаги следующие: