• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

BLE SoC PHY6202

pvvx

Активный участник сообщества
@cool2000 - Если отключить RC32_TRACKINK_ALLOW, тогда работа в соединение становится стабильнее - подавал с генератора 20Гц и полчаса соединение держит. При 50Гц уже сбивается.
С включенным флагом - тянет только до 2 Гц.
Но, с нуля это не пройдет. Только после калибровки RTC, а этот флаг завязан на начальную калибровку.
RC 32KHz tracking counter, calculate 16MHz ticks number per RC32KHz cycle
В этом регистре:
#define STD_RC32_16_CYCLE_16MHZ_CYCLE (7812) // standard 16Mhz cycles for 16 RC32KHz tick
16*16000000/32768 = 7812.5
При чтении в HTML `DA64f00040` значение болтается вокруг 7812.5.

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

cool2000

Member
Перемудрили китайцы с калибровкой. Видимо тупо подбирали, чтобы хоть как-то работало. По хорошему, тут надо использовать ПИФ, а не БИФ, да ещё с и от балды выбранным параметром.
 

cool2000

Member
Ещё явный ляп с ограничениями на величину ухода. Если текущее значение counter_tracking выходит за границы, то надо для вычисления g_counter_traking_avg брать одно из граничных значений, а не усреднённое, иначе слежения вообще не будет.
Возможно из-за этого тайминги сбиваются, судя по тому, что при отключённой калибровке всё работает.
 

pvvx

Активный участник сообщества
0x4000f05C - [bit16] 16M [bit8:4] cnt [bit3] track_en_rc32k
0x4000f064 - RC 32KHz tracking counter, calculate 16MHz ticks number per RC32KHz cycle
Считает автоматом сколько периодов 16 MHz за установленный счет RC.
 

pvvx

Активный участник сообщества
Там всё ещё хуже - в некоторых местах похоже считают что RC идет как 32000 Гц, а не 32768...
Солянка для разных чипов PHY.
 

pvvx

Активный участник сообщества
Надо глянуть реальную стабильность RC генератора. Вбить константу и проверить, т.к. без этих расчетов всё работает стабильно.
Термометр на борту есть - можно даже по нему откалибровать :)
 

pvvx

Активный участник сообщества
В биты 8..4 записывают множитель для 16МГц (16)?
Если 0 туда записать, то не будет считать или примет множитель равным 32?
Я не знаю.
Где-то есть комент в исходниках, как переключить на другую CLK...

Похоже есть несоответствие -
hal_rc32k_clk_tracking_init():
counter_tracking = g_counter_traking_avg = STD_RC32_16_CYCLE_16MHZ_CYCLE;
Т.е. считают на 16 циклов.
А расчет в patch.c идет для 2-х циклов.

Но:
g_counter_traking_cnt = 0x1fff0a30;
sleep_tick = 0x1fff0a34;
counter_tracking = 0x1fff0a38;

Считано 0x1fff0a30: e8030000 12e9ba43 621e0000 78563412
counter_tracking -> 0x1e62 = 7778 тиков CLK 16 MHz

Разгадывать надо...
 

cool2000

Member
Считываются примерно такие значения:
  • 1FFF0A14: 00001E78 (7800) - g_counter_traking_avg
  • 1FFF0A30: 000003E8 (1000) - g_counter_traking_cnt
  • 1FFF0A34: EE8F7F5E (????) - sleep_tick
  • 1FFF0A38: 0001E7D (7805) - counter_tracking
  • 1FFF0A3C: 12345678 (????) - forever_write
Вроде оба счётчика в пределах нормы: 7812±391.
Не нашёл исходного текста enterSleepProcess1()
Вот что гидра выдаёт:
C:
void rc32k_cap_cal(uint count)
{
  uint val;
 
  if ((count < 8204) || (((AP_AON->PMCTL1 & 0x7e) >> 1) == 0) {
     if (7420 < count) {
       return;
     }
     if (125 < (AP_AON->PMCTL1 & 0x7e)) {
       return;
     }
     val = ((AP_AON->PMCTL1 & 0x7e) >> 1) + 1;
  }
  else {
     val = ((AP_AON->PMCTL1 & 0x7e) >> 1) - 1;
  }
  AP_AON->PMCTL1 = AP_AON->PMCTL1 & 0xffffff81 | (val << 1);
  WaitRTCCount(3);
  return;
}

// Added SDK 3.1.3
#define   RC32_CAP_ADAPTIVE_TRIM           0x00000400

void enterSleepProcess1(uint32_t time)

{
  if (pGlobal_config[LL_SWITCH] & RC32_CAP_ADAPTIVE_TRIM) {
     rc32k_cap_cal(AP_AON->RC32CNT & 0x1ffff); // 0x4000f064
  }
  if (osal_search_active_task(0)) {
     enterSleepProcess0(time);
  }
}
 

pvvx

Активный участник сообщества
Sleep скорее всего ничего не меняет, т.к. работа RF идет по вычисленным счетчикам при просыпании.
Значение для sleep только уменьшает потребление. Но если переспит, то тоже будет беда - пропуск...
Я пока не нашел, где "рветcя".
 

pvvx

Активный участник сообщества
Где в SDK минимальное время периода сна для отработки выхода в сон?
Для теста надо его увеличить, а счетчик срабатывания, записываемый в RTC тупо уменьшить. Пусть просыпается раньше и ждет.
 

pvvx

Активный участник сообщества
При работе OTA у меня ещё ни разу соединение не разоралось. А там загрузка максимальная.
При OTA даже не отключал все остальные функции - отработку датчиков и запись истории в Flash.
В Telink такое не проходит.
Сложно искать случайные сбои.... т.к. ещё не выяснено кто сбоит.
А RTC все равно надо изучить для нормальной коррекции времени. По этому с RTC и начал копаться...
 

cool2000

Member
Если таймеры тактируются частотой 4МГц, то Timer2 считает 625us интервалы:
set_timer(AP_TIM2, 625); // OSAL 625us tick - 4000000/(625*4)
но Timer3 получается не секундный, а 4-х секундный (точнее 4,194 сек)
#define BASE_TIME_UNITS (0x3fffff)
set_timer(AP_TIM3, BASE_TIME_UNITS); // 1s timer 4000000/(4194303*4))

C:
uint32_t tracking_cnt = 0;

void wakeup_init1(void)

{
    efuse_init();
    __wdt_init();
    uint8_t pktFmt = PKT_FMT_BLE1M;    // packet format 1: BLE 1M
    uint32  temp;
   
    hal_system_clock_change_process();
   
    if (g_system_clk == SYS_CLK_XTAL_16M)
    {
        WaitRTCCount(pGlobal_config[WAKEUP_DELAY]);
    }
    else
    {
        uint32_t tracking_c1,tracking_c2;
       
        tracking_c1 = rtc_get_counter();
        WaitRTCCount(15);
        check_16MXtal_by_rcTracking();
        WaitRTCCount(5);
        if (g_system_clk != SYS_CLK_DBL_32M)
        {
            check_96MXtal_by_rcTracking();
        }
        else
        {
            /*
                for hclk=32M DBL
                switch to 32M RC and reset DBL
            */
            if ((AP_AON->RTCCLK0 & 0x07) == SYS_CLK_DBL_32M) {
                clk_init(SYS_CLK_RC_32M);
            }
            //reset doubler
            AP_PCRM->CLKHF_CTL1 &= ~BIT(8);
            WaitRTCCount(2);
            AP_PCRM->CLKHF_CTL1 |= BIT(8);
        }
        tracking_c2 = rtc_get_counter();
       
        tracking_cnt = (tracking_c2>=tracking_c1) ? (tracking_c2 - tracking_c1) : (0xffffffff - tracking_c1 + tracking_c2);
        pGlobal_config[WAKEUP_ADVANCE] = 1650 + 30*tracking_cnt;
    }

    // ============ config BB Top
    *(volatile uint32_t*) 0x40030000 = 0x3d068001;  // set tx pkt =2
    *(volatile uint32_t*) 0x400300bc = 0x834;       //[7:0] pll_tm [11:8] rxafe settle
    *(volatile uint32_t*) 0x400300a4 = 0x140;       //[6] for tpm_en
    clk_init(g_system_clk);
    // ========== init timers
    set_timer(AP_TIM2, 625);             // OSAL 625us tick
    AP_TIM2->LoadCount = 2499;
    AP_TIM2->ControlReg = 3;
    set_timer(AP_TIM3, BASE_TIME_UNITS); // 1s timer
    NVIC_EnableIRQ(BB_IRQn);
    NVIC_EnableIRQ(TIM1_IRQn);
    NVIC_EnableIRQ(TIM2_IRQn);
    // =========== ll HW setting
    set_max_length(0xff);
    ll_hw_set_empty_head(0x0001);
    //time related setting
    ll_hw_set_rx_timeout_1st(500);
    ll_hw_set_rx_timeout(88);   //ZQ 20180606, reduce rx timeout for power saving
    //preamble + syncword=40us, sync process = 8us
    //timeout should be larger then 48us,
    //ll_hw_set_rx_timeout(       268);     //for ble shoulde be larger than 80+128. if sync, the timeout timer stop.
    // (80 + 128) - BLE 5.0 preamble + access time, 60 for HW process delay
    // this time doesn't consider HW startup time, it is set in other regs
    ll_hw_set_loop_timeout(30000);
//      ll_hw_set_tx_rx_release (10,     1);
//      ll_hw_set_rx_tx_interval(       57);        //T_IFS=150us for BLE 1M
//      ll_hw_set_tx_rx_interval(       65);        //T_IFS=150us for BLE 1M
//      ll_hw_set_trx_settle    (57, 8, 52);        //TxBB,RxAFE,PLL
    ll_hw_set_timing(pktFmt);
    ll_hw_ign_rfifo(LL_HW_IGN_SSN | LL_HW_IGN_CRC | LL_HW_IGN_EMP);
    temp = AP_AON->RTCCFG2;
    AP_AON->RTCCFG2 = (temp & 0xfffefe00) | 0x0108;  //[16] 16M [8:4] cnt [3] track_en_rc32k
}

uint32_t rtc_get_counter(void)
{
  return AP_AON->RTCCNT;
}

uint32_t read_current_fine_time(void)
{
  return (0x400001 - (AP_TIM3->CurrentCount >> 2));
}
 

pvvx

Активный участник сообщества
pGlobal_config[MIN_SLEEP_TIME] = 1600;
Чип только просыпается это время + ещё заснуть. Для экономии питания надо менять это значение на большее. Или на короткие дистанции использовать не deep-sleep, а
suspends (__ASM volatile ("wfi") / wfe / ...)
 

pvvx

Активный участник сообщества
Не влияет pGlobal_config[MIN_SLEEP_TIME]
Ставил = 10000. На диаграмме питания невидать - так же делает паузы и на меньше 10 мс.
Менял AP_AON->RTCCC0 = sleep_tick + time; //set RTC comparatr0 value
Ставил if(time > 600) time -= 500; Так же не влияет.
Соединение держится одинаково - срывает от IRQ GPIO.
 

pvvx

Активный участник сообщества
1707707248695.png
pGlobal_config[MIN_SLEEP_TIME] = 0xf24f4 = 992500
1707707238841.png
И перезагрузка....
 

cool2000

Member
И перезагрузка....
Возможно watchdog срабатывает, хотя watchdog_config(WDG_2S); должен 2 сек ждать.
Для проверки попробовать переключить WDT в режим прерывания:
//#define HAL_WDG_CFG_MODE WDG_USE_POLLING_MODE
#define HAL_WDG_CFG_MODE WDG_USE_INT_MODE
или в pwrmgr.c раскомментировать код
C:
__ATTR_SECTION_SRAM__ void osal_idle_task(void)
{
    if (AP_WDT_ENABLE_STATE)
        AP_WDT_FEED;

    if (osal_idle_app_loop())
        osal_pwrmgr_powerconserve0();
}
int hal_pwrmgr_init(void)
{
    memset(&mCtx, 0, sizeof(mCtx));

    switch(mPwrMode)
    {
    case PWR_MODE_NO_SLEEP:
    case PWR_MODE_PWROFF_NO_SLEEP:
        disableSleep();
        break;

    case PWR_MODE_SLEEP:
        enableSleep();
        break;
    }

/*
        if wdt enable, set osal idle task to feed wdt before powerconserve
*/
  if(AP_WDT_ENABLE_STATE)
        JUMP_FUNCTION(OSAL_POWER_CONSERVE)=(uint32_t)&osal_idle_task;
    return PPlus_SUCCESS;
}
Кстати, внутри osal_pwrmgr_powerconserve0 после всяких проверок вызывается wfi.
Или просто отключить WDT.
 

pvvx

Активный участник сообщества
Возможно watchdog срабатывает, хотя watchdog_config(WDG_2S); должен 2 сек ждать.
Это я для проверки такое значение поставил. При меньших всё равно стабильность с irq gpio не наблюдается. И с соединением.
Но у меня только один экземпляр из 5-ти термометров для тестов прерывает соединение сам по себе, и то спустя не менее пары десятков минут. THB2. На нем и тренируюсь...
THB2 отличается тем, что нет индуктивности на DC-DC. Может в этом дело?
 
Сверху Снизу