ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
21 ноября
1263998 Топик полностью
LightElf (01.12.2022 12:57 - 08.12.2022 22:33, просмотров: 727) ответил Гyдвин на Наткнулся на пример реализации пользовательского загрузчика с перенаправлением векторов у китайцев. Без танцев с бубнами с корявой поддержкой этого дела в чипе. Такой подход мне нравится гораздо больше. Ну и сохраняется встроенный bootloader для штатной прошивки через usb/uart если что. Пример проверил - работает. Прикрепил...
UPD. Исправил размер массива - слишком большой создавался. Если интересно - я разобрался со штатным механизмом, вполне нормально работает. 

Переключение из бута в аппкод:

typedef void (*jump_code)(void);
static const uint16_t jump_app[] =
{
// R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1
0x2140, 0x0409, 0x3110, 0x0209, 0x3140, 0x2057, 0x7008,
// R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2
0x20A8, 0x7008,
// R8_RESET_STATUS = RB_ROM_CODE_OFS
0x2010, 0x7108,
// R8_RST_WDOG_CTRL = RB_SOFTWARE_RESET
0x2001, 0x7188,
// ISB
0xF3BF, 0x8F6F,
// R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG0
0x2000, 0x7008,
// for (;;);
0xE7FE
};
void app_start(void)
{
volatile uint16_t codebuf[sizeof(jump_app)/sizeof(jump_app[0])];
__disable_interrupt();
for (int i=0; i < sizeof(jump_app)/sizeof(jump_app[0]); i++)
{
codebuf[i] = jump_app[i];
}
((jump_code)(1 | (uint32_t)codebuf))();
}


Переключение назад в бут:

void boot_start(void) 
{
uint32_t t;
__disable_interrupt();
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
// разрешаем просыпание по событию RTC
R8_SLP_WAKE_CTRL |= RB_SLP_RTC_WAKE;
R16_POWER_PLAN = RB_PWR_PLAN_EN | RB_PWR_MUST_0010;
R8_SAFE_ACCESS_SIG = 0;
// берем текущее время RTC
do {
t = R32_RTC_CNT_32K;
} while ( t != R32_RTC_CNT_32K );
// добавляем 10 тиков
t = t + 10;
// учтем возможность переполнения
if (t > 0xA8C00000)
{
t -= 0xA8C00000;
}
// округлим вверх
if (t & 0xFFFF)
{
t += 0x10000;
}
// сбрасываем флаги (иначе не уснем)
R8_RTC_FLAG_CTRL = RB_RTC_TRIG_CLR | RB_RTC_TMR_CLR;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
// заряжаем момент просыпания
R32_RTC_TRIG = t;
// включаем будильник
R8_RTC_MODE_CTRL = RB_RTC_TRIG_EN | 0x0f;
R8_SAFE_ACCESS_SIG = 0;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
// выключаем PLL и кварц
R16_CLK_SYS_CFG = 5;
R8_SAFE_ACCESS_SIG = 0;
// падаем в shutdown
__SEV();
__WFE();
__WFE();
// когда RTC досчитает, произойдет глобальный сброс
while(1);
}
Не надо делать мне как лучше, оставьте мне как хорошо