#include #include #include #include #include #include #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 (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 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