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

8710 странности с GPIO

pvvx

Активный участник сообщества
Разбирался с IP пинами, и получилась таблица
IP получал: HAL_GPIO_GetIPPinName_8195a(PA_0) - исходный код закрыт
Port и Pin: HAL_GPIO_GET_PORT_BY_NAME(), HAL_GPIO_GET_PIN_BY_NAME() - простое смещение
Что-то вообще не понятно - какой ещё IP ? Нафиг вам он? У вас RTL8195AM?

ROM-BIOS (перевод в код си из asm, для справки, могут быть неточности):
Код:
uint32_t HAL_GPIO_GetIPPinName_8195a(uint32_t chip_pin)
{
  return GPIO_GetIPPinName_8195a(chip_pin);
}
unsigned char GPIO_PinMap_Chip2IP_8195a[] = {...... };
uint32_t GPIO_GetIPPinName_8195a(uint32_t result)
{
  unsigned char *ptr = &GPIO_PinMap_Chip2IP_8195a[2];
  if(result) {
   while(*ptr != 255) {
    if(*ptr == (unsigned char) result) return result;
    ptr += 2;
   }
   DBG_GPIO_WARN("Cannot find pin for GPIO %d\n", result);
   result = 255;
  }
  return result;
}
Как видим - запрос по нулю (PA_0) всегда = 0.
Какого смысла тратить время и код на бесполезное сравнение готового номера в этот-же номер?
Посмотреть вложение 3705
Сложил с распиновкой чипа, однако ничего интересного не вышло
А что это за раскраска?
Код пина в SDK = (((код буквы порта)-'A')<<4) | (номер пина в порту): RTL00MP3/PinNames.h at master · pvvx/RTL00MP3 · GitHub

Тест в RtlDuino RtlDuino/Test_GPIO_out.ino at master · pvvx/RtlDuino · GitHub
В Arduino для доступа к пинам используется другая нумерация.
 
Последнее редактирование:

pvvx

Активный участник сообщества
В таблице PullUp указаны адреса регистров + 0x40000000
Таблицы находятся в ROM-BIOS, адреса указаны в *.ld файле. Код, исполняемый в ROM-BIOS и TCM RAM работает без дополнительных циклов ожидания, в SRAM и SDRAM с доп. тактами ожидания. Т.ч. нет смысла писать свой перевод номеров пинов или обращения к ним в своем коде - используйте процедуры ROM-BIOS.
Обращение к пинам идет через GPIO_LockV02() и GPIO_UnLockV02() (в ROM-BIOS) используются флаги _pHAL_Gpio_Adapter->Locked/_pHAL_Gpio_Adapter->Gpio_Func_En
 
Последнее редактирование:

Seeker

New member
GPIO_PinMap_Chip2IP_8195a есть часть того что я попытался описать.
Не спорю, что PC_0 = (2<<4|0) = 0x20
Работа с ногами из примеров:
Код:
void gpio_mode (gpio_t *obj, PinMode mode);
void gpio_dir  (gpio_t *obj, PinDirection direction);
void gpio_init(gpio_t *obj, PinName pin);
В gpio_init в конце есть функция, которая принимает структуру _HAL_GPIO_PIN_
[inline]HAL_GPIO_Init(&obj->hal_pin);[/inline]
где hal_pin.pin_name= HAL_GPIO_GetIPPinName_8195a(PC_0 ); // = 42 для PC_0
Внутри HAL_GPIO_Init есть следующая функция
[inline]HAL_GPIO_Init_8195a(_HAL_GPIO_PIN_); // что делает неизвестно, кода нет[/inline]
Также gpio_write(gpio_t *obj, int value)
Ипользует:
Код:
pin_num = obj->hal_pin_num;       // = HAL_GPIO_GET_PORT_BY_NAME(hal_pin.pin_name ); // = 10 для hal_pin.pin_name = 42 , расчитывается по смещению
port_num = obj->hal_port_num;    // = HAL_GPIO_GET_PIN_BY_NAME(hal_pin.pin_name );    // = 1 по смещению
Код:
reg_value =  HAL_READ32(GPIO_REG_BASE, GPIO_SWPORT_DR_TBL[port_num]);
reg_value &= ~(1 << pin_num);
reg_value |= ((value&0x01)<< pin_num);
HAL_WRITE32(GPIO_REG_BASE, GPIO_SWPORT_DR_TBL[port_num], reg_value);
Вот и пришел я к заключению, что порты A, B,C ,E которые написаны на модуле и в даташите просто фантик. А внутри они сидят на двух портах.
Но из предоставленного Вами массива GPIO_PinMap_Chip2IP_8195a, видно что портов три.
Данное исследование предводит к надобности переписать gpio исходники полностью.
 
Последнее редактирование:
  • Like
Реакции: KomX

pvvx

Активный участник сообщества
Вот и пришел я к заключению, что порты A, B,C ,E которые написаны на модуле и в даташите просто фантик. А внутри они сидят на двух портах.
Но из предоставленного Вами массива GPIO_PinMap_Chip2IP_8195a, видно что портов три.
Данное исследование предводит к надобности переписать gpio исходники полностью.
Зачем переписывать ROM? И как? :)
Физически быти управления пинами раскиданы, можно так выразиться по группам в 3 32-х битных регистров SoC. И то регистры подтяжек и прочего управления пинов находятся в других полях и занимают не 3 ристра :) Какого смысла делать свою таблицу? Придется переписывать весь HAL на все устройства, с целью получить другие таблицы и переписать всю документацию, включая рисунки чипов? Что это меняет?
Описания адресов управления пинами даны в хидерах, таблицы соответствия пинов к ним в ROM и все процедуры уже есть. Нет никакого смысла это переписывать, кроме как увеличить размер кода в RAM.
И зачем в исходниках SDK исходники ROM? Её всё равно не поменять.

@Seeker - с чем боритесь? Получить линейную адресацию всех устройств и пинов всё равно не удастся - будут другие таблицы с другими именами пинов и ничего не измениться, кроме большего объема кода в RAM.
Обращаться напрямую к регистрам в многозадачной (RTOS) среде нельзя. Пока вы будите работать со считанным значением регистра, его может изменить другая задача и будут конфликты. Подход, как это применялось в 8-ми битных простых MCU тут не применим.
Чтобы изменить бит пина вашей задаче надо запросить и взять флаг у RTOS что она занимает устройство i/o и другие задачи пока будут ждать окончания работы вашей. Когда ваша задача изменит значение пина, то должна отдать флаг системе - освободить устройство i/o. После этого ожидающие задачи смогут тоже изменить i/o. Для пользователя и существует уровень api работы с пинами, где это всё уже исполняется.
HAL уровень не имеет связи с RTOS, а описывает только абстракцию аппаратного уровня.
Api уровень строится над HAL и связывает работу с системой (RTOS).
Напрямую в регистры в пользовательской части кода никто не лезет.
Если пишите специальный драйвер для работы с i/o, то придется учесть работу других устройств и их структуры. Сложного там ничего нет.
Обращение к пинам идет через GPIO_LockV02() и GPIO_UnLockV02() (в ROM-BIOS) используются флаги _pHAL_Gpio_Adapter->Locked/_pHAL_Gpio_Adapter->Gpio_Func_En
Получить физический адрес бита так-же не сложно - используйте уже имеющиеся процедуры в ROM, переводящие виртуальный адрес порта и пина в физический для каждого типа доступа - чтения значения, или изменения направления i/o, или изменения бита прерывания, или изменения битов PullUp. Они могут быть разными в разных позициях физических регистров SoC. По этому линейного понятия - это регистр порта 'A' - нет. Есть только виртуальные.
 
Последнее редактирование:

Seeker

New member
Вот так люблю работать с ножками
Пример Stm'a
Код:
SysReg(GPIO_PC + GPIO_BRR)=PIN_14;
где:
#define SysReg(x) *((volatile u32*)(x))
#define GPIO_PC  (u32)(0x40011000)
#define GPIO_BRR  (u32)(0x14)
#define PIN_14  ((u32)0x4000)
На RTL'е сейчас тьма мусора, преобразования туда сюда. Меня такой код не устраивает. А в многопоточности надобности до сих пор не было.
 

Seeker

New member
Та таблица которую вычислял оказалась
const u8 Default_Port_PinDef[GPIO_PORT_NUM][GPIO_PORT_WIDTH+1]
из common\mbed\targets\hal\rtl8195a\port_api.c
Там повторно реализованы методы работы с gpio.
Копирайт древний "Copyright (c) 2006-2013 ARM Limited".
 

pvvx

Активный участник сообщества
Последнее редактирование:

pvvx

Активный участник сообщества
Код:
#ifndef _BITBAND_IO_H_
#define _BITBAND_IO_H_

#include "hal_platform.h"
#include "hal_api.h"
#include "hal_gpio.h"
#include "rtl8195a_gpio.h"

#define BITBAND_PERI_REF    0x40000000
#define BITBAND_PERI_BASE    0x42000000
#define BITBAND_PERI(a,b)    (BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4))    // Convert PERI address
#define ucBITBAND_PERI(a,b)    *((volatile unsigned char *)BITBAND_PERI(a,b))
#define uiBITBAND_PERI(a,b) *((volatile unsigned int *)BITBAND_PERI(a,b))

#define GPIO_A0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,0)    //Port = 0, bit = 0, A0
#define GPIO_A1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,1)    //Port = 0, bit = 1, A1
#define GPIO_A2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,0)    //Port = 1, bit = 0, A2
#define GPIO_A3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,1)    //Port = 1, bit = 1, A3
#define GPIO_A4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,2)    //Port = 1, bit = 2, A4
#define GPIO_A5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,3)    //Port = 1, bit = 3, A5
#define GPIO_A6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,4)    //Port = 1, bit = 4, A6
#define GPIO_A7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,5)    //Port = 1, bit = 5, A7

#define GPIO_B0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,6)    //Port = 1, bit = 6, B0
#define GPIO_B1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,7)    //Port = 1, bit = 7, B1
#define GPIO_B2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,8)    //Port = 1, bit = 8, B2
#define GPIO_B3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,2)    //Port = 0, bit = 2, B3
#define GPIO_B4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,3)    //Port = 0, bit = 3, B4
#define GPIO_B5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,9)    //Port = 1, bit = 9, B5
#define GPIO_B6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,4)    //Port = 0, bit = 4, B6
#define GPIO_B7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,5)    //Port = 0, bit = 5, B7

#define GPIO_C0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,10)    //Port = 1, bit = 10, C0
#define GPIO_C1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,6)     //Port = 0, bit = 6,  C1
#define GPIO_C2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,11)    //Port = 1, bit = 11, C2
#define GPIO_C3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,7)     //Port = 0, bit = 7,  C3
#define GPIO_C4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,8)    //Port = 0, bit = 8,  C4
#define GPIO_C5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,9)    //Port = 0, bit = 9,  C5
#define GPIO_C6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,10)   //Port = 0, bit = 10, C6
#define GPIO_C7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,11)    //Port = 0, bit = 11, C7
#define GPIO_C8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,12)    //Port = 0, bit = 12, C8
#define GPIO_C9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,13)    //Port = 0, bit = 13, C9

#define GPIO_D0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,12)  //Port = 1, bit = 12, D0
#define GPIO_D1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,14)  //Port = 0, bit = 14, D1
#define GPIO_D2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,13)  //Port = 1, bit = 13, D2
#define GPIO_D3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,15)  //Port = 0, bit = 15, D3
#define GPIO_D4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,16)  //Port = 0, bit = 16, D4
#define GPIO_D5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,17)  //Port = 0, bit = 17, D5
#define GPIO_D6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,18)  //Port = 0, bit = 18, D6
#define GPIO_D7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,19)  //Port = 0, bit = 19, D7
#define GPIO_D8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,14)  //Port = 1, bit = 14, D8
#define GPIO_D9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,20)  //Port = 0, bit = 20, D9

#define GPIO_E0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,15)  //Port = 2, bit = 15, E0
#define GPIO_E1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,21)  //Port = 0, bit = 21, E1
#define GPIO_E2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,22)  //Port = 0, bit = 22, E2
#define GPIO_E3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,23)  //Port = 0, bit = 23, E3
#define GPIO_E4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,16)  //Port = 1, bit = 16, E4
#define GPIO_E5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,24)  //Port = 0, bit = 24, E5
#define GPIO_E6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,25)  //Port = 0, bit = 25, E6
#define GPIO_E7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,26)  //Port = 0, bit = 26, E7
#define GPIO_E8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,27)  //Port = 0, bit = 27, E8
#define GPIO_E9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,17)  //Port = 1, bit = 17, E9
#define GPIO_E10 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,18) //Port = 1, bit = 17, E10

#define GPIO_F0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,19)  //Port = 1, bit = 19, F0
#define GPIO_F1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,20)  //Port = 1, bit = 20, F1
#define GPIO_F2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,21)  //Port = 1, bit = 21, F2
#define GPIO_F3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,22)  //Port = 1, bit = 22, F3
#define GPIO_F4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,23)  //Port = 1, bit = 23, F4
#define GPIO_F5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,24)  //Port = 1, bit = 24, F5

#define GPIO_G0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,25)  //Port = 1, bit = 25, G0
#define GPIO_G1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,26)  //Port = 1, bit = 26, G1
#define GPIO_G2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,27)  //Port = 1, bit = 27, G2
#define GPIO_G3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,28)  //Port = 0, bit = 28, G3
#define GPIO_G4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,28)  //Port = 1, bit = 28, G4
#define GPIO_G5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,29)  //Port = 1, bit = 29, G5
#define GPIO_G6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,30)  //Port = 1, bit = 30, G6
#define GPIO_G7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,31)  //Port = 1, bit = 31, G7

#define GPIO_H0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,0)   //Port = 2, bit = 0,  H0
#define GPIO_H1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,29)  //Port = 0, bit = 29, H1
#define GPIO_H2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,1)   //Port = 2, bit = 1,  H2
#define GPIO_H3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,30)  //Port = 0, bit = 30, H3
#define GPIO_H4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,2)   //Port = 2, bit = 2,  H4
#define GPIO_H5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,31)  //Port = 0, bit = 31, H5
#define GPIO_H6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,3)   //Port = 2, bit = 3,  H6
#define GPIO_H7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,4)   //Port = 2, bit = 4,  H7

#define GPIO_I0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,5)   //Port = 2, bit = 5,  I0
#define GPIO_I1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,6)   //Port = 2, bit = 6,  I1
#define GPIO_I2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,7)   //Port = 2, bit = 7,  I2
#define GPIO_I3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,8)   //Port = 2, bit = 8,  I3
#define GPIO_I4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,9)   //Port = 2, bit = 9,  I4
#define GPIO_I5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,10)  //Port = 2, bit = 10, I5
#define GPIO_I6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,11)  //Port = 2, bit = 11, I6
#define GPIO_I7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,12)  //Port = 2, bit = 12, I7

#define GPIO_J0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,13)  //Port = 2, bit = 13, J0
#define GPIO_J1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,14)  //Port = 2, bit = 14, J1
#define GPIO_J2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,15)  //Port = 2, bit = 15, J2
#define GPIO_J3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,16)  //Port = 2, bit = 16, J3
#define GPIO_J4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,17)  //Port = 2, bit = 17, J4
#define GPIO_J5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,18)  //Port = 2, bit = 18, J5
#define GPIO_J6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,19)  //Port = 2, bit = 19, J6

#define GPIO_K0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,20)  //Port = 2, bit = 20, K0
#define GPIO_K1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,21)  //Port = 2, bit = 21, K1
#define GPIO_K2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,22)  //Port = 2, bit = 22, K2
#define GPIO_K3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,23)  //Port = 2, bit = 23, K3
#define GPIO_K4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,24)  //Port = 2, bit = 24, K4
#define GPIO_K5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,25)  //Port = 2, bit = 25, K5
#define GPIO_K6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,26)  //Port = 2, bit = 26, K6

#endif // _BITBAND_IO_H_
ARM Information Center
 
Последнее редактирование:

Geniuser

New member
При старте устройства требуется определить состояние кнопки (пина), если это делать в функции main.c, то задержка полсекунды, состояние кнопки уже не актуально. По дизассемблеру определил, что первая редактируемая функция до вызова main.с в SDK это DiagPrintf в файле low_level_io.c , добавил туда в начало функции код с user_init_func

low_level_io.c

Код:
extern void (*user_init_func) (void);

u32
DiagPrintf(
    IN  const char *fmt, ...
)
{
        if (user_init_func != NULL) (*user_init_func)();

    if(disablePrintf == TRUE)    return _TRUE;
 
    (void)VSprintf(0, fmt, ((const int *)&fmt)+1);
    return _TRUE;
}
main.c

Код:
void (*user_init_func)(void) = work_start;
__no_init volatile uint32_t btn;

void work_start(void)
{
    taskDISABLE_INTERRUPTS();
    user_init_func = NULL;
    disablePrintf = TRUE;  
    // Init button   
    gpio_init(&gpio_btn, GPIO_nBTN);
    gpio_dir(&gpio_btn, PIN_INPUT);    // Direction: Input
    gpio_mode(&gpio_btn, PullUp);     // PullUp
    btn = gpio_read(&gpio_btn);
    gpio_deinit(&gpio_btn, GPIO_nBTN);
    disablePrintf = FALSE;
    taskENABLE_INTERRUPTS();
}

void main(void)
{
// Init button
    gpio_init(&gpio_btn, GPIO_nBTN);
    gpio_dir(&gpio_btn, PIN_INPUT);    // Direction: Input
    gpio_mode(&gpio_btn, PullUp);     // PullUp

 
     if (btn == 1)
     {
            // Если кнопка (не) нажата при старте
     }

}

Вместе с Jtag работает, как только запускаю код без отладки - выдает Хард Фолт.

Код:
ROM Version: 0.3

Build ToolChain Version: gcc version 4.8.3 (Realtek ASDK-4.8.3p1 Build 2003)

=========================================================
Check boot type form eFuse
SPI Initial
Image1 length: 0x3a18, Image Addr: 0x10000bc8
Image1 Validate OK, Going jump to Image1
BOOT from Flash:YES
SPI calibration
Find the avaiable window
Baud:2; auto_length:0; Delay start:0; Delay end:63
[SPIF Err]SpicNVMCalStore: The flash memory(@0x9088 = 0x1310002) is not able to
===== Enter Image 1 ====!!
SPI calibration
Find the avaiable window
Baud:1; auto_length:11; Delay start:0; Delay end:63
[SPIF Err]SpicNVMCalStore: The flash memory(@0x90b8 = 0x1311101) is not able to
be write, Erase it first!!
load NEW fw 0
Flash Image2:Addr 0xb000, Len 263860, Load to SRAM 0x10006000
No Image3
Img2 Sign: RTKWin, InfaStart @ 0x10006051
RTL8195A[HAL]: Hard Fault Error!!!!
RTL8195A[HAL]: R0 = 0x0
RTL8195A[HAL]: R1 = 0x0
RTL8195A[HAL]: R2 = 0xe
RTL8195A[HAL]: R3 = 0x10047a60
RTL8195A[HAL]: R12 = 0x1c
RTL8195A[HAL]: LR = 0xd87d
RTL8195A[HAL]: PC = 0xe
RTL8195A[HAL]: PSR = 0x40000200
RTL8195A[HAL]: BFAR = 0x8
RTL8195A[HAL]: CFSR = 0x20000
RTL8195A[HAL]: HFSR = 0x40000000
RTL8195A[HAL]: DFSR = 0x0
RTL8195A[HAL]: AFSR = 0x0
RTL8195A[HAL]: PriMask 0x1
RTL8195A[HAL]: BasePri 0x0
RTL8195A[HAL]: SVC priority: 0x00
RTL8195A[HAL]: PendSVC priority: 0x00
RTL8195A[HAL]: Systick priority: 0x00
Опытным путём обнаружил, что если проинициализировать глобальную переменную, то её значение изменённое до main в work_start не сохраняется, поэтому пришлось делать __no_init btn и повторять gpio_init(&gpio_btn). Ворос как сделать правильно, чтобы SDK не рассыпалось?
 
Последнее редактирование:

pvvx

Активный участник сообщества
Ворос как сделать правильно, чтобы SDK не рассыпалось?
Включить функцию опроса что там вам надо в bootloader. Его исходники даны. Как один из множества возможных вариантов: Вставляете в BootLoader свою функцию, которая определяет и записывает какие-то нужные значения (хоть килобайты) по абсолютному адресу в области данных BootLoader-a до границы __ram_heap1_start__. Описываете эти переменные в *.ld и по загрузке любого выбранного приложения с SDK работаете с ними.
Вариантов ещё много, но всё зависит от того, что вам надо получить, как и для чего...
Кнопки и пины, ответственные за всякие Wake UP из разных режимов sleep имеют свои регистры статусов и событий - флагов и причин просыпания... Часть устройств, ответственных за просыпание из разных режимов sleep имеют и прерывания... как и назначаемые пины просыпания из DeepSleep().
Никто, кроме вас не знает, что вы там пытаетесь определить - может хотите фиксировать причину подачи питания на чип?
С удержанным RESET проц жрет больше чем в DeepSleep() или ожидания активации по уровню на пине... та и в текущих версиях BootLoader грузит разные прошивки на выбор по уровню на пинах...
 
Последнее редактирование:

Geniuser

New member
Здравствуйте,
столкнулся с такой проблемой
в разных местах программы делаю выключение по кнопке (если устройство при этом заряжается, то вместо выключения применяется рестарт. Пробовал 2-мя способами sys_reset() и watchdog, поведение одинаковое - рестарт происходит. Однако в разных местах программы он происходит по-разному:
либо так

Код:
=========================================================

ROM Version: 0.3

Build ToolChain Version: gcc version 4.8.3 (Realtek ASDK-4.8.3p1 Build 2003)

=========================================================
Check boot type form eFuse
SPI Initial
Image1 length: 0x3a18, Image Addr: 0x10000bc8
Image1 Validate OK, Going jump to Image1
BOOT from Flash:YES
===== Enter Image 1 ====

load NEW fw 0
Flash Image2:Addr 0xb000, Len 308036, Load to SRAM 0x10006000
No Image3
Img2 Sign: RTKWin, InfaStart @ 0x10006051
===== Enter Image 2 ====
либо вот так
Код:
=========================================================

ROM Version: 0.3

Build ToolChain Version: gcc version 4.8.3 (Realtek ASDK-4.8.3p1 Build 2003)

=========================================================
Check boot type form eFuse
SPI Initial
Image1 length: 0x3a18, Image Addr: 0x10000bc8
Image1 Validate OK, Going jump to Image1
BOOT from Flash:YES
===== Enter Image 1 ====

load OLD fw 1
Flash Image2:Addr 0x80000, Len 305844, Load to SRAM 0x10006000
No Image3
Img2 Sign: RTKWin, InfaStart @ 0x10006051
===== Enter Image 2 ====
Во втором случае грузится предыдущая версия прошивки OTA.
Раскопал по этому вопросу такую информацию:
First RTL-00 module tests - RTL8710 Community Forum
PINE64 - Firmware Recovery
Прошиваю через JTAG и несколько раз было по OTA.

Там упоминается некая ножка FLASH и механизм отката прошивки. В документации ничего не описано по этой теме. Предполагаю, что столкнулся с этой проблемой. Какая-то ножка при старте заставляет грузится старую прошивку. Как узнать какая ножка? И как механизм работает, как можно отключить, чтобы всегда грузилась новая прошивка?
 

sharikov

Active member
Там упоминается некая ножка FLASH и механизм отката прошивки. В документации ничего не описано по этой теме. Предполагаю, что столкнулся с этой проблемой. Какая-то ножка при старте заставляет грузится старую прошивку. Как узнать какая ножка? И как механизм работает, как можно отключить, чтобы всегда грузилась новая прошивка?
Это уже обсуждалось.
Номера ножек записаны в секторе system data
https://esp8266.ru/forum/threads/rtl871x-flash-memory-map.2117/#post-30627
Какую прошивку грузить выбирается в rtl_boot.c
 

Geniuser

New member
Это уже обсуждалось.
Номера ножек записаны в секторе system data
https://esp8266.ru/forum/threads/rtl871x-flash-memory-map.2117/#post-30627
Какую прошивку грузить выбирается в rtl_boot.c
Огромное спасибо, а не подскажете какие настройки ножек FLASH, отвечающих за загрузку old и new image по умолчанию?
 

Geniuser

New member
Выполнил в коде программы:

Код:
unsigned int tmp = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_DATA_ADDR + 0x08); // config data + 8
    DiagPrintf("\r\nFLASH_KEY: 0x%08X\r\n", tmp);
Получил значение FLASH_KEY: 0x00000000

Получается по-умолчанию FLASH ножка GA0? Но у меня состояние этой ножки не меняется при перезагрузке, однако грузятся разные прошивки.
Эту ножку я использую как SPI1_MISO, есть подозрение, что если SPI инициализирован, перед рестартом, то грузится одна прошивка, а если не инициализирован (деинициализирован), то другая.
Причем от процедуры рестарта это не зависит (watch_dog, sys_reset, ota_platform_reset). Пока нет ясности в этом вопросе.
 
Сверху Снизу