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

yanvasilij

Свой
  • Постов

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

  • Посещение

Сообщения, опубликованные yanvasilij


  1. Снова вернулся к попыткам собрать статическую либу. Проблема так и не решилась. Достоверно выяснилось следующее:

     

    1) Когда я добавляю syscalls.o в статическую библиотеку вместе со всем остальным, то при компиляции приложения с использованием этой либы вылазит ошибка:

     

    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-abort.o): In function `abort':
    abort.c:(.text.abort+0xa): undefined reference to `_exit'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-sbrkr.o): In function `_sbrk_r':
    sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-signalr.o): In function `_kill_r':
    signalr.c:(.text._kill_r+0xe): undefined reference to `_kill'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-signalr.o): In function `_getpid_r':
    signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-writer.o): In function `_write_r':
    writer.c:(.text._write_r+0x10): undefined reference to `_write'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-closer.o): In function `_close_r':
    closer.c:(.text._close_r+0xc): undefined reference to `_close'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-fstatr.o): In function `_fstat_r':
    fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-isattyr.o): In function `_isatty_r':
    isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-lseekr.o): In function `_lseek_r':
    lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
    c:/program files (x86)/gnu tools arm embedded/4.9 2015q2/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libg.a(lib_a-readr.o): In function `_read_r':
    readr.c:(.text._read_r+0x10): undefined reference to `_read'
    collect2.exe: error: ld returned 1 exit status
    

     

    Но все перечисленные функции реализованы в syscalls.c! Почему он их не видит?!

     

    2) Когда я исключаю из библиотеки syscalls.o и приликовываю ее на этапе компиляции приложения вместе с библиотекой, все компилируется без ошибок и прекрасно работает.

     

    Компилирую arm-none-eabi-gcc, линкую либу arm-none-eabi-gcc-ar, линкую приложение arm-none-eabi-gcc. Флаги следующие:

     

    #common flags
    SET(COMMON_FLAGS "-mthumb")
    SET(COMMON_FLAGS "${COMMON_FLAGS} -Wall")
    SET(COMMON_FLAGS "${COMMON_FLAGS} -mcpu=cortex-m3")
    SET(COMMON_FLAGS "${COMMON_FLAGS} -mlittle-endian")
    #common compiler flags
    SET(COMMON_CFLAGS "-D USE_STDPERIPH_DRIVER")
    SET(COMMON_CFLAGS "${COMMON_CFLAGS} -D USE_STDPERIPH_DRIVER")
    SET(COMMON_CFLAGS "${COMMON_CFLAGS} -D STM32F429_439xx")
    #SET(COMMON_CFLAGS "${COMMON_CFLAGS} --specs=rdimon.specs")
    #SET(COMMON_CFLAGS "${COMMON_CFLAGS} -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group")
    #c-files compiler flags
    SET(CMAKE_C_FLAGS "${COMMON_FLAGS} ${COMMON_CFLAGS}" CACHE INTERNAL "c compiler flags")
    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
    #cpp-files compiler flags
    SET(CMAKE_CXX_FLAGS "${COMMON_FLAGS} ${COMMON_CFLAGS}" CACHE INTERNAL "cxx compiler flags")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-threadsafe-statics")
    #linker flags
    SET(CMAKE_EXE_LINKER_FLAGS "${COMMON_FLAGS}" CACHE INTERNAL "exe link flags")
    SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-section")
    SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}  -T ./linkScript/STM32F407ZG_FLASH.ld")
    

     

     

  2. Кроме всего прочего, имейте в виду, что нормальный сигнал в кабеле появляется только после процедуры Autonegatiation. До этого Вы будете видеть только link-импульсы, короткие и редкие. После того, как две физики договариваются, начинается нормальный обмен. Протокол описан в стандарте.

     

    Спасибо! Именно то, что мне нужно. На осциллографе, получается, мы видели только link-импульсы, короткие и редкие. Следовательно что-то неладное на стороне микросхемы PHY. Начали проверять - выяснилось непропай на ноге генератора тактовой частоты. Пропаяли - все заработало.

  3. что-то не понимаю, в чём вопрос.

    Создать цель сборки, состоящую из двух зависимостей - исполняемого файла и либы.

    Вызывать эту цель сборки, соберётся и то, и то.

     

    Ну вот как указать, чтобы либа собиралась arm-none-eabi-gcc-ar?

  4. Доброго времени суток!

     

    Ситуация такая. Компилирую проект через make полученный cmake. Когда мне нужен просто исполняемый файл(alf, hex и т.п.) или просто статическая библиотека проблем нет, но мне нужно получать одновременно и статическую библиотеку и hex. Как выяснилось линковка статических либ осуществляется arm-none-eabi-gcc-ar, а линковка исполняемого файла arm-none-eabi-gcc. Как же сделать так, чтобы на выходе получать и то и то?

     

     

  5. А эти две разные микросхемы PHY точно расчитаны на работу с одинаковыми трансформаторами? Не зря же выпускается великое множество трансформаторов с различными схемами соединения обмоток и различными коэффициентами трансформации.

     

    Микросхемы KSZ8721 и KSZ8863. Обе могут работать с этим трасформатором, но у нас работает только KSZ8863, а вот KSZ8721 почему то не хочет. Скажите можно ли проверять работу трасформатора осциллографа так, как это делаем мы? Если нужно могу полностью подключение выложить, но надо ли?

  6. Вопрос вероятно идиотский, но ответа самостоятельно я так и не нашел. Есть две схемы с одинаковыми трансформаторами, но с разными микросхемами PHY. Первая схема работает отлично, моргают светодиоды link, есть пинги и т.п. На второй схеме нет ни линка ни пинга. Начали тыкать осциллографом и дошли в итоге до следующего: после траснформатора на ногах TPTX и TPRX на работающей схеме наблюдаем активную цифровую движуху (при подключенном сетевом кабеле разумеется); а на второй схеме после того же трасформатора нет никакого движения. Чтобы проверить, где проблема в физике или в трасформаторе решили поднять микросхему физики и посмотреть на особняком стоящем трансформаторе сигналы при подключенном сетевом кабеле. Так вот сигналы так и не появились (на неработающей схеме). Корректна ли такая проверка? Схему подключения трансформатора привожу ниже.

     

    post-69041-1459322240_thumb.png

  7. Да, там обычно много чего ходит broadcast'ом.

     

     

    Просто именованы на схеме странно: получились группы "RXDx и TX_EN" и "TXDx CRS_DV".

     

    Вообщем еще раз перепроверил - действительно пины перепутаны! Перепаял и все заработало - пинги есть, как свитч все прекрасно работает. Спасибо Вам огромное!

  8. Вообщем есть у меня проект под 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;
    
    }
    
    

     

    Не могу добиться пингов. Что я упускаю?

  9. На вид все нормально (у меня, правда, была другая конфигурация с 25МГц входом). Посмотрите, есть ли импульсы на SMRXDV3 при внешнем пинге.

    Да, у Вас CRS_DV и TX_EN на RMII не перепутаны случайно?

     

    Движение на SMRXDV3 есть, даже без пингов (возможно потому, что железка подключена к локальной сети, где много чего ходит?). CRS_DV и TX_EN не перепутаны - проверил только что. А почему вы предположили, что они перепутаны, есть какие-то ньюансы?

  10. Возможность прочитать идентификатор подтверждает работоспособность SMI (MDC/MDIO), а не RMII.

     

     

    Лучше приведите схему, с тактированием там есть нюансы.

     

    Выкинув из схемы лишнее получается следующее:

     

    post-69041-1459171911_thumb.png

     

    Да, я Вас обманул - используется специальная микросхема для тактирования

  11. Чтобы проверить связь с микросхемой я запросил Physical Identifier. По даташиту он должен быть 0x0022 страшем и 0x1430 в младшем -> при считывании так и оказалось. Связь по RMII есть я так понимаю.

     

        HAL_ETH_ReadPHYRegister(&heth, 0x02, &high);
        HAL_ETH_ReadPHYRegister(&heth, 0x03, &low);

     

    Между внешними портами связь есть. Попробовал через этот свитч соедининить комьютер и роутер - все работает.

     

    Тактирование от внешнего кварца 25 МГц.

  12. KSZ8863 - это свитч, поэтому вместо "драйвера" максимум нужна затычка, которая на все вопросы будет отвечать "Link up 100Mbit FDX", ибо других вариантов не предполагается.

     

    Нет у KSZ8863 помимо свитча есть еще MII/RMII для подключения к ЕМАК контроллеру. Вот у меня не получается заставить работать как раз эту часть, не могу добиться хотябы пингов. Вот и подумал спросить может уже кто оживлял.

  13. Вообщем проверил, как советовала Tanya - оказалась неверный тип термопары (я думал, что это тип K, а оказался тип E). Мне подогнали фирменный калибратор, который умеет эмулировать термопары, на нем все прекрасно работает. Спасибо всем за помощь!

  14. Если нет разности температуры между Г.С. и Х.С. то ТЭДС должна быть равна 0 (по вашим измерениям -0.182997 мВ)

    Чтобы получить истинную температуру надо просто прибавить(вычесть) температуру холодного спая. (тут вроде все правильно)

    Похоже ошибка в схемотехнике, не точно измеряется ТЭДС термопары. (т.к. 28,5 - 23,89 = 4,61 это примерно и есть те самые пересчетные в мВ -0.182997 мВ т.е. программа отрабатывает правильно)

     

    Спасибо за подсказку! Действительно я совсем об это не подумал. Начал проверять и выяснил, что напряжение появлялось, как оказалось, из-за того, что сама плата слегка греется, нагревая тем самым Х.С., создавая разницу между Г.С. и Х.С. А когда я калибровал датчик холодного спая, то не поднес эталонный датчик вплотную к разъему. В результате датчик температуры ХС врал на 4-5 градусов. Это точно вносило погрешность в измерения.

     

    Но вот беда: все равно результаты идут неверные. При комнаной температуре показания казались корректными (совпадали с эталоном). Но стоило мне бросить термопару в стакан с кипятком, как стало ясно что показания неверные - 130 градусов на кипящей воде. Чем выше температура тем больше разница между эталоном и моими измерения с термопарой. Например:

    - Показания эталонного прибора - 35 C

    - Моя программа показала 41,72

    - Термоэдс при этом была 0.481197 мВ

    - Температура холодного спая 30.04

     

    Проверил градуировочную характеристку, зашитую в контроллер, - точно совпадает с ГОСТом. Что это может быть?

     

     

     

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

    - Термоэдс измеряется точно, я подавал эталонное напряжение и оно совпадало с тем, что выдавал мой микроконтроллер (проверил несколькими приборами)

    - Температура холодного спая тоже определяется точно (проверял датчиком 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 Считывание завершено */
    

     

    Почему может быть такая большая погрешность? Что я упустил, подскажите пожалуйста?

     

     

  16. Если Вы используете в своей программе имя массива ...

     

    Так и было сделано, typeSCalibrationTable[]={ .... } и подобные ему массивы объявлены в отдельных *.c файлах, внутри класса TermocoupleSProcessor используются лишь указатель на этот массив.

     

     

    extern const float *tcoupleScalibrationTable; //Таблица объявлена, где-то в другом месте
    
    class TermocoupleProcessorBase : public BarrierSensorProcessorBase
    {
    
        public:
    
    ...
        float const *tCoupleParams; /**< @brief Внутри класса лишь указатель на массив */
    ...
    
    ...
          //В некотором месте программы происходит назначение этого указателя
          tCoupleParams = tcoupleScalibrationTable;
    ...
    };

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

    При RTOS это делается через очередь

     

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

  18. const в плюсах делает Ваш массив локальным в пределах единицы компиляции, так что static было писать не обязательно.

    В результате в каждом .с файле, где этот массив используется появляется ещё одна его копия.

     

    Если нужны константные данные, но доступные из разных файлов, объявляйте их как extern const, такая константа будет глобальной в проекте.

     

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

  19. по слову ZI-data определяется что это Keil

    автор, попробуйте массив вынести из класса и подепить его через конструктор или Extern

     

    Да компилятор keil.

    Моя вина - не сказал. Так и было с самого начала, в классе лишь указатель на этот массив.

  20. б-р-р-р, каждый вызов функции увеличивает потребление стека. Но по выходу из функции размер стека возвращается к значению до вызова. Рекурсий у вас тут не видно

     

     

     

    попробовать typeSCalibrationTable сделать как static const

     

    Нет, в том то и дело, что работа со стеком это динамика, статически выделяемая память при компиляции тут не при чем (точнее она при чем только при указании размера стека). Я не спорю с тем фактом, что увеличением вызовов увеличит потребление стека, это я понимаю. Проблема в том, что у меня увеличивается объем выделенной статической памяти, на этапе компиляции (секция ZI-data), при увеличении точек входа в эту злосчастную функцию в программе.

     

    typeSCalibrationTable уже как static const, я забыл это упомянуть.

  21. Доброго времени суток!

     

    Столкнулся с тем, что не хватает памяти на микроконтроллере. Начал копать и выяснил, что больше всего памяти потребляет вызов функции, которая у меня занимается вычислениями по калибровочным таблицам (кусочно-линейная аппроксимация). Поскольку мое устройство должно поддерживать большое количество датчиков, вызов этой функции осуществляется из разных мест программы. Добавления каждого нового вызова этой функции вызывает у меня увеличение потребления статической памяти. Я долго думал можно ли с этим что либо поделать, но так и не придумал. Ниже привожу примеры использования.\

     

    Собственно сами функции:

    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 в каждом подобном классе приводит к резкому возрастанию выделения статической памяти. В итоге у меня ее просто не хватает. Что можно с этим поделать, есть идеи?

     

     

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