em9304: upload container blob if HAVE_EM9304_PATCH_CONTAINER

This commit is contained in:
Matthias Ringwald 2018-01-08 22:51:19 +01:00
parent 1005167dec
commit d080547ccf

View File

@ -53,9 +53,17 @@
#include <string.h> /* memcpy */
#include "hci.h"
#include "crc32.h"
// should go to some common place
#define OPCODE(ogf, ocf) (ocf | ogf << 10)
#define HCI_OPCODE_EM_WRITE_PATCH_START (0xFC27)
#define HCI_OPCODE_EM_WRITE_PATCH_CONTINUE (0xFC28)
#define HCI_OPCODE_EM_WRITE_PATCH_ABORT (0xFC29)
#define HCI_OPCODE_EM_CPU_RESET (0xFC32)
#define HCI_OPCODE_EM_PATCH_QUERY (0xFC34)
static const uint32_t baudrates[] = {
0,
0,
@ -74,6 +82,43 @@ static const uint32_t baudrates[] = {
1843200,
};
#if 0
// crc32 from 802.3 without table lookup to minimize code
uint32_t crc32(const uint8_t *data, uint16_t len) {
int i, j;
uint32_t byte, crc, mask;
crc = 0xFFFFFFFF;
for (i=0;i<len;i++){
byte = data[i];
crc = crc ^ byte;
for (j = 7; j >= 0; j--) {
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
i = i + 1;
}
return ~crc;
}
#endif
#ifdef HAVE_EM9304_PATCH_CONTAINER
extern const uint8_t container_blob_data[];
extern const uint32_t container_blob_size;
static uint32_t container_blob_offset = 0;
static uint32_t container_end; // current container
static uint16_t patch_sequence_number;
static int em_cpu_reset_sent;
static enum {
UPLOAD_IDLE,
UPLOAD_ACTIVE,
} upload_state;
#endif
static void chipset_set_bd_addr_command(bd_addr_t addr, uint8_t *hci_cmd_buffer){
little_endian_store_16(hci_cmd_buffer, 0, OPCODE(OGF_VENDOR, 0x02));
hci_cmd_buffer[2] = 0x06;
@ -84,7 +129,7 @@ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buf
// lookup baudrates
int i;
int found = 0;
for (i=0;i < sizeof(baudrates)/sizeof(uint32_t);i++){
for (i=0 ; i < sizeof(baudrates)/sizeof(uint32_t) ; i++){
if (baudrates[i] == baudrate){
found = i;
break;
@ -99,10 +144,88 @@ static void chipset_set_baudrate_command(uint32_t baudrate, uint8_t *hci_cmd_buf
hci_cmd_buffer[3] = i;
}
#ifdef HAVE_EM9304_PATCH_CONTAINER
static void chipset_init(const void * config){
UNUSED(config);
container_blob_offset = 0;
em_cpu_reset_sent = 0;
upload_state = UPLOAD_IDLE;
}
static btstack_chipset_result_t chipset_next_command(uint8_t * hci_cmd_buffer){
log_info("pos %u, container end %u, blob size %u", container_blob_offset, container_end, container_blob_size);
if (container_blob_offset >= container_blob_size) {
if (0 == em_cpu_reset_sent){
// send EM CPU Reset
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_CPU_RESET);
hci_cmd_buffer[2] = 0;
em_cpu_reset_sent = 1;
return BTSTACK_CHIPSET_VALID_COMMAND;
} else {
return BTSTACK_CHIPSET_DONE;
}
}
uint32_t tag;
uint16_t bytes_to_upload;
uint32_t crc;
switch (upload_state){
case UPLOAD_IDLE:
// check for 'em93' tag
tag = little_endian_read_32(container_blob_data, container_blob_offset);
if (0x656d3933 != tag) {
log_error("Expected 0x656d3933 ('em934') but got %08x", tag);
return BTSTACK_CHIPSET_DONE;
}
// fetch info for current container
container_end = container_blob_offset + little_endian_read_32(container_blob_data, container_blob_offset + 4);
// start uploading (<= 59 bytes)
patch_sequence_number = 1;
bytes_to_upload = btstack_min(59, container_end - container_blob_offset);
crc = crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
// build command
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_START);
hci_cmd_buffer[2] = 5 + bytes_to_upload;
hci_cmd_buffer[3] = 0; // upload to iRAM1
little_endian_store_32(hci_cmd_buffer, 4, crc);
memcpy(&hci_cmd_buffer[8], &container_blob_data[container_blob_offset], bytes_to_upload);
container_blob_offset += bytes_to_upload;
if (container_blob_offset < container_end){
upload_state = UPLOAD_ACTIVE;
}
return BTSTACK_CHIPSET_VALID_COMMAND;
case UPLOAD_ACTIVE:
// Upload next segement
bytes_to_upload = btstack_min(58, container_end - container_blob_offset);
crc = crc32(&container_blob_data[container_blob_offset], bytes_to_upload);
// build command
little_endian_store_16(hci_cmd_buffer, 0, HCI_OPCODE_EM_WRITE_PATCH_CONTINUE);
hci_cmd_buffer[2] = 6 + bytes_to_upload;
little_endian_store_16(hci_cmd_buffer, 3, patch_sequence_number++);
little_endian_store_32(hci_cmd_buffer, 5, crc);
memcpy(&hci_cmd_buffer[9], &container_blob_data[container_blob_offset], bytes_to_upload);
container_blob_offset += bytes_to_upload;
if (container_blob_offset >= container_end){
log_info("container done maybe another one");
upload_state = UPLOAD_IDLE;
}
return BTSTACK_CHIPSET_VALID_COMMAND;
}
return BTSTACK_CHIPSET_DONE;
}
#endif
static const btstack_chipset_t btstack_chipset_em9301 = {
"EM9301",
NULL, // chipset_init not used
NULL, // chipset_next_command not used
#ifdef HAVE_EM9304_PATCH_CONTAINER
chipset_init,
chipset_next_command,
#else
NULL,
NULL,
#endif
chipset_set_baudrate_command,
chipset_set_bd_addr_command,
};