refactoring programmer
This commit is contained in:
parent
b9052ca694
commit
b9a3524daf
9 changed files with 284 additions and 364 deletions
|
@ -16,7 +16,11 @@ class MemoryBase {
|
|||
return flash.ReadBlock(addr, reinterpret_cast<uint8_t*> (ptr), len);
|
||||
}
|
||||
void Erase (const uint32_t blok) {
|
||||
flash.EraseSector(blok);
|
||||
/* Flash používá 24-bitovou adresu počátku bloku, zde máme k dispozici
|
||||
* jen 16-bitový offset. Takže to jen natáhneme 256 krát. Software
|
||||
* tomu musí odpovídat.
|
||||
* */
|
||||
flash.EraseSector(blok << 8);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
/*********************************************************************************
|
||||
* Do mluvícího teploměru bylo potřeba nějak dostat data do externí flash.
|
||||
* Zde je základ programátoru, je to recyklovaný kód, takže zatím to umí jen
|
||||
* binární soubory do 64KiB, ale patrně nebude problém dopsat to na větší délku.
|
||||
* binární soubory. Dodělat Intel hex není problém, ale nepotřebuji to.
|
||||
* Umí to jen nor flash se stránkou 4096 bytů, předpokládaná velikost je 32Mbit.
|
||||
* Software je dost surový, bez kontrol, prostě jen aby to trochu fungovalo.
|
||||
**********************************************************************************/
|
||||
static GpioClass led (GPIOB, 8);
|
||||
|
|
|
@ -7,7 +7,8 @@ MFLAGS = -o $(PR)
|
|||
|
||||
all: $(PR)
|
||||
|
||||
OBJECTS = main.o usart.o baud.o linkprotocol.o intelhex.o
|
||||
OBJECTS = main.o usart.o baud.o programmer.o intelhex.o
|
||||
#linkprotocol.o
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
#ifndef HELPERS_H
|
||||
#define HELPERS_H
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "fifo.h"
|
||||
#include "baselayer.h"
|
||||
|
||||
class MemoryBase {
|
||||
unsigned lenght;
|
||||
unsigned char * data;
|
||||
public:
|
||||
explicit MemoryBase (const unsigned len) noexcept : lenght(len) {
|
||||
data = new unsigned char [lenght];
|
||||
}
|
||||
~MemoryBase () { delete [] data; }
|
||||
uint32_t getLenght () { return lenght; }
|
||||
uint8_t * getData () { return data; }
|
||||
uint32_t Write (const uint32_t addr, const void * ptr, const uint32_t len) {
|
||||
printf("Readen at 0x%04X \r", addr);
|
||||
fflush(stdout);
|
||||
const uint8_t * dptr = reinterpret_cast<const uint8_t*>(ptr);
|
||||
for (unsigned n=0; n<len; n++) data [addr + n] = dptr [n];
|
||||
return len;
|
||||
}
|
||||
uint32_t Read (const uint32_t addr, void * ptr, const uint32_t len) {
|
||||
uint8_t * data = reinterpret_cast<uint8_t*>(ptr);
|
||||
for (unsigned n=0; n<len; n++) data[n] = n;
|
||||
return len; }
|
||||
void Erase (const uint32_t blok) {}
|
||||
};
|
||||
|
||||
class CdcCmd : public BaseLayer {
|
||||
static constexpr int maxlen = 0x80;
|
||||
FIFO<char, maxlen> ring;
|
||||
char line [maxlen];
|
||||
unsigned index;
|
||||
public:
|
||||
explicit CdcCmd () noexcept : BaseLayer(), ring(), index(0u) {}
|
||||
uint32_t Up(const char * data, const uint32_t len) override {
|
||||
for (unsigned n=0u; n<len; n++) ring.Write (data [n]);
|
||||
return len;
|
||||
}
|
||||
void SendString (const char * ptr, const uint32_t len) {
|
||||
/*
|
||||
fprintf(stdout, "TX");
|
||||
int r = fwrite (ptr, 1, len, stdout); (void) r;
|
||||
fflush (stdout);
|
||||
*/
|
||||
unsigned ofs = 0u, res = len;
|
||||
while (res) {
|
||||
const unsigned n = Down (ptr + ofs, res);
|
||||
ofs += n;
|
||||
res -= n;
|
||||
}
|
||||
}
|
||||
char * GetLine (unsigned & len) {
|
||||
char c;
|
||||
while (ring.Read(c)) {
|
||||
line [index++] = c;
|
||||
if (c == '\n') {
|
||||
len = index;
|
||||
/*
|
||||
fprintf(stdout, "RX");
|
||||
int r = fwrite (line, 1, index, stdout); (void) r;
|
||||
fflush (stdout);
|
||||
*/
|
||||
index = 0u;
|
||||
return line;
|
||||
}
|
||||
}
|
||||
len = 0u;
|
||||
return line;
|
||||
}
|
||||
};
|
||||
#endif // HELPERS_H
|
|
@ -1,122 +0,0 @@
|
|||
#include <string.h>
|
||||
#include "helpers.h"
|
||||
#include "linkprotocol.h"
|
||||
|
||||
#define trace(...)
|
||||
|
||||
LinkProtocol::LinkProtocol(CdcCmd & g, MemoryBase & b) noexcept : cdccmd(g), ihx(), driver(b),
|
||||
begin_addr(0), start_addr(0), lenght (0) {
|
||||
}
|
||||
void LinkProtocol::ParseLine (const char * line) {
|
||||
const unsigned readen = strlen (line);
|
||||
RowTypes t = ihx.parseRecord (line, readen);
|
||||
switch (t) {
|
||||
case dataRecord: AcquireDataRecord (); break;
|
||||
case elaRecord: AcquireElaRecord (); break;
|
||||
case slaRecord: AcquireSlaRecord (); break;
|
||||
case eofRecord: AcquireEofRecord (); break;
|
||||
case reqRecord: AcquireReqRecord (); break;
|
||||
case ersRecord: AcquireErsRecord (); break;
|
||||
default:
|
||||
trace ("BAD record 0x%02X\r\n", t);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
void LinkProtocol::AcquireDataRecord() {
|
||||
uint32_t ofs, len;
|
||||
uint8_t * ptr = ihx.getDataRow (ofs, len);
|
||||
uint32_t res = driver.Write (begin_addr + ofs, ptr, len);
|
||||
if (res) {
|
||||
//SendAck();
|
||||
ihx.AddOffset (res); // posun offsetu az po ack
|
||||
return;
|
||||
}
|
||||
//SendAck (false);
|
||||
}
|
||||
// První paket, který musí přijít při každé akci.
|
||||
void LinkProtocol::AcquireElaRecord() {
|
||||
ihx.getAddress (begin_addr);
|
||||
trace("Begin = 0x%08X\r\n", begin_addr);
|
||||
//driver = GetDriverByAddress (begin_addr);
|
||||
//if (driver) driver->On (begin_addr);
|
||||
SendAck();
|
||||
}
|
||||
typedef void (*pHandler) (void);
|
||||
void LinkProtocol::AcquireSlaRecord() {
|
||||
ihx.getAddress (start_addr);
|
||||
trace("Start = 0x%08X\r\n", start_addr);
|
||||
}
|
||||
void LinkProtocol::AcquireEofRecord() {
|
||||
ihx.getLenght (lenght);
|
||||
trace ("Lenght = %d\r\n", lenght);
|
||||
SendAck();
|
||||
}
|
||||
void LinkProtocol::AcquireReqRecord() {
|
||||
static constexpr unsigned chunk_size = 0x10;
|
||||
uint8_t data [chunk_size];
|
||||
uint32_t res = 0x10, len, ofs;
|
||||
len = chunk_size;
|
||||
ihx.getOffset (ofs);
|
||||
//trace ("AcquireReqRecord: %04X, len=%d\r\n", ofs, len);
|
||||
res = driver.Read (begin_addr + ofs, data, len);
|
||||
res = ihx.DataRecord (strbuf, data, res);
|
||||
cdccmd.SendString (strbuf, res);
|
||||
}
|
||||
void LinkProtocol::AcquireErsRecord() {
|
||||
uint32_t block;
|
||||
ihx.getOffset (block);
|
||||
driver.Erase (block);
|
||||
SendAck();
|
||||
}
|
||||
|
||||
void LinkProtocol::SendAck (bool ok) {
|
||||
RowTypes t = ok ? ackRecord : nakRecord;
|
||||
const uint32_t r = ihx.BTxRecord (strbuf, t);
|
||||
cdccmd.SendString (strbuf, r);
|
||||
}
|
||||
////////////////////////////////////////////////////////
|
||||
void LinkProtocol::ReadMem() {
|
||||
uint32_t res = ihx.BTxRecord (strbuf, reqRecord);
|
||||
cdccmd.SendString (strbuf, res);
|
||||
}
|
||||
bool LinkProtocol::isEOF(const unsigned len) {
|
||||
uint32_t ofs;
|
||||
ihx.getOffset(ofs);
|
||||
if (ofs < len) return false;
|
||||
return true;
|
||||
}
|
||||
bool LinkProtocol::StartOperation() {
|
||||
uint32_t res = ihx.ElaRecord(strbuf, 0u);
|
||||
cdccmd.SendString (strbuf, res);
|
||||
return true;
|
||||
}
|
||||
bool LinkProtocol::Erase(const unsigned int n) {
|
||||
uint32_t ofs, addr = n * 0x1000u;
|
||||
ihx.getOffset(ofs);
|
||||
ihx.AddOffset(addr - ofs);
|
||||
uint32_t res = ihx.BTxRecord (strbuf, ersRecord);
|
||||
cdccmd.SendString (strbuf, res);
|
||||
return true;
|
||||
}
|
||||
bool LinkProtocol::WriteMem(const uint8_t * data, const unsigned int len) {
|
||||
unsigned ofs = 0u, rem = len, chunk;
|
||||
for (;;) {
|
||||
unsigned value;
|
||||
char * res = cdccmd.GetLine(value);
|
||||
if (value == 0u) continue;
|
||||
RowTypes t = ihx.parseRecord(res, value);
|
||||
if (t != ackRecord) return false;
|
||||
if (rem == 0u) break;
|
||||
|
||||
chunk = rem > 0x20 ? 0x20 : rem;
|
||||
unsigned rl = ihx.DataRecord(strbuf, data + ofs, chunk);
|
||||
printf("Write at 0x%04X \r", ofs);
|
||||
fflush(stdout);
|
||||
ihx.AddOffset(chunk);
|
||||
cdccmd.SendString(strbuf, rl);
|
||||
ofs += chunk;
|
||||
rem -= chunk;
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
#ifndef LINKPROTOCOL_H
|
||||
#define LINKPROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "intelhex.h"
|
||||
|
||||
class CdcCmd;
|
||||
class MemoryBase;
|
||||
/**
|
||||
* @class LinkProtocol
|
||||
* @brief Protokol po CDC.
|
||||
*
|
||||
* Vychází z formátu IntelHex. komunikaci začíná PC, modul odpovídá. První co musí PC (vždy na začátku konunikace !) poslat
|
||||
* je paket ElaRecord (4), který určuje počáteční adresu - podle ní modul vybere potřebný ovladač paměti. Formy komunikace :
|
||||
* -# Mazání obsahu flash. Probíhá po jednotlivých blocích.
|
||||
* - PC -> MODUL : ersRecord (v poli offset číslo bloku relativně k počátku typu paměti)
|
||||
* - MODUL -> PC : ackRecord (v poli offset číslo bloku relativně k počátku typu paměti)
|
||||
* -# Zápis dat do paměti.
|
||||
* - PC -> MODUL : dataRecord (max. 32 bytů)
|
||||
* - MODUL -> PC : ackRecord nebo nakRecord pokud je cosi špatně
|
||||
* -# Čtení dat z paměti.
|
||||
* - PC -> MODUL : reqRecord (v poli offset odkud chci číst)
|
||||
* - MODUL -> PC : dataRecord - pokud má nulovou délku, další data nejsou. Posílána je délka 32 bytů.
|
||||
* -# Spuštění uživatelského programu.
|
||||
* - PC -> MODUL : slaRecord
|
||||
* - bez odpovědi - je to jen pro uživatelské testy a může to špatně skončit. Vlastně je to přidáno
|
||||
* jen proto, že to jde.
|
||||
* */
|
||||
class LinkProtocol {
|
||||
static constexpr unsigned strbuflen = 0x80u;
|
||||
public:
|
||||
explicit LinkProtocol(CdcCmd & g, MemoryBase & b) noexcept;
|
||||
void ParseLine (const char * line);
|
||||
bool StartOperation ();
|
||||
void ReadMem ();
|
||||
bool WriteMem (const uint8_t * data, const unsigned len);
|
||||
bool Erase (const unsigned n);
|
||||
bool isEOF (const unsigned len);
|
||||
protected:
|
||||
void AcquireDataRecord ();
|
||||
void AcquireElaRecord ();
|
||||
void AcquireSlaRecord ();
|
||||
void AcquireEofRecord ();
|
||||
void AcquireReqRecord ();
|
||||
void AcquireErsRecord ();
|
||||
|
||||
void SendAck (bool ok=true);
|
||||
private:
|
||||
CdcCmd & cdccmd;
|
||||
IntelHex ihx;
|
||||
MemoryBase & driver;
|
||||
|
||||
uint32_t begin_addr;
|
||||
uint32_t start_addr;
|
||||
uint32_t lenght;
|
||||
|
||||
char strbuf [strbuflen];
|
||||
};
|
||||
|
||||
#endif // LINKPROTOCOL_H
|
|
@ -1,118 +1,27 @@
|
|||
#include <signal.h>
|
||||
#include <cstdio>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdlib>
|
||||
#include "usart.h"
|
||||
#include "fifo.h"
|
||||
#include "linkprotocol.h"
|
||||
#include "helpers.h"
|
||||
|
||||
static constexpr unsigned FlashBlockSize = 0x1000u;
|
||||
volatile bool loop = false;
|
||||
void sig_handler (int) {
|
||||
loop = false;
|
||||
}
|
||||
static UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._Flash_Programmer_0001-if00", 9600);
|
||||
static MemoryBase mem (0x400u * FlashBlockSize); // 4MiB flash
|
||||
static CdcCmd cmd;
|
||||
static LinkProtocol lnk (cmd, mem);
|
||||
|
||||
static void read_flash (const unsigned len) {
|
||||
lnk.StartOperation();
|
||||
while (loop) {
|
||||
unsigned value;
|
||||
char * res = cmd.GetLine(value);
|
||||
if (value == 0u) continue;
|
||||
lnk.ParseLine(res);
|
||||
if (lnk.isEOF(len)) break;
|
||||
lnk.ReadMem();
|
||||
}
|
||||
}
|
||||
static void erase_blocks (const unsigned num = 1) {
|
||||
unsigned block = 0u;
|
||||
lnk.StartOperation();
|
||||
while (loop) {
|
||||
unsigned value;
|
||||
char * res = cmd.GetLine(value);
|
||||
if (value == 0u) continue;
|
||||
if (block >= num) break;
|
||||
lnk.ParseLine(res);
|
||||
lnk.Erase (block);
|
||||
printf("Erasing blok %d \r", block);
|
||||
fflush(stdout);
|
||||
block += 1u;
|
||||
}
|
||||
}
|
||||
static uint8_t * open_file_for_read (const char * name, unsigned & len) {
|
||||
struct stat prop;
|
||||
const int r = stat (name, & prop);
|
||||
if (r) return nullptr;
|
||||
const unsigned flen = prop.st_size;
|
||||
FILE * in = fopen (name, "r");
|
||||
uint8_t * data = new uint8_t [flen];
|
||||
const int l = fread (data, 1, flen, in);
|
||||
printf("readen = %d bytes\n", l);
|
||||
fclose(in);
|
||||
len = flen;
|
||||
return data;
|
||||
}
|
||||
static void read_flash_binary (const char * name) {
|
||||
const unsigned flen = 0x10000u;
|
||||
printf("Read data\n");
|
||||
read_flash (flen);
|
||||
FILE * out = fopen(name,"w");
|
||||
int r = fwrite(mem.getData(), 1, flen, out);
|
||||
(void) r;
|
||||
fclose(out);
|
||||
}
|
||||
static void write_flash_binary (const char * name) {
|
||||
unsigned flen = 0u;
|
||||
uint8_t * data = open_file_for_read(name, flen);
|
||||
if (!data) return;
|
||||
printf("Write data\n");
|
||||
uint32_t blocks = flen / FlashBlockSize;
|
||||
if (flen % FlashBlockSize) blocks += 1u;
|
||||
erase_blocks (blocks);
|
||||
|
||||
lnk.StartOperation();
|
||||
lnk.WriteMem (data, flen);
|
||||
delete [] data;
|
||||
}
|
||||
static void verify_flash_binary (const char * name) {
|
||||
unsigned flen = 0u;
|
||||
uint8_t * data = open_file_for_read(name, flen);
|
||||
if (!data) return;
|
||||
printf("Verify data\n");
|
||||
read_flash (flen);
|
||||
uint8_t * fdata = mem.getData();
|
||||
unsigned ok = 0;
|
||||
for (unsigned n=0u; n<flen; n++) {
|
||||
if (fdata[n] != data[n]) {
|
||||
printf("err at %04X - %02X != %02X\n", n, fdata[n], data[n]);
|
||||
ok += 1u;
|
||||
}
|
||||
}
|
||||
if (ok == 0u) printf("\nFlash OK\n");
|
||||
else printf("\nTotal errors = %d\n", ok);
|
||||
|
||||
delete [] data;
|
||||
}
|
||||
#include "programmer.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 3) {
|
||||
printf("Usage:\r\t$ %s r|w|v file.bin\n", argv[0]);
|
||||
printf("Usage:\r\t$ %s r|w|v file.bin [numblocks]\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
loop = true;
|
||||
signal(SIGINT, sig_handler);
|
||||
UsartClass usart ("/dev/serial/by-id/usb-Kizarm_Labs._Flash_Programmer_0001-if00", 9600);
|
||||
Programmer cmd;
|
||||
cmd += usart;
|
||||
cmd.Flush();
|
||||
if (argv[1][0] == 'r') {
|
||||
read_flash_binary (argv[2]);
|
||||
long len = 16;
|
||||
if (argc > 3) {
|
||||
len = strtol (argv[3], nullptr, 10);
|
||||
}
|
||||
cmd.read_flash_binary (argv[2], len);
|
||||
} else if (argv[1][0] == 'w') {
|
||||
write_flash_binary(argv[2]);
|
||||
cmd.write_flash_binary(argv[2]);
|
||||
} else if (argv[1][0] == 'v') {
|
||||
verify_flash_binary(argv[2]);
|
||||
cmd.verify_flash_binary(argv[2]);
|
||||
} else {
|
||||
printf("bad parameter %s\n", argv[1]);
|
||||
}
|
||||
|
|
216
V203F6P6/programmer/software/programmer.cpp
Normal file
216
V203F6P6/programmer/software/programmer.cpp
Normal file
|
@ -0,0 +1,216 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "programmer.h"
|
||||
#define trace printf
|
||||
|
||||
Programmer::Programmer() : BaseLayer(), ring(), ihx(),
|
||||
line_len(0u), line_index(0u), begin_addr(0u), file_len(0u) {
|
||||
file_pool = new uint8_t [MaxPages * PageSize];
|
||||
memory_pool = new uint8_t [MaxPages * PageSize];
|
||||
}
|
||||
Programmer::~Programmer() {
|
||||
delete [] memory_pool;
|
||||
delete [] file_pool;
|
||||
}
|
||||
void Programmer::Flush() {
|
||||
char c;
|
||||
while (ring.Read(c));
|
||||
}
|
||||
|
||||
uint32_t Programmer::Up(const char * data, const uint32_t len) {
|
||||
for (unsigned n=0u; n<len; n++) ring.Write (data [n]);
|
||||
return len;
|
||||
}
|
||||
|
||||
void Programmer::read_flash_binary(const char * name, const unsigned int blen) {
|
||||
file_len = blen * PageSize;
|
||||
if (file_len > (MaxPages * PageSize)) {
|
||||
fprintf(stderr, "read request too long - %d\n", file_len);
|
||||
}
|
||||
printf("read %d bytes...\n", file_len);
|
||||
read_flash(file_len);
|
||||
FILE * out = fopen(name, "w");
|
||||
int r = fwrite(memory_pool, 1, file_len, out);
|
||||
printf("writen %d bytes to %s\n", r, name);
|
||||
fclose(out);
|
||||
}
|
||||
void Programmer::verify_flash_binary(const char * name) {
|
||||
if (!open_file_for_read(name)) return;
|
||||
printf("verify %d bytes...\n", file_len);
|
||||
read_flash(file_len);
|
||||
unsigned err = 0u;
|
||||
for (unsigned n=0u; n<file_len; n++) {
|
||||
if (file_pool[n] != memory_pool[n]) {
|
||||
fprintf(stderr, "err at 0x%06X: 0x%02X != 0x%02X\n", n, file_pool[n], memory_pool[n]);
|
||||
err += 1u;
|
||||
}
|
||||
}
|
||||
if (err) printf("verify errors: %d\n", err);
|
||||
else printf("flash OK\n");
|
||||
}
|
||||
void Programmer::write_flash_binary(const char * name) {
|
||||
if (!open_file_for_read(name)) return;
|
||||
uint32_t blocks = file_len / PageSize;
|
||||
if (file_len % PageSize) blocks += 1u;
|
||||
erase_blocks (blocks);
|
||||
|
||||
begin_addr = 0u;
|
||||
StartOperation(begin_addr);
|
||||
unsigned ofs = 0u, rem = file_len, chunk;
|
||||
while (true) {
|
||||
chunk = rem > 0x20 ? 0x20 : rem;
|
||||
unsigned rl = ihx.DataRecord(strbuf, file_pool + begin_addr + ofs, chunk);
|
||||
SendString(strbuf, rl);
|
||||
while (!GetLine());
|
||||
RowTypes t = ihx.parseRecord(line, line_len);
|
||||
if (t != ackRecord) fprintf(stderr, "BAD WriteOperation 0x%X\n", begin_addr + ofs);
|
||||
ihx.AddOffset(chunk);
|
||||
ofs += chunk;
|
||||
rem -= chunk;
|
||||
printf("write at 0x%04X \r", begin_addr + ofs);
|
||||
fflush(stdout);
|
||||
if (ofs >= ihxPage) {
|
||||
begin_addr += ihxPage;
|
||||
StartOperation(begin_addr);
|
||||
ofs = 0u;
|
||||
}
|
||||
if (rem == 0u) break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void Programmer::SendString(const char * ptr, const uint32_t len) {
|
||||
/*
|
||||
fprintf(stdout, "TX");
|
||||
int r = fwrite (ptr, 1, len, stdout); (void) r;
|
||||
fflush (stdout);
|
||||
*/
|
||||
unsigned ofs = 0u, res = len;
|
||||
while (res) {
|
||||
const unsigned n = Down (ptr + ofs, res);
|
||||
ofs += n;
|
||||
res -= n;
|
||||
}
|
||||
}
|
||||
bool Programmer::open_file_for_read(const char * name) {
|
||||
struct stat prop;
|
||||
const int r = stat (name, & prop);
|
||||
if (r) {
|
||||
fprintf(stderr, "file %s not exists.", name);
|
||||
return false;
|
||||
}
|
||||
const unsigned flen = prop.st_size;
|
||||
if (flen > (MaxPages * PageSize)) {
|
||||
fprintf(stderr, "verify/write request too long - %d\n", flen);
|
||||
return false;
|
||||
}
|
||||
FILE * in = fopen (name, "r");
|
||||
if (!in) {
|
||||
fprintf(stderr, "file %s not open for read.", name);
|
||||
return false;
|
||||
}
|
||||
const int l = fread (file_pool, 1, flen, in);
|
||||
printf("%s: readen = %d bytes\n", name, l);
|
||||
fclose(in);
|
||||
file_len = flen;
|
||||
return true;
|
||||
}
|
||||
bool Programmer::GetLine() {
|
||||
char c;
|
||||
while (ring.Read(c)) {
|
||||
line [line_index++] = c;
|
||||
if (c == '\n') {
|
||||
line_len = line_index;
|
||||
/*
|
||||
fprintf(stdout, "RX");
|
||||
int r = fwrite (line, 1, line_len, stdout); (void) r;
|
||||
fflush (stdout);
|
||||
*/
|
||||
line_index = 0u;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Programmer::ParseLine() {
|
||||
RowTypes t = ihx.parseRecord (line, line_len);
|
||||
switch (t) {
|
||||
case dataRecord: AcquireDataRecord (); break;
|
||||
case reqRecord: AcquireReqRecord (); break;
|
||||
default:
|
||||
trace ("BAD record 0x%02X\r\n", t);
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Programmer::StartOperation(const unsigned addr) {
|
||||
uint32_t res = ihx.ElaRecord(strbuf, addr);
|
||||
SendString (strbuf, res);
|
||||
while (!GetLine());
|
||||
RowTypes t = ihx.parseRecord(line, line_len);
|
||||
if (t != ackRecord) fprintf(stderr, "BAD StartOperation\n");
|
||||
}
|
||||
|
||||
void Programmer::AcquireDataRecord() {
|
||||
uint32_t ofs, len;
|
||||
uint8_t * ptr = ihx.getDataRow (ofs, len);
|
||||
memcpy (memory_pool + begin_addr + ofs, ptr, len);
|
||||
if (len) {
|
||||
ihx.AddOffset (len); // posun offsetu az po ack
|
||||
return;
|
||||
}
|
||||
}
|
||||
void Programmer::AcquireReqRecord() {
|
||||
static constexpr unsigned chunk_size = 0x10;
|
||||
uint8_t data [chunk_size];
|
||||
uint32_t res = 0x10, len, ofs;
|
||||
len = chunk_size;
|
||||
ihx.getOffset (ofs);
|
||||
//trace ("AcquireReqRecord: %04X, len=%d\r\n", ofs, len);
|
||||
memcpy (data, memory_pool + begin_addr + ofs, len);
|
||||
res = ihx.DataRecord (strbuf, data, len);
|
||||
SendString (strbuf, res);
|
||||
}
|
||||
void Programmer::read_flash(const unsigned len) {
|
||||
StartOperation(begin_addr);
|
||||
while (true) {
|
||||
const uint32_t res = ihx.BTxRecord (strbuf, reqRecord);
|
||||
SendString (strbuf, res);
|
||||
while (!GetLine());
|
||||
ParseLine();
|
||||
uint32_t ofs;
|
||||
ihx.getOffset(ofs);
|
||||
printf("read flash at 0x%X \r", begin_addr + ofs);
|
||||
fflush(stdout);
|
||||
if (ofs >= ihxPage) {
|
||||
begin_addr += ihxPage;
|
||||
StartOperation(begin_addr);
|
||||
ofs = 0u;
|
||||
}
|
||||
if ((begin_addr + ofs) >= len) break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
void Programmer::Erase(const unsigned int n) {
|
||||
uint32_t ofs, addr = n * 0x10u; // adresa zmenšena 256x
|
||||
ihx.getOffset(ofs);
|
||||
ihx.AddOffset(addr - ofs);
|
||||
uint32_t res = ihx.BTxRecord (strbuf, ersRecord);
|
||||
SendString (strbuf, res);
|
||||
}
|
||||
|
||||
void Programmer::erase_blocks(const unsigned int blocks) {
|
||||
StartOperation(0u);
|
||||
for (unsigned n=0u; n<blocks; n++) {
|
||||
Erase(n);
|
||||
while (!GetLine());
|
||||
RowTypes t = ihx.parseRecord(line, line_len);
|
||||
if (t != ackRecord) fprintf(stderr, "BAD EraseOperation %d\n", n);
|
||||
printf("erase block %d \r", n+1);
|
||||
fflush(stdout);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
46
V203F6P6/programmer/software/programmer.h
Normal file
46
V203F6P6/programmer/software/programmer.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef PROGRAMMER_H
|
||||
#define PROGRAMMER_H
|
||||
#include "cstdint"
|
||||
#include "baselayer.h"
|
||||
#include "fifo.h"
|
||||
#include "intelhex.h"
|
||||
/**
|
||||
*/
|
||||
class Programmer : public BaseLayer {
|
||||
static constexpr unsigned MaxStrLen = 1024u;
|
||||
static constexpr unsigned MaxPages = 1024u;
|
||||
static constexpr unsigned PageSize = 0x1000u;
|
||||
static constexpr unsigned ihxPage = 0x10000u;
|
||||
FIFO<char, MaxStrLen> ring;
|
||||
IntelHex ihx;
|
||||
char strbuf[MaxStrLen];
|
||||
char line [MaxStrLen];
|
||||
unsigned line_len, line_index;
|
||||
unsigned begin_addr;
|
||||
unsigned file_len;
|
||||
uint8_t * file_pool;
|
||||
uint8_t * memory_pool;
|
||||
public:
|
||||
explicit Programmer ();
|
||||
virtual ~Programmer ();
|
||||
uint32_t Up (const char * data, const uint32_t len) override;
|
||||
void Flush ();
|
||||
|
||||
void read_flash_binary (const char * name, const unsigned blen = 16u);
|
||||
void verify_flash_binary (const char * name);
|
||||
void write_flash_binary (const char * name);
|
||||
protected:
|
||||
bool open_file_for_read (const char * name);
|
||||
void SendString (const char * ptr, const uint32_t len);
|
||||
bool GetLine ();
|
||||
void ParseLine ();
|
||||
void StartOperation (const unsigned addr);
|
||||
void AcquireDataRecord ();
|
||||
void AcquireReqRecord ();
|
||||
|
||||
void Erase (const unsigned n);
|
||||
void read_flash (const unsigned len);
|
||||
void erase_blocks (const unsigned blocks);
|
||||
};
|
||||
|
||||
#endif // PROGRAMMER_H
|
Loading…
Add table
Reference in a new issue