mirror of
https://github.com/pine64/blisp.git
synced 2025-01-01 11:20:13 +00:00
WIP
This commit is contained in:
parent
29a36a2d7b
commit
f7964a9cb2
@ -5,6 +5,13 @@
|
||||
|
||||
#include "blisp_chip.h"
|
||||
|
||||
struct blisp_segment_header {
|
||||
uint32_t dest_addr;
|
||||
uint32_t length;
|
||||
uint32_t reserved;
|
||||
uint32_t crc32;
|
||||
};
|
||||
|
||||
struct blisp_device {
|
||||
struct blisp_chip* chip;
|
||||
void* serial_port;
|
||||
@ -24,6 +31,12 @@ int32_t blisp_device_init(struct blisp_device* device, struct blisp_chip* chip);
|
||||
int32_t blisp_device_open(struct blisp_device* device, const char* port_name);
|
||||
int32_t blisp_device_handshake(struct blisp_device* device);
|
||||
int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info);
|
||||
int32_t blisp_device_load_boot_header(struct blisp_device* device, uint8_t* boot_header);
|
||||
int32_t blisp_device_load_segment_header(struct blisp_device* device, struct blisp_segment_header* segment_header);
|
||||
int32_t blisp_device_load_segment_data(struct blisp_device* device, uint8_t* segment_data, uint32_t segment_data_length);
|
||||
int32_t blisp_device_write_memory(struct blisp_device* device, uint32_t address, uint32_t value);
|
||||
int32_t blisp_device_check_image(struct blisp_device* device);
|
||||
int32_t blisp_device_run_image(struct blisp_device* device);
|
||||
void blisp_device_close(struct blisp_device* device);
|
||||
|
||||
#endif
|
@ -10,6 +10,7 @@ enum blisp_chip_type {
|
||||
|
||||
struct blisp_chip { // TODO: Move elsewhere?
|
||||
enum blisp_chip_type type;
|
||||
const char* type_str;
|
||||
bool usb_isp_available;
|
||||
};
|
||||
|
||||
|
145
lib/blisp.c
145
lib/blisp.c
@ -59,11 +59,11 @@ int32_t blisp_device_open(struct blisp_device* device, const char* port_name)
|
||||
uint32_t vid, pid;
|
||||
sp_get_port_usb_vid_pid(serial_port, &vid, &pid);
|
||||
device->is_usb = pid == 0xFFFF;
|
||||
if (device->is_usb) {
|
||||
device->current_baud_rate = 2000000;
|
||||
} else {
|
||||
// if (device->is_usb) {
|
||||
// device->current_baud_rate = 2000000;
|
||||
// } else {
|
||||
device->current_baud_rate = 500000;
|
||||
}
|
||||
// }
|
||||
sp_set_baudrate(serial_port, device->current_baud_rate);
|
||||
device->serial_port = serial_port;
|
||||
return 0;
|
||||
@ -76,8 +76,8 @@ int32_t blisp_send_command(struct blisp_device* device, uint8_t command, void* p
|
||||
|
||||
device->tx_buffer[0] = command;
|
||||
device->tx_buffer[1] = 0;
|
||||
device->tx_buffer[2] = (payload_size >> 8) & 0xFF;
|
||||
device->tx_buffer[3] = payload_size & 0xFF;
|
||||
device->tx_buffer[2] = payload_size & 0xFF;
|
||||
device->tx_buffer[3] = (payload_size >> 8) & 0xFF;
|
||||
if (add_checksum) {
|
||||
uint32_t checksum = 0;
|
||||
checksum += device->tx_buffer[2] + device->tx_buffer[3];
|
||||
@ -97,13 +97,28 @@ int32_t blisp_send_command(struct blisp_device* device, uint8_t command, void* p
|
||||
}
|
||||
|
||||
int32_t blisp_receive_response(struct blisp_device* device, bool expect_payload) {
|
||||
// TODO: Check checksum
|
||||
int ret;
|
||||
struct sp_port* serial_port = device->serial_port;
|
||||
ret = sp_blocking_read(serial_port, &device->rx_buffer[0], 2, 300);
|
||||
if (ret < 2) {
|
||||
return -1;
|
||||
} else if (device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
|
||||
if (expect_payload) {
|
||||
sp_blocking_read(serial_port, &device->rx_buffer[2], 2, 100);
|
||||
uint16_t data_length = (device->rx_buffer[3] << 8) | (device->rx_buffer[2]);
|
||||
sp_blocking_read(serial_port, &device->rx_buffer[0], data_length, 100);
|
||||
return data_length;
|
||||
}
|
||||
return 0;
|
||||
} else if (device->rx_buffer[0] == 'P' && device->rx_buffer[1] == 'D') {
|
||||
return -1;
|
||||
} else if (device->rx_buffer[0] == 'F' && device->rx_buffer[1] == 'L') {
|
||||
sp_blocking_read(serial_port, &device->rx_buffer[2], 2, 100);
|
||||
device->error_code = (device->rx_buffer[3] << 8) | (device->rx_buffer[2]);
|
||||
return -4; // Failed
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t blisp_device_handshake(struct blisp_device* device)
|
||||
@ -112,21 +127,27 @@ int32_t blisp_device_handshake(struct blisp_device* device)
|
||||
uint8_t handshake_buffer[600];
|
||||
struct sp_port* serial_port = device->serial_port;
|
||||
|
||||
if (device->is_usb) {
|
||||
sp_blocking_write(serial_port, "BOUFFALOLAB5555RESET\0\0", 22, 100);
|
||||
}
|
||||
uint32_t bytes_count = 0.003f * (float)device->current_baud_rate / 10.0f; // TODO: 0.003f is only for BL70X!
|
||||
if (bytes_count > 600) bytes_count = 600;
|
||||
memset(handshake_buffer, 'U', bytes_count);
|
||||
ret = sp_blocking_write(serial_port, handshake_buffer, bytes_count, 100);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
if (device->is_usb) {
|
||||
sp_blocking_write(serial_port, "BOUFFALOLAB5555RESET\0\0", 22,
|
||||
100);
|
||||
}
|
||||
|
||||
ret = sp_blocking_write(serial_port, handshake_buffer, bytes_count,
|
||||
100);
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 100);
|
||||
if (ret == 2 && device->rx_buffer[0] == 'O' && device->rx_buffer[1] == 'K') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ret = sp_blocking_read(serial_port, device->rx_buffer, 2, 100);
|
||||
if (ret < 2 || device->rx_buffer[0] != 'O' || device->rx_buffer[1] != 'K') {
|
||||
return -4; // didn't received response
|
||||
}
|
||||
return 0;
|
||||
return -4; // didn't received response
|
||||
}
|
||||
|
||||
int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boot_info* boot_info)
|
||||
@ -137,6 +158,94 @@ int32_t blisp_device_get_boot_info(struct blisp_device* device, struct blisp_boo
|
||||
if (ret < 0) return ret;
|
||||
|
||||
ret = blisp_receive_response(device, true);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
if (device->chip->type == BLISP_CHIP_BL70X) {
|
||||
memcpy(boot_info->boot_rom_version, &device->rx_buffer[0], 4); // TODO: Endianess
|
||||
memcpy(boot_info->chip_id, &device->rx_buffer[16], 8);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: Use struct instead of uint8_t*
|
||||
int32_t blisp_device_load_boot_header(struct blisp_device* device, uint8_t* boot_header)
|
||||
{
|
||||
int ret;
|
||||
ret = blisp_send_command(device, 0x11, boot_header, 176, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, false);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blisp_device_load_segment_header(struct blisp_device* device, struct blisp_segment_header* segment_header)
|
||||
{
|
||||
int ret;
|
||||
ret = blisp_send_command(device, 0x17, segment_header, 16, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, false);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blisp_device_load_segment_data(struct blisp_device* device, uint8_t* segment_data, uint32_t segment_data_length)
|
||||
{
|
||||
int ret;
|
||||
ret = blisp_send_command(device, 0x18, segment_data, segment_data_length, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, true); // TODO: Handle response
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blisp_device_check_image(struct blisp_device* device)
|
||||
{
|
||||
int ret;
|
||||
ret = blisp_send_command(device, 0x19, NULL, 0, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, false);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blisp_device_write_memory(struct blisp_device* device, uint32_t address, uint32_t value)
|
||||
{
|
||||
int ret;
|
||||
uint8_t payload[8];
|
||||
*(uint32_t*)(payload) = address;
|
||||
*(uint32_t*)(payload + 4) = value; // TODO: Endianness
|
||||
ret = blisp_send_command(device, 0x50, payload, 8, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, false);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t blisp_device_run_image(struct blisp_device* device)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (device->chip->type == BLISP_CHIP_BL70X) { // ERRATA
|
||||
ret = blisp_device_write_memory(device, 0x4000F100, 0x4E424845);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_device_write_memory(device, 0x4000F104, 0x22010000);
|
||||
if (ret < 0) return ret;
|
||||
// ret = blisp_device_write_memory(device, 0x40000018, 0x00000000);
|
||||
// if (ret < 0) return ret;
|
||||
ret = blisp_device_write_memory(device, 0x40000018, 0x00000002);
|
||||
if (ret < 0) return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = blisp_send_command(device, 0x1A, NULL, 0, false);
|
||||
if (ret < 0) return ret;
|
||||
ret = blisp_receive_response(device, false);
|
||||
if (ret < 0) return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,5 +2,6 @@
|
||||
|
||||
struct blisp_chip blisp_chip_bl70x = {
|
||||
.type = BLISP_CHIP_BL70X,
|
||||
.type_str = "bl70x",
|
||||
.usb_isp_available = true
|
||||
};
|
||||
|
@ -1,17 +1,42 @@
|
||||
#include "../cmd.h"
|
||||
#include "argtable3.h"
|
||||
#include <blisp.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
|
||||
#define REG_EXTENDED 1
|
||||
#define REG_ICASE (REG_EXTENDED << 1)
|
||||
|
||||
static struct arg_rex* cmd;
|
||||
static struct arg_file* binary_to_write;
|
||||
static struct arg_str* port_name;
|
||||
static struct arg_str* port_name, *chip_type;
|
||||
static struct arg_end* end;
|
||||
static void* cmd_write_argtable[4];
|
||||
static void* cmd_write_argtable[5];
|
||||
|
||||
ssize_t
|
||||
get_binary_folder(char* buffer, uint32_t buffer_size) {
|
||||
#ifdef __linux__
|
||||
readlink("/proc/self/exe", buffer, BUFSIZ); // TODO: Error handling
|
||||
char* pos = strrchr(buffer, '/');
|
||||
pos[0] = '\0';
|
||||
return pos - buffer;
|
||||
#else
|
||||
#error NOT IMPLEMENTED
|
||||
WCHAR path[MAX_PATH];
|
||||
GetModuleFileName(NULL, path, ARRAYSIZE(path));
|
||||
#endif
|
||||
}
|
||||
|
||||
void blisp_flash_firmware() {
|
||||
// TODO: We support currently only BL70X
|
||||
if (chip_type->count == 0 || strcmp(chip_type->sval[0], "bl70x") != 0) {
|
||||
fprintf(stderr, "Chip type is invalid.\n");
|
||||
return;
|
||||
}
|
||||
struct blisp_device device;
|
||||
uint32_t ret;
|
||||
ret = blisp_device_init(&device, &blisp_chip_bl70x);
|
||||
@ -28,9 +53,89 @@ void blisp_flash_firmware() {
|
||||
ret = blisp_device_handshake(&device);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "\nFailed to handshake with device.\n");
|
||||
return;
|
||||
goto exit1;
|
||||
}
|
||||
printf(" OK\n");
|
||||
printf(" OK\nGetting chip info...");
|
||||
struct blisp_boot_info boot_info;
|
||||
ret = blisp_device_get_boot_info(&device, &boot_info);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "\nFailed to get boot info.\n");
|
||||
goto exit1;
|
||||
}
|
||||
printf(" BootROM version %d.%d.%d.%d, ChipID: %02X%02X%02X%02X%02X%02X%02X%02X\n",
|
||||
boot_info.boot_rom_version[0],
|
||||
boot_info.boot_rom_version[1],
|
||||
boot_info.boot_rom_version[2],
|
||||
boot_info.boot_rom_version[3],
|
||||
boot_info.chip_id[0],
|
||||
boot_info.chip_id[1],
|
||||
boot_info.chip_id[2],
|
||||
boot_info.chip_id[3],
|
||||
boot_info.chip_id[4],
|
||||
boot_info.chip_id[5],
|
||||
boot_info.chip_id[6],
|
||||
boot_info.chip_id[7]);
|
||||
|
||||
char exe_path[PATH_MAX];
|
||||
char eflash_loader_path[PATH_MAX];
|
||||
get_binary_folder(exe_path, PATH_MAX); // TODO: Error handling
|
||||
snprintf(eflash_loader_path, PATH_MAX, "%s/data/%s/eflash_loader_32m.bin", exe_path, device.chip->type_str);
|
||||
|
||||
FILE* eflash_loader_file = fopen(eflash_loader_path, "rb");
|
||||
uint8_t eflash_loader_header[176];
|
||||
fread(eflash_loader_header, 176, 1, eflash_loader_file); // TODO: Error handling
|
||||
|
||||
printf("Loading eflash_loader...\n");
|
||||
ret = blisp_device_load_boot_header(&device, eflash_loader_header);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to load boot header.\n");
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
uint32_t sent_data = 0;
|
||||
uint32_t buffer_size = 0;
|
||||
uint8_t buffer[4092];
|
||||
|
||||
// TODO: Real checking of segments count
|
||||
for (uint8_t seg_index = 0; seg_index < 1; seg_index++) {
|
||||
struct blisp_segment_header segment_header = {0};
|
||||
fread(&segment_header, 16, 1, eflash_loader_file); // TODO: Error handling
|
||||
|
||||
ret = blisp_device_load_segment_header(&device, &segment_header);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to load segment header.\n");
|
||||
goto exit1;
|
||||
}
|
||||
printf("Flashing %d. segment\n", seg_index + 1);
|
||||
printf("0b / %" PRIu32 "b (0.00%%)\n", segment_header.length);
|
||||
|
||||
while (sent_data < segment_header.length) {
|
||||
buffer_size = segment_header.length - sent_data;
|
||||
if (buffer_size > 4092) {
|
||||
buffer_size = 4092;
|
||||
}
|
||||
fread(buffer, buffer_size, 1, eflash_loader_file);
|
||||
blisp_device_load_segment_data(&device, buffer, buffer_size); // TODO: Error handling
|
||||
sent_data += buffer_size;
|
||||
printf("%" PRIu32 "b / %" PRIu32 "b (%.2f%%)\n", sent_data, segment_header.length,
|
||||
(((float)sent_data / (float)segment_header.length) * 100.0f));
|
||||
}
|
||||
}
|
||||
|
||||
ret = blisp_device_check_image(&device);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to check image.\n");
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
ret = blisp_device_run_image(&device);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "Failed to run image.\n");
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
exit1:
|
||||
if (eflash_loader_file != NULL) fclose(eflash_loader_file);
|
||||
blisp_device_close(&device);
|
||||
}
|
||||
|
||||
@ -38,11 +143,12 @@ int8_t
|
||||
cmd_write_args_init() {
|
||||
cmd_write_argtable[0] = cmd
|
||||
= arg_rex1(NULL, NULL, "write", NULL, REG_ICASE, NULL);
|
||||
cmd_write_argtable[1] = binary_to_write
|
||||
= arg_file1(NULL, NULL, "<input>", "Binary to write");
|
||||
cmd_write_argtable[1] = chip_type = arg_str1("c", "chip", "<chip_type>", "Chip Type (bl70x)");
|
||||
cmd_write_argtable[2] = port_name
|
||||
= arg_str0("p", "port", "<port_name>", "Name/Path to the Serial Port (empty for search)");
|
||||
cmd_write_argtable[3] = end = arg_end(10);
|
||||
cmd_write_argtable[3] = binary_to_write
|
||||
= arg_file1(NULL, NULL, "<input>", "Binary to write");
|
||||
cmd_write_argtable[4] = end = arg_end(10);
|
||||
|
||||
if (arg_nullcheck(cmd_write_argtable) != 0) {
|
||||
fprintf(stderr, "insufficient memory\n");
|
||||
|
Loading…
Reference in New Issue
Block a user