Skip to content

Commit 6699e18

Browse files
committed
Implemented active image and firmware update commands
1 parent 0d0b6a7 commit 6699e18

File tree

1 file changed

+300
-26
lines changed

1 file changed

+300
-26
lines changed

firmware/programmer/nand_programmer.c

Lines changed: 300 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "led.h"
1111
#include "log.h"
1212
#include "version.h"
13+
#include "flash.h"
1314
#include <stdio.h>
1415
#include <string.h>
1516
#include <stddef.h>
@@ -22,18 +23,28 @@
2223

2324
#define NP_NAND_GOOD_BLOCK_MARK 0xFF
2425

26+
#define BOOT_CONFIG_ADDR 0x08003800
27+
#define FLASH_START_ADDR 0x08000000
28+
#define FLASH_SIZE 0x40000
29+
#define FLASH_PAGE_SIZE 0x800
30+
#define FLASH_BLOCK_SIZE 0x800
31+
2532
typedef enum
2633
{
27-
NP_CMD_NAND_READ_ID = 0x00,
28-
NP_CMD_NAND_ERASE = 0x01,
29-
NP_CMD_NAND_READ = 0x02,
30-
NP_CMD_NAND_WRITE_S = 0x03,
31-
NP_CMD_NAND_WRITE_D = 0x04,
32-
NP_CMD_NAND_WRITE_E = 0x05,
33-
NP_CMD_NAND_CONF = 0x06,
34-
NP_CMD_NAND_READ_BB = 0x07,
35-
NP_CMD_VERSION_GET = 0x08,
36-
NP_CMD_NAND_LAST = 0x09,
34+
NP_CMD_NAND_READ_ID = 0x00,
35+
NP_CMD_NAND_ERASE = 0x01,
36+
NP_CMD_NAND_READ = 0x02,
37+
NP_CMD_NAND_WRITE_S = 0x03,
38+
NP_CMD_NAND_WRITE_D = 0x04,
39+
NP_CMD_NAND_WRITE_E = 0x05,
40+
NP_CMD_NAND_CONF = 0x06,
41+
NP_CMD_NAND_READ_BB = 0x07,
42+
NP_CMD_VERSION_GET = 0x08,
43+
NP_CMD_ACTIVE_IMAGE_GET = 0x09,
44+
NP_CMD_FW_UPDATE_S = 0x0a,
45+
NP_CMD_FW_UPDATE_D = 0x0b,
46+
NP_CMD_FW_UPDATE_E = 0x0c,
47+
NP_CMD_NAND_LAST = 0x0d,
3748
} np_cmd_code_t;
3849

3950
enum
@@ -197,6 +208,12 @@ typedef struct __attribute__((__packed__))
197208
version_t version;
198209
} np_resp_version_t;
199210

211+
typedef struct __attribute__((__packed__))
212+
{
213+
np_resp_t header;
214+
uint8_t active_image;
215+
} np_resp_active_image_t;
216+
200217
typedef struct
201218
{
202219
uint32_t addr;
@@ -210,12 +227,18 @@ typedef struct
210227
uint32_t offset;
211228
} np_page_t;
212229

230+
typedef struct __attribute__((__packed__))
231+
{
232+
uint8_t active_image;
233+
} boot_config_t;
234+
213235
typedef struct
214236
{
215237
uint8_t *rx_buf;
216238
uint32_t rx_buf_len;
217239
uint32_t addr;
218240
uint32_t len;
241+
uint32_t base_addr;
219242
uint32_t page_size;
220243
uint32_t block_size;
221244
uint32_t total_size;
@@ -234,6 +257,7 @@ typedef struct
234257
typedef struct
235258
{
236259
int id;
260+
bool is_chip_cmd;
237261
int (*exec)(np_prog_t *prog);
238262
} np_cmd_handler_t;
239263

@@ -1118,17 +1142,268 @@ int np_cmd_version_get(np_prog_t *prog)
11181142
return 0;
11191143
}
11201144

1145+
static int np_boot_config_read(boot_config_t *config)
1146+
{
1147+
if (flash_read(BOOT_CONFIG_ADDR, (uint8_t *)config, sizeof(boot_config_t))
1148+
< 0)
1149+
{
1150+
return -1;
1151+
}
1152+
1153+
return 0;
1154+
}
1155+
1156+
static int np_boot_config_write(boot_config_t *config)
1157+
{
1158+
if (flash_page_erase(BOOT_CONFIG_ADDR) < 0)
1159+
return -1;
1160+
1161+
if (flash_write(BOOT_CONFIG_ADDR, (uint8_t *)config, sizeof(boot_config_t))
1162+
< 0)
1163+
{
1164+
return -1;
1165+
}
1166+
1167+
return 0;
1168+
}
1169+
1170+
static int np_cmd_active_image_get(np_prog_t *prog)
1171+
{
1172+
boot_config_t boot_config;
1173+
np_resp_active_image_t resp;
1174+
size_t resp_len = sizeof(resp);
1175+
1176+
DEBUG_PRINT("Get active image command\r\n");
1177+
1178+
if (np_boot_config_read(&boot_config))
1179+
return NP_ERR_INTERNAL;
1180+
1181+
resp.header.code = NP_RESP_DATA;
1182+
resp.header.info = resp_len - sizeof(resp.header);
1183+
resp.active_image = boot_config.active_image;
1184+
1185+
if (np_comm_cb)
1186+
np_comm_cb->send((uint8_t *)&resp, resp_len);
1187+
1188+
return 0;
1189+
}
1190+
1191+
static int np_cmd_fw_update_start(np_prog_t *prog)
1192+
{
1193+
uint32_t addr, len;
1194+
np_write_start_cmd_t *write_start_cmd;
1195+
1196+
if (prog->rx_buf_len < sizeof(np_write_start_cmd_t))
1197+
{
1198+
ERROR_PRINT("Wrong buffer length for write start command %lu\r\n",
1199+
prog->rx_buf_len);
1200+
return NP_ERR_LEN_INVALID;
1201+
}
1202+
1203+
write_start_cmd = (np_write_start_cmd_t *)prog->rx_buf;
1204+
addr = write_start_cmd->addr;
1205+
len = write_start_cmd->len;
1206+
1207+
DEBUG_PRINT("Write at 0x%lx 0x%lx bytes command\r\n", addr, len);
1208+
1209+
prog->base_addr = FLASH_START_ADDR;
1210+
prog->page_size = FLASH_PAGE_SIZE;
1211+
prog->block_size = FLASH_BLOCK_SIZE;
1212+
prog->total_size = FLASH_SIZE;
1213+
1214+
if (addr + len > prog->base_addr + prog->total_size)
1215+
{
1216+
ERROR_PRINT("Write address 0x%lx+0x%lx is more then flash size "
1217+
"0x%lx\r\n", addr, len, prog->base_addr + prog->total_size);
1218+
return NP_ERR_ADDR_EXCEEDED;
1219+
}
1220+
1221+
if (addr % prog->page_size)
1222+
{
1223+
ERROR_PRINT("Address 0x%lx is not aligned to page size 0x%lx\r\n", addr,
1224+
prog->page_size);
1225+
return NP_ERR_ADDR_NOT_ALIGN;
1226+
}
1227+
1228+
if (!len)
1229+
{
1230+
ERROR_PRINT("Length is 0\r\n");
1231+
return NP_ERR_LEN_INVALID;
1232+
}
1233+
1234+
if (len % prog->page_size)
1235+
{
1236+
ERROR_PRINT("Length 0x%lx is not aligned to page size 0x%lx\r\n", len,
1237+
prog->page_size);
1238+
return NP_ERR_LEN_NOT_ALIGN;
1239+
}
1240+
1241+
prog->addr = addr;
1242+
prog->len = len;
1243+
prog->addr_is_set = 1;
1244+
1245+
prog->page.page = addr / prog->page_size;
1246+
prog->page.offset = 0;
1247+
1248+
prog->bytes_written = 0;
1249+
prog->bytes_ack = 0;
1250+
1251+
return np_send_ok_status();
1252+
}
1253+
1254+
static int np_cmd_fw_update_data(np_prog_t *prog)
1255+
{
1256+
uint32_t write_len, bytes_left, len;
1257+
np_write_data_cmd_t *write_data_cmd;
1258+
1259+
if (prog->rx_buf_len < sizeof(np_write_data_cmd_t))
1260+
{
1261+
ERROR_PRINT("Wrong buffer length for write data command %lu\r\n",
1262+
prog->rx_buf_len);
1263+
return NP_ERR_LEN_INVALID;
1264+
}
1265+
1266+
write_data_cmd = (np_write_data_cmd_t *)prog->rx_buf;
1267+
len = write_data_cmd->len;
1268+
if (len + sizeof(np_write_data_cmd_t) > NP_PACKET_BUF_SIZE)
1269+
{
1270+
ERROR_PRINT("Data size is wrong 0x%lx\r\n", len);
1271+
return NP_ERR_CMD_DATA_SIZE;
1272+
}
1273+
1274+
if (len + sizeof(np_write_data_cmd_t) != prog->rx_buf_len)
1275+
{
1276+
ERROR_PRINT("Buffer len 0x%lx is bigger then command 0x%lx\r\n",
1277+
prog->rx_buf_len, len + sizeof(np_write_data_cmd_t));
1278+
return NP_ERR_CMD_DATA_SIZE;
1279+
}
1280+
1281+
if (!prog->addr_is_set)
1282+
{
1283+
ERROR_PRINT("Write address is not set\r\n");
1284+
return NP_ERR_ADDR_INVALID;
1285+
}
1286+
1287+
if (prog->page.offset + len > prog->page_size)
1288+
write_len = prog->page_size - prog->page.offset;
1289+
else
1290+
write_len = len;
1291+
1292+
memcpy(prog->page.buf + prog->page.offset, write_data_cmd->data, write_len);
1293+
prog->page.offset += write_len;
1294+
1295+
if (prog->page.offset == prog->page_size)
1296+
{
1297+
if (prog->addr >= prog->base_addr + prog->total_size)
1298+
{
1299+
ERROR_PRINT("Write address 0x%lx is more then flash size 0x%lx\r\n",
1300+
prog->addr, prog->base_addr + prog->total_size);
1301+
return NP_ERR_ADDR_EXCEEDED;
1302+
}
1303+
1304+
if (flash_page_erase(prog->addr) < 0)
1305+
return NP_ERR_INTERNAL;
1306+
1307+
if (flash_write(prog->addr, prog->page.buf, prog->page_size) < 0)
1308+
return NP_ERR_INTERNAL;
1309+
1310+
prog->addr += prog->page_size;
1311+
prog->page.page++;
1312+
prog->page.offset = 0;
1313+
}
1314+
1315+
bytes_left = len - write_len;
1316+
if (bytes_left)
1317+
{
1318+
memcpy(prog->page.buf, write_data_cmd->data + write_len, bytes_left);
1319+
prog->page.offset += bytes_left;
1320+
}
1321+
1322+
prog->bytes_written += len;
1323+
if (prog->bytes_written - prog->bytes_ack >= prog->page_size ||
1324+
prog->bytes_written == prog->len)
1325+
{
1326+
if (np_send_write_ack(prog->bytes_written))
1327+
return -1;
1328+
prog->bytes_ack = prog->bytes_written;
1329+
}
1330+
1331+
if (prog->bytes_written > prog->len)
1332+
{
1333+
ERROR_PRINT("Actual write data length 0x%lx is more then 0x%lx\r\n",
1334+
prog->bytes_written, prog->len);
1335+
return NP_ERR_LEN_EXCEEDED;
1336+
}
1337+
1338+
return 0;
1339+
}
1340+
1341+
static int np_cmd_fw_update_end(np_prog_t *prog)
1342+
{
1343+
boot_config_t boot_config;
1344+
1345+
prog->addr_is_set = 0;
1346+
1347+
if (prog->page.offset)
1348+
{
1349+
ERROR_PRINT("Data of 0x%lx length was not written\r\n",
1350+
prog->page.offset);
1351+
return NP_ERR_NAND_WR;
1352+
}
1353+
1354+
if (np_boot_config_read(&boot_config))
1355+
return NP_ERR_INTERNAL;
1356+
1357+
boot_config.active_image = boot_config.active_image ? 0 : 1;
1358+
if (np_boot_config_write(&boot_config))
1359+
return NP_ERR_INTERNAL;
1360+
1361+
return np_send_ok_status();
1362+
}
1363+
1364+
static int np_cmd_fw_update(np_prog_t *prog)
1365+
{
1366+
np_cmd_t *cmd = (np_cmd_t *)prog->rx_buf;
1367+
int ret = 0;
1368+
1369+
switch (cmd->code)
1370+
{
1371+
case NP_CMD_FW_UPDATE_S:
1372+
led_wr_set(true);
1373+
ret = np_cmd_fw_update_start(prog);
1374+
break;
1375+
case NP_CMD_FW_UPDATE_D:
1376+
ret = np_cmd_fw_update_data(prog);
1377+
break;
1378+
case NP_CMD_FW_UPDATE_E:
1379+
ret = np_cmd_fw_update_end(prog);
1380+
led_wr_set(false);
1381+
break;
1382+
default:
1383+
break;
1384+
}
1385+
1386+
if (ret < 0)
1387+
led_wr_set(false);
1388+
1389+
return ret;
1390+
}
1391+
11211392
static np_cmd_handler_t cmd_handler[] =
11221393
{
1123-
{ NP_CMD_NAND_READ_ID, np_cmd_nand_read_id },
1124-
{ NP_CMD_NAND_ERASE, np_cmd_nand_erase },
1125-
{ NP_CMD_NAND_READ, np_cmd_nand_read },
1126-
{ NP_CMD_NAND_WRITE_S, np_cmd_nand_write },
1127-
{ NP_CMD_NAND_WRITE_D, np_cmd_nand_write },
1128-
{ NP_CMD_NAND_WRITE_E, np_cmd_nand_write },
1129-
{ NP_CMD_NAND_CONF, np_cmd_nand_conf },
1130-
{ NP_CMD_NAND_READ_BB, np_cmd_read_bad_blocks },
1131-
{ NP_CMD_VERSION_GET, np_cmd_version_get },
1394+
{ NP_CMD_NAND_READ_ID, 1, np_cmd_nand_read_id },
1395+
{ NP_CMD_NAND_ERASE, 1, np_cmd_nand_erase },
1396+
{ NP_CMD_NAND_READ, 1, np_cmd_nand_read },
1397+
{ NP_CMD_NAND_WRITE_S, 1, np_cmd_nand_write },
1398+
{ NP_CMD_NAND_WRITE_D, 1, np_cmd_nand_write },
1399+
{ NP_CMD_NAND_WRITE_E, 1, np_cmd_nand_write },
1400+
{ NP_CMD_NAND_CONF, 0, np_cmd_nand_conf },
1401+
{ NP_CMD_NAND_READ_BB, 1, np_cmd_read_bad_blocks },
1402+
{ NP_CMD_VERSION_GET, 0, np_cmd_version_get },
1403+
{ NP_CMD_ACTIVE_IMAGE_GET, 0, np_cmd_active_image_get },
1404+
{ NP_CMD_FW_UPDATE_S, 0, np_cmd_fw_update },
1405+
{ NP_CMD_FW_UPDATE_D, 0, np_cmd_fw_update },
1406+
{ NP_CMD_FW_UPDATE_E, 0, np_cmd_fw_update },
11321407
};
11331408

11341409
static bool np_cmd_is_valid(np_cmd_code_t code)
@@ -1148,19 +1423,18 @@ static int np_cmd_handler(np_prog_t *prog)
11481423
}
11491424
cmd = (np_cmd_t *)prog->rx_buf;
11501425

1151-
if (!prog->chip_is_conf && cmd->code != NP_CMD_NAND_CONF &&
1152-
cmd->code != NP_CMD_VERSION_GET)
1153-
{
1154-
ERROR_PRINT("Chip is not configured\r\n");
1155-
return NP_ERR_CHIP_NOT_CONF;
1156-
}
1157-
11581426
if (!np_cmd_is_valid(cmd->code))
11591427
{
11601428
ERROR_PRINT("Invalid cmd code %d\r\n", cmd->code);
11611429
return NP_ERR_CMD_INVALID;
11621430
}
11631431

1432+
if (!prog->chip_is_conf && cmd_handler[cmd->code].is_chip_cmd)
1433+
{
1434+
ERROR_PRINT("Chip is not configured\r\n");
1435+
return NP_ERR_CHIP_NOT_CONF;
1436+
}
1437+
11641438
return cmd_handler[cmd->code].exec(prog);
11651439
}
11661440

0 commit comments

Comments
 (0)