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

Сергей Борщ

Модератор
  • Постов

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

  • Посещение

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

    31

Сообщения, опубликованные Сергей Борщ


  1. 26 минут назад, MementoMori сказал:

    Я писал выше:

    Библиотеке вы в строке

    Socket->SendData(*buffer);

    передаете ссылку на объект типа TArray__1<System::Byte> (или сам объект по значению, но это если совсем криворукие библиотеку писали). Ей абсолютно фиолетово, где этот объект лежит. Поэтому код

    	{
    		TArray__1<System::Byte> buffer;
    		 buffer.set_length(sizeof(INFO_VAR));
    	
    		memcpy(buffer.data(),pInfo,sizeof(INFO_VAR));
    		Socket->SendData(buffer);
    	}

    будет работать ничуть не хуже, но будет короче и быстрее.

    1 час назад, dimka76 сказал:

    Он же писал, что пишет под Андроид.

    Так что, скорее всего, это Java.

    Слышал, что Java сама мусор убирает. А тут delete в коде. Неужели в Java все-все переменные должны объявляться через new? Тогда new было бы просто избыточно.

  2. 3 часа назад, MementoMori сказал:

    Ну дык вот, делал уже

    А теперь читайте по губам:

    3 часа назад, Сергей Борщ сказал:

    именно на буфер, а не на ваш объект класса TArray1<System::Byte>

     

    2 часа назад, MementoMori сказал:

    Делается под конкретную платформу. Для себя, если быть точным.

    Даже если для себя - это не повод делать программу медленной. Зачем вы создаете объект в динамической памяти через new? Размер буфера в этом классе задается на этапе исполнения, значит сам буфер этот объект хранит в динамической памяти и размер самого объекта мизерный, его можно смело разместить на стеке не тратя время и электричество на выделение в динамической памяти и последующее удаление. Следующее улучшение - я бы создал наследника этого класса, для которого определил бы через шаблон  operator <<() для ссылки на любой тип, чтобы можно было писать Buffer << INFO_VAR; и о вычислении размера INFO_VAR и занесении этого размера в set_length() голова болела у компилятора.

  3. 14 минут назад, MementoMori сказал:

    но я хочу понять, как это делается проще, через указатели

    1) получить указатель на буфер (именно на буфер, а не на ваш объект каласса TArray1<System::Byte>)

    2a) memcpy()

    2b) явно привести этот указатель на буфер к типу "указатель на tINFO_VAR" и присвоить структуру по приведенному указателю.

    Не видя описания TArray1 очень трудно что-то посоветовать. По вашим примерам видно, что этот класс переопределяет operator[]. Можно, конечно, воспользоваться им, но есть подозрение, что этот класс предоставляет какой-то более удобный в данном случае способ доступа к буферу.

     

  4. 2 часа назад, Arlleex сказал:

    Может, кто-то знает что по этому поводу?

    AN004 GD32F1 silicon limitations (rev2.1).pdf

    Брал на сайте GD, сейчас ни в лоб, ни через гуглю не нашел. Странно, видимо плохо искал.

  5. Я очень слабо верю в самопроизвольную порчу option bytes. А вот в ошибку программы, из-за которой она вызывает процедуру записи option bytes и пишет туда мусор, верю охотно. Поставьте ловушки перед всеми записями в FLASH->OPCR с проверкой на допустимые значения. Может еще какой-то флаг, который выставляется где-то глубоко в программе в момент появления штатной необходимости записи в option bytes и проверяется непосредственно перед записью. Потому что перед записью еще должен сброситься OPTLOCK двумя записями  разных чисел в FLASH->OPTKEYR, что явно не может произойти случайно, а только при исполнении кода, заточенного на запись option bytes, Я бы копал в эту сторону. 

    • Like 1
  6. 34 минуты назад, jcxz сказал:

    имеющего только один единственный write-only бит?

    Не знаю - во всех STM32, с которыми я работал последние несколько лет, в этом регистре есть еще другие значащие биты и их надо сохранять. Погорячились вы.

    Добавлено: прошел по ссылке, нигде конкретная модель STM32 не указана. Один write-only бит в CRC->CR есть только у F10x. Но у них нет упоминаемого в тексте RCC->AHB1ENR. У любого STM32 с регистром RCC->AHB1ENR на борту в регистре CRC->CR есть дополнительные биты, которые надо либо где-то хранить, либо прочитать (я знаю про константы времени компиляции и сам их использую). Так что снова пук в лужу, код абсолютно корректный.

  7. 2 часа назад, jcxz сказал:

    Так вот оказывается откуда весь этот быдлокод лезет!

    Плохого кода в интернете, действительно, много. Но какая претензия к именно этой строчке? Она абсолютно корректна.

  8. Нет, уменьшить количество шагов нельзя. Их количество прибито гвоздями. Хотите другое количество шагов - возьмите другую микросхему потенциометра.

    Можно на вторые концы кнопок подать сигнал с генератора (одна микросхема или два транзистора), тогда потенциометр будет шагать пока нажата кнопка.

  9. 26 минут назад, TOG сказал:

    Потом Устройство перестает быть точкой доступа

    И надо предусмотреть возможность потом вернуть его в исходное состояние. То есть какая-то кнопка или иной орган управления все же должен быть. Например - датчик холла в SOT23 и попавшийся под руку магнит.

  10. 3 минуты назад, jcxz сказал:

    А если заменить на WFE?

    Перепрошить ~сотню устройств (пусть около 20 сек на устройство - это займет около получаса) и пройти несколько кругов побудки/усыпления (это еще часа два-три) чисто ради любопытства - сомнительное удовольствие.

     

  11. Столкнулся с такой проблемой - устройство должно уйти в shutdown и по сигналу WKUP3 проснуться. Реализовано это так:

    Спойлер
    void sleep_manager::do_shutdown()
    {
        __disable_irq();
        // enable RTC write access, select Shutdown as deep sleep mode
        PWR->CR1 = 0
            | 0 * PWR_CR1_LPR                                       // Supply mode, 0: main regulator, 1: low power regulator
            | 1 * (PWR_CR1_VOS & -PWR_CR1_VOS)                      // Voltage scaling, 1: Range 1 (fast), 2: Range 2 (slow), 0, 3: forbidden
            | 1 * PWR_CR1_DBP                                       // Enable write access to backup domain registers
            | 0 * PWR_CR1_FPDS                                      // Flash mode during LPSleep, 0: Idle, 1: Power-down
            | 0 * PWR_CR1_FPDR                                      // Flash mode during LPRun, 0: Idle, 1: Power-down
            | 0 * PWR_CR1_SUBGHZSPINSSSEL                           // Radio SPI NSS select, 0: PWR->SUBGHZSPICR.NSS, 1: LPTIM3_OUT
            | 4 * (PWR_CR1_LPMS & -PWR_CR1_LPMS)                    // Low-power selection: 0: Stop0, 1: Stop1, 2: Stop2, 3: Standby, 4..7: Shutdown
            ;
    
        PWR->PUCRB = 0
            | 1 * PIN_BITMASK(SM353_INPUT)                          // подтяжка к питанию на WKUP3
            ;
    
        PWR->CR4 = 0
            | 0 * PWR_CR4_WRFBUSYP                                  // Wakeup from radio BUSY polarity, 0: active high(rising), 1: active low (falling)
            | 0 * PWR_CR4_VBRS                                      // Vbat battery charging resistor, 0: 5 kOhm, 1: 1.5 kOhm
            | 0 * PWR_CR4_VBE                                       // Vbat battery charging enable
            | 1 * PWR_CR4_WP3                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
            | 0 * PWR_CR4_WP2                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
            | 0 * PWR_CR4_WP1                                       // WKUP3 polarity, 0: active high(rising), 1: active low (falling)
            ;
    
        // disable PVD if was enabled
        PWR->CR2 = 0
            | 0 * PWR_CR2_PVME3                                     // Vdda monitoring versus 1.62v threshold enable
            | 0 * (PWR_CR2_PLS & -PWR_CR2_PLS)                      // PVD threshold, 0: 2.0v, 1: 2.2v, 2: 2.4v, 3: 2.5v, 4: 2.6v, 5: 2.8v, 6: 2.9v, 7: PVD_IN < VREFINT
            | 0 * PWR_CR2_PVDE                                      // PVD enable
            ;
    
        // настройка подтяжек на всех выводах
        PWR->PDCRA = ...
        PWR->PDCRB = ...
        PWR->PDCRC = ...
        PWR->PDCRH = ...
    
        PWR->CR3 = 0
            | 0 * PWR_CR3_EIWUL                                     // Internal wakeup line interrupt enable
            | 0 * PWR_CR3_EWRFIRQ                                   // Radio IRQ wakeup from standby enable
            | 0 * PWR_CR3_EWRFBUSY                                  // Radio busy wakeup from standby enable
            | 1 * PWR_CR3_APC                                       // Apply pull-up/down configuration, 1: use PWR->PUCRx, PWR->PDCRx
            | 0 * PWR_CR3_RRS                                       // SRAM2 power in Standby mode, 0: off, 1: low-power regulator
            | 0 * PWR_CR3_EWPVD                                     // PVD enable by radio active state
            | 1 * PWR_CR3_ULPEN                                     // Supply voltage sampling in Stop & Standby modes, 0: continuously,  1: periodically (~12 ms)
            | 1 * PWR_CR3_EWUP3                                     // WKUPx enable
            | 0 * PWR_CR3_EWUP2                                     // WKUPx enable
            | 0 * PWR_CR3_EWUP1                                     // WKUPx enable
            ;
    
        SCB->SCR |= SCB_SCR_SLEEPDEEP;
        EXTI->IMR1 = 0;
    
        {
            // errata 2.2.11: Potential deadlock condition on wakeup from some low-power modes
            auto Attempts = 48/6 * 1000 * 1000;   // ~1 sec at MSI48
            for(;;)
            {
                if(PWR->SR2 & PWR_SR2_LDORDY)
                    break;
    
                if(!--Attempts)
                    wdt_reboot();
            }
        }
    
        for(;;)
        {
            EXTI->PR1 = ~0; // clear pending EXTI.
            PWR->SCR = ~0;  // clear wakeup status
    
            __WFI();
        }
    }

     

    Почти всегда это работает, но очень редко устройство может сбойнуть (захочешь конкретное устройство специально загнать в это состояние - хоть обусыпляйся, но если ~сотню устройств разбудить/усыпить - где-то на третьем проходе одно из устройств может сбойнуть). При этом программа постоянно крутится в бесконечном цикле вокруг WFI, PWR->EXTSCR в нулях, т.е. ядро даже не пытается уйти в сон. В PWR->SR1 все флаги в нулях, EXTI->PRx в нулях, NVIC->ISPRx в нулях. Контроллер тактируется от MSI, настроенного на 48 МГц. Что может мешать ему уснуть?

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

  12. 33 минуты назад, jcxz сказал:

    Зачем "сначала запускать загрузчик" при отладке приложения?

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

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

  13. 36 минут назад, haker_fox сказал:

    И ожидал такого поведения, т.к. микроконтроллеру ничего не остаётся, как начать исполнять код, где уже зашит мой загрузчик.

    Забыл упомянуть еще один момент - Эклипса после загрузки образа прошивки из .elf сама устанавливает счетчик команд на начальный адрес. Этот адрес в gcc устанавливается скриптом компоновщика через директиву ENTRY(). Поскольку ИАР тоже использует формат .elf - наверняка в нем тоже есть подобный механизм.

  14. Странные проблемы. IAR (как и любая другая среда) после загрузки образа делает аппаратный либо программный сброс, который сам по себе делает то, что вы хотите - запускает ваш загрузчик. И уже загрузчик должен прописывать VTOR, указатель стека и передавать управление приложению. Вот запустить приложение в обход загрузчика - это да, это надо приложить усилия (я для старого ИАРа писал файл с макросами отладчика, которые вычитывали из памяти адрес стека приложения, грузили его в нужный регистр, грузили VTOR, вычитывали адрес обработчика вектора сброса приложения и писали его в PC. Собственно, примерно то же делаю и с OpenOCD. 

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