загрузчик mik32 для альфа-версии bsp arduino ide
This commit is contained in:
parent
dd1e920f05
commit
bd225dbabe
39
include/README
Normal file
39
include/README
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
This directory is intended for project header files.
|
||||||
|
|
||||||
|
A header file is a file containing C declarations and macro definitions
|
||||||
|
to be shared between several project source files. You request the use of a
|
||||||
|
header file in your project source file (C, C++, etc) located in `src` folder
|
||||||
|
by including it, with the C preprocessing directive `#include'.
|
||||||
|
|
||||||
|
```src/main.c
|
||||||
|
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Including a header file produces the same results as copying the header file
|
||||||
|
into each source file that needs it. Such copying would be time-consuming
|
||||||
|
and error-prone. With a header file, the related declarations appear
|
||||||
|
in only one place. If they need to be changed, they can be changed in one
|
||||||
|
place, and programs that include the header file will automatically use the
|
||||||
|
new version when next recompiled. The header file eliminates the labor of
|
||||||
|
finding and changing all the copies as well as the risk that a failure to
|
||||||
|
find one copy will result in inconsistencies within a program.
|
||||||
|
|
||||||
|
In C, the usual convention is to give header files names that end with `.h'.
|
||||||
|
It is most portable to use only letters, digits, dashes, and underscores in
|
||||||
|
header file names, and at most one dot.
|
||||||
|
|
||||||
|
Read more about using header files in official GCC documentation:
|
||||||
|
|
||||||
|
* Include Syntax
|
||||||
|
* Include Operation
|
||||||
|
* Once-Only Headers
|
||||||
|
* Computed Includes
|
||||||
|
|
||||||
|
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||||
46
lib/README
Normal file
46
lib/README
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
|
||||||
|
This directory is intended for project specific (private) libraries.
|
||||||
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
|
The source code of each library should be placed in a an own separate directory
|
||||||
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|
|--lib
|
||||||
|
| |
|
||||||
|
| |--Bar
|
||||||
|
| | |--docs
|
||||||
|
| | |--examples
|
||||||
|
| | |--src
|
||||||
|
| | |- Bar.c
|
||||||
|
| | |- Bar.h
|
||||||
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
|
| |
|
||||||
|
| |--Foo
|
||||||
|
| | |- Foo.c
|
||||||
|
| | |- Foo.h
|
||||||
|
| |
|
||||||
|
| |- README --> THIS FILE
|
||||||
|
|
|
||||||
|
|- platformio.ini
|
||||||
|
|--src
|
||||||
|
|- main.c
|
||||||
|
|
||||||
|
and a contents of `src/main.c`:
|
||||||
|
```
|
||||||
|
#include <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
|
libraries scanning project source files.
|
||||||
|
|
||||||
|
More information about PlatformIO Library Dependency Finder
|
||||||
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
16
platformio.ini
Normal file
16
platformio.ini
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
; PlatformIO Project Configuration File
|
||||||
|
;
|
||||||
|
; Build options: build flags, source filter
|
||||||
|
; Upload options: custom upload port, speed and extra flags
|
||||||
|
; Library options: dependencies, extra library storages
|
||||||
|
; Advanced options: extra scripting
|
||||||
|
;
|
||||||
|
; Please visit documentation for the other options and examples
|
||||||
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
|
|
||||||
|
[env:mik32v2]
|
||||||
|
platform = MIK32
|
||||||
|
board = mik32v2
|
||||||
|
framework = framework-mik32v2-sdk
|
||||||
|
board_debug.ldscript = eeprom
|
||||||
409
src/bootloader.c
Normal file
409
src/bootloader.c
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
#include "mik32_hal_pcc.h"
|
||||||
|
#include "mik32_hal_spifi_w25.h"
|
||||||
|
|
||||||
|
#include "power_manager.h"
|
||||||
|
#include "uart.h"
|
||||||
|
#include "pad_config.h"
|
||||||
|
#include "mcu32_memory_map.h"
|
||||||
|
|
||||||
|
#include "riscv_csr_encoding.h"
|
||||||
|
#include "csr.h"
|
||||||
|
|
||||||
|
#include "string.h"
|
||||||
|
|
||||||
|
#define JALR_TO_SPIFI() \
|
||||||
|
asm volatile( "la ra, 0x80000000\n\t" \
|
||||||
|
"jalr ra" \
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#define ACK 0x0F /* Подтверждение */
|
||||||
|
#define NACK 0xF0 /* Нет подтверждения */
|
||||||
|
#define MAX_PACKAGE_SIZE 256 /* максимальный размер пакета */
|
||||||
|
#define TIMEOUT_VALUE 1000000 /* Время ожидания загрузчика до прыжка по умолчанию в RAM 1000000 */
|
||||||
|
|
||||||
|
/* Виды команд */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
PACKAGE_SIZE = 0x30, /* Команда размера пакета */
|
||||||
|
SEND_PACKAGE = 0x60, /* Команда отправить пакет */
|
||||||
|
FULL_ERASE = 0xFE /* Команда стирания spifi*/
|
||||||
|
} BotloaderComand;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SPIFI_ADDRESS = 0x80000000
|
||||||
|
} AddressMemory;
|
||||||
|
|
||||||
|
/* Виды ошибок */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ERROR_NONE = 0,
|
||||||
|
ERROR_TIMEOUT = 1, // Время ожидания истекло
|
||||||
|
} Bootloader_error;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t* address; // Адрес для записи присылаемых байт
|
||||||
|
uint16_t size_package; // Размер пакета
|
||||||
|
uint8_t error;
|
||||||
|
uint8_t command; // Текущая принятая загрузчиком команда
|
||||||
|
} Bootloader_attributes;
|
||||||
|
|
||||||
|
Bootloader_attributes hBootloader = {(uint8_t*) SPIFI_ADDRESS, MAX_PACKAGE_SIZE, ERROR_NONE, 0};
|
||||||
|
uint32_t timeout = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* Инициализация UART */
|
||||||
|
void Bootloader_UART_Init()
|
||||||
|
{
|
||||||
|
PM->CLK_APB_P_SET = PM_CLOCK_APB_P_UART_0_M; // Включение тактирования UART0
|
||||||
|
|
||||||
|
PAD_CONFIG->PORT_0_CFG |= (0b01 << (5 << 1)) | (0b01 << (6 << 1)); // Настройка выводов PORT0.5 и PORT0.6
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Настройки USART:
|
||||||
|
* Асинхронный режим. Включен RX и TX;
|
||||||
|
* Кадр: 8 бит данных, бит четности выключен, 1 стоп бит;
|
||||||
|
* Байт LSB - первый бит нулевой.
|
||||||
|
*/
|
||||||
|
UART_0->CONTROL1 = 0;
|
||||||
|
UART_0->CONTROL2 = 0;
|
||||||
|
UART_0->CONTROL3 = 0;
|
||||||
|
UART_0->DIVIDER = 138; /* Baudrate = 230400 */
|
||||||
|
UART_0->FLAGS = 0xFFFFFFFF;
|
||||||
|
UART_0->CONTROL1 = UART_CONTROL1_RE_M | UART_CONTROL1_TE_M | UART_CONTROL1_UE_M;
|
||||||
|
|
||||||
|
/* Ожидание флагов готовности RX и TX */
|
||||||
|
while (!(UART_0->FLAGS & (UART_FLAGS_REACK_M | UART_FLAGS_TEACK_M)))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bootloader_UART_Deinit()
|
||||||
|
{
|
||||||
|
UART_0->CONTROL1 = 0;
|
||||||
|
UART_0->CONTROL2 = 0;
|
||||||
|
UART_0->CONTROL3 = 0;
|
||||||
|
UART_0->DIVIDER = 0x0000; // сброс бодрейта
|
||||||
|
UART_0->FLAGS = 0xFFFFFFFF; // сброс всех флагов
|
||||||
|
UART_0->TXDATA = 0x00;
|
||||||
|
|
||||||
|
PAD_CONFIG->PORT_0_CFG &= (0b00 << (5 << 1)) | (0b00 << (6 << 1)); // Настройка выводов PORT0.5 и PORT0.6
|
||||||
|
|
||||||
|
PM->CLK_APB_P_SET &= !PM_CLOCK_APB_P_UART_0_M; // Выключение тактирования UART0
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Отправить байт */
|
||||||
|
void Bootloader_UART_WriteByte(uint16_t Write_Byte)
|
||||||
|
{
|
||||||
|
UART_0->TXDATA = Write_Byte;
|
||||||
|
/* Ожидаем успешную передачу */
|
||||||
|
while (!(UART_0->FLAGS & UART_FLAGS_TC_M))
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ожидание и считывание байта */
|
||||||
|
uint16_t Bootloader_UART_ReadByte()
|
||||||
|
{
|
||||||
|
timeout = 0;
|
||||||
|
while ((!(UART_0->FLAGS & UART_FLAGS_RXNE_M)) && (timeout != TIMEOUT_VALUE))
|
||||||
|
{
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == TIMEOUT_VALUE)
|
||||||
|
{
|
||||||
|
hBootloader.error = ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint16_t)UART_0->RXDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Обработчик ошибок */
|
||||||
|
void Bootloader_ErrorHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
switch (hBootloader.error)
|
||||||
|
{
|
||||||
|
case ERROR_TIMEOUT:
|
||||||
|
Bootloader_UART_WriteByte(NACK);
|
||||||
|
if (UART_0->FLAGS & UART_FLAGS_ORE_M)
|
||||||
|
{
|
||||||
|
UART_0->FLAGS |= UART_FLAGS_ORE_M;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
hBootloader.error = ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPIFI_HandleTypeDef spifi = {.Instance = SPIFI_CONFIG};
|
||||||
|
|
||||||
|
uint8_t erase_chip(SPIFI_HandleTypeDef *spifi)
|
||||||
|
{
|
||||||
|
const uint32_t cmd_chip_erase =
|
||||||
|
SPIFI_DIRECTION_INPUT |
|
||||||
|
SPIFI_CONFIG_CMD_INTLEN(0) |
|
||||||
|
SPIFI_CONFIG_CMD_FIELDFORM(SPIFI_FIELDFORM_ALL_SERIAL) |
|
||||||
|
SPIFI_CONFIG_CMD_FRAMEFORM(SPIFI_FRAMEFORM_OPCODE) |
|
||||||
|
SPIFI_CONFIG_CMD_OPCODE(0xC7); //CHIP_ERASE = 0x60 или 0xC7
|
||||||
|
HAL_SPIFI_W25_WriteEnable(spifi);
|
||||||
|
uint8_t stat = HAL_SPIFI_SendCommand_LL(spifi, cmd_chip_erase, 0, 0, 0, 0, 0, HAL_SPIFI_TIMEOUT);
|
||||||
|
stat = HAL_SPIFI_W25_WaitBusy(spifi, 10000000); // SPIFI_W25_PROGRAM_BUSY = 100000
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Загрузить данные пакета в RAM */
|
||||||
|
#define SIZE_4K 4096
|
||||||
|
void Bootloader_LoadArrayInRam(uint8_t uart_data[])
|
||||||
|
{
|
||||||
|
static uint32_t relative_write_address;
|
||||||
|
|
||||||
|
if ((relative_write_address % SIZE_4K) == 0)
|
||||||
|
HAL_SPIFI_W25_SectorErase4K(&spifi, relative_write_address);
|
||||||
|
|
||||||
|
HAL_SPIFI_W25_PageProgram(&spifi, (uint32_t)hBootloader.address, hBootloader.size_package, uart_data);
|
||||||
|
hBootloader.address += hBootloader.size_package;
|
||||||
|
relative_write_address += hBootloader.size_package;
|
||||||
|
}
|
||||||
|
|
||||||
|
// разметка строки в хекс-файле
|
||||||
|
#define BYTE_COUNT_POS 0 // индекс счетчика байт данных
|
||||||
|
#define ADDRES_POS 1 // индекс адреса
|
||||||
|
#define ADDRES_QTY 2 // количество байт адреса
|
||||||
|
#define RECORD_TYPE_POS 3 // индекс типа записи
|
||||||
|
#define DATA_POS 4 // индекс начала данных в команде
|
||||||
|
|
||||||
|
// типы записей в хекс-фйле
|
||||||
|
#define REC_TYPE_DATA 0x00
|
||||||
|
#define REC_TYPE_EOF 0x01
|
||||||
|
#define REC_TYPE_EXT_LIN_ADDR 0x04
|
||||||
|
|
||||||
|
uint32_t abs_addr = 0; // адрес из хекса
|
||||||
|
uint32_t rel_addr = 0; // адрес от начала области spifi, по нему определяем, надо ли стирать сектор и какой именно
|
||||||
|
uint8_t page_data[256] = {0}; // сюда собираем распарсенные данные из хекса
|
||||||
|
uint16_t page_fill_size = 0; // счетчик, сколько заполнно в page_data. когда page_data заполнена до конца - будем записывать в spifi
|
||||||
|
|
||||||
|
void go_to_spifi();
|
||||||
|
|
||||||
|
void mem_write()
|
||||||
|
{
|
||||||
|
// если адрес дошел до начала нового сектора, стираем новый сектор
|
||||||
|
rel_addr = (uint32_t)(hBootloader.address) - 0x80000000;
|
||||||
|
if ((rel_addr % SIZE_4K) == 0)
|
||||||
|
HAL_SPIFI_W25_SectorErase4K(&spifi, rel_addr);
|
||||||
|
|
||||||
|
// записываем страницу в 256 байт в spifi
|
||||||
|
HAL_SPIFI_W25_PageProgram(&spifi, (uint32_t)hBootloader.address, 256, page_data);
|
||||||
|
// увеличиваем адреса, по которым писать и стирать
|
||||||
|
hBootloader.address += 256;
|
||||||
|
// обнуляем буфер и счетчик заполнения буфера
|
||||||
|
page_fill_size = 0;
|
||||||
|
memset(page_data, 0, 256);
|
||||||
|
}
|
||||||
|
void Bootloader_parseHexAndLoadInMemory(uint8_t rx_data[])
|
||||||
|
{
|
||||||
|
// из принятых данных вытаскиваем тип записи
|
||||||
|
uint8_t rec_type = rx_data[RECORD_TYPE_POS];
|
||||||
|
switch (rec_type)
|
||||||
|
{
|
||||||
|
case REC_TYPE_EXT_LIN_ADDR:
|
||||||
|
// если так получилось, что нам слали данные, буфер на 256 не заполнился, а тут прилетела команда смены адреса, то пишем сколько есть
|
||||||
|
if (page_fill_size != 0)
|
||||||
|
mem_write();
|
||||||
|
// собираем адрес, с которого начинаем писать из данных команды смены адреса. нам присылают только 2 старших байта адреса
|
||||||
|
abs_addr = (rx_data[DATA_POS] << 24) + (rx_data[DATA_POS+1] << 16);
|
||||||
|
hBootloader.address = (uint8_t*)abs_addr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REC_TYPE_DATA:
|
||||||
|
// перекладываем из приемного буфера данные команды в буфер для записи
|
||||||
|
memcpy(&page_data[page_fill_size], &rx_data[DATA_POS], rx_data[BYTE_COUNT_POS]);
|
||||||
|
// указываем, на сколько заполнился буфер
|
||||||
|
page_fill_size += rx_data[BYTE_COUNT_POS];
|
||||||
|
// если пора записывать целую страницу - пишемм
|
||||||
|
if (page_fill_size == 256)
|
||||||
|
mem_write();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REC_TYPE_EOF: // конец прошивки
|
||||||
|
Bootloader_UART_WriteByte(ACK);
|
||||||
|
// если есть недозаполненная страница, записываем ее как есть
|
||||||
|
if (page_fill_size != 0)
|
||||||
|
mem_write();
|
||||||
|
// и идем в записанную программу
|
||||||
|
go_to_spifi();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t uart_data[MAX_PACKAGE_SIZE] = {0}; // Массив данных из полученного пакета
|
||||||
|
void Bootloader_UART_ReadPackage()
|
||||||
|
{
|
||||||
|
for (uint32_t counter = 0; counter < hBootloader.size_package; counter++)
|
||||||
|
{
|
||||||
|
timeout = 0;
|
||||||
|
while ((!(UART_0->FLAGS & UART_FLAGS_RXNE_M)) && (timeout != TIMEOUT_VALUE)) // Ожидание байта пакета
|
||||||
|
{
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == TIMEOUT_VALUE)
|
||||||
|
{
|
||||||
|
hBootloader.error = ERROR_TIMEOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart_data[counter] = UART_0->RXDATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hBootloader.error)
|
||||||
|
{
|
||||||
|
Bootloader_parseHexAndLoadInMemory(uart_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bootloader_Commands()
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
hBootloader.command = Bootloader_UART_ReadByte(); // Ожидание и считывание команды
|
||||||
|
if (hBootloader.error)
|
||||||
|
{
|
||||||
|
Bootloader_ErrorHandler(); // Обработчик ошибок
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (hBootloader.command)
|
||||||
|
{
|
||||||
|
case PACKAGE_SIZE:
|
||||||
|
Bootloader_UART_WriteByte(ACK); // Подтвердить команду
|
||||||
|
hBootloader.size_package = Bootloader_UART_ReadByte() + 1; // Прочитать размер пакета
|
||||||
|
Bootloader_UART_WriteByte(ACK); // Подтвердить
|
||||||
|
|
||||||
|
break;
|
||||||
|
case SEND_PACKAGE:
|
||||||
|
Bootloader_UART_WriteByte(ACK); // Подтвердить команду
|
||||||
|
Bootloader_UART_ReadPackage(); // Получить пакет и скопировать его в RAM
|
||||||
|
|
||||||
|
if (hBootloader.error)
|
||||||
|
{
|
||||||
|
Bootloader_ErrorHandler(); // Обработчик ошибок
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bootloader_UART_WriteByte(ACK); // Подтвердить считывание и копирования пакета в RAM
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FULL_ERASE:
|
||||||
|
if (erase_chip(&spifi) != HAL_OK)
|
||||||
|
Bootloader_UART_WriteByte(NACK);
|
||||||
|
else
|
||||||
|
Bootloader_UART_WriteByte(ACK);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SystemClock_Config();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
SystemClock_Config();
|
||||||
|
HAL_SPIFI_MspInit(&spifi);
|
||||||
|
HAL_SPIFI_Reset(&spifi);
|
||||||
|
|
||||||
|
|
||||||
|
Bootloader_UART_Init(); // Инициализация UART. НАстройка выводов и тактирования
|
||||||
|
|
||||||
|
timeout = 0;
|
||||||
|
while ((!(UART_0->FLAGS & UART_FLAGS_RXNE_M)) && (timeout != TIMEOUT_VALUE)) // Загрузчик ожидает команду
|
||||||
|
{
|
||||||
|
timeout++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout == TIMEOUT_VALUE)
|
||||||
|
{
|
||||||
|
go_to_spifi();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Bootloader_Commands(); // Обработка и ожидания команд
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* code */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemClock_Config(void)
|
||||||
|
{
|
||||||
|
PCC_InitTypeDef PCC_OscInit = {0};
|
||||||
|
|
||||||
|
PCC_OscInit.OscillatorEnable = PCC_OSCILLATORTYPE_ALL;
|
||||||
|
PCC_OscInit.FreqMon.OscillatorSystem = PCC_OSCILLATORTYPE_OSC32M;
|
||||||
|
PCC_OscInit.FreqMon.ForceOscSys = PCC_FORCE_OSC_SYS_UNFIXED;
|
||||||
|
PCC_OscInit.FreqMon.Force32KClk = PCC_FREQ_MONITOR_SOURCE_OSC32K;
|
||||||
|
PCC_OscInit.AHBDivider = 0;
|
||||||
|
PCC_OscInit.APBMDivider = 0;
|
||||||
|
PCC_OscInit.APBPDivider = 0;
|
||||||
|
PCC_OscInit.HSI32MCalibrationValue = 128;
|
||||||
|
PCC_OscInit.LSI32KCalibrationValue = 128;
|
||||||
|
PCC_OscInit.RTCClockSelection = PCC_RTC_CLOCK_SOURCE_AUTO;
|
||||||
|
PCC_OscInit.RTCClockCPUSelection = PCC_CPU_RTC_CLOCK_SOURCE_OSC32K;
|
||||||
|
HAL_PCC_Config(&PCC_OscInit);
|
||||||
|
}
|
||||||
|
void SPIFI_disableDataCache(SPIFI_MemoryModeConfig_HandleTypeDef *spifi)
|
||||||
|
{
|
||||||
|
spifi->Instance->CTRL |= SPIFI_CONFIG_CTRL_D_CACHE_DIS_M;
|
||||||
|
}
|
||||||
|
void SPIFI_Init()
|
||||||
|
{
|
||||||
|
HAL_SPIFI_MspInit(&spifi);
|
||||||
|
HAL_SPIFI_Reset(&spifi);
|
||||||
|
|
||||||
|
uint8_t sreg1 = HAL_SPIFI_W25_ReadSREG(&spifi, W25_SREG1);
|
||||||
|
uint8_t sreg2 = HAL_SPIFI_W25_ReadSREG(&spifi, W25_SREG2);
|
||||||
|
|
||||||
|
|
||||||
|
/*В Winbond для выставления QE используется команда 0x01 в 1-м бите 2го статус регистра.
|
||||||
|
Количество промежуточных данных в команде 4READ = 0xEB равно 3 байта (в cmd_mem)*/
|
||||||
|
HAL_SPIFI_W25_WriteSREG(&spifi, sreg1, sreg2 | (1 << 1)); // ? HAL_SPIFI_W25_QuadEnable(&spifi);
|
||||||
|
|
||||||
|
SPIFI_MemoryCommandTypeDef cmd_mem = {
|
||||||
|
.OpCode = 0xEB,
|
||||||
|
.FieldForm = SPIFI_CONFIG_CMD_FIELDFORM_OPCODE_SERIAL,
|
||||||
|
.FrameForm = SPIFI_CONFIG_CMD_FRAMEFORM_OPCODE_3ADDR,
|
||||||
|
.InterimData = 0,
|
||||||
|
.InterimLength = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
SPIFI_MemoryModeConfig_HandleTypeDef spifi_mem = {
|
||||||
|
.Instance = spifi.Instance,
|
||||||
|
.CacheEnable = SPIFI_CACHE_ENABLE,
|
||||||
|
.CacheLimit = 0x00010000,
|
||||||
|
.Command = cmd_mem,
|
||||||
|
};
|
||||||
|
|
||||||
|
HAL_SPIFI_MemoryMode_Init(&spifi_mem);
|
||||||
|
// SPIFI_disableDataCache(&spifi_mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void go_to_spifi()
|
||||||
|
{
|
||||||
|
Bootloader_UART_Deinit();
|
||||||
|
SPIFI_Init();
|
||||||
|
write_csr(mtvec, 0x80000000);
|
||||||
|
JALR_TO_SPIFI();
|
||||||
|
}
|
||||||
11
test/README
Normal file
11
test/README
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
This directory is intended for PlatformIO Test Runner and project tests.
|
||||||
|
|
||||||
|
Unit Testing is a software testing method by which individual units of
|
||||||
|
source code, sets of one or more MCU program modules together with associated
|
||||||
|
control data, usage procedures, and operating procedures, are tested to
|
||||||
|
determine whether they are fit for use. Unit testing finds problems early
|
||||||
|
in the development cycle.
|
||||||
|
|
||||||
|
More information about PlatformIO Unit Testing:
|
||||||
|
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||||
Loading…
Reference in New Issue
Block a user