stk500.c
来自「这是一个非常有价值的参考代码」· C语言 代码 · 共 1,205 行 · 第 1/2 页
C
1,205 行
fprintf(stderr, "%s: stk500_loadaddr(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -1; } stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_OK) { return 0; } fprintf(stderr, "%s: loadaddr(): (b) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -1;}static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes){ unsigned char buf[16]; int memtype; unsigned int addr; int a_div; int block_size; int tries; unsigned int n; int flash; if (page_size == 0) { page_size = 128; } if (strcmp(m->desc, "flash") == 0) { memtype = 'F'; flash = 1; } else if (strcmp(m->desc, "eeprom") == 0) { memtype = 'E'; flash = 0; } else { return -2; } if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO])) a_div = 2; else a_div = 1; if (n_bytes > m->size) { n_bytes = m->size; n = m->size; } else { if ((n_bytes % page_size) != 0) { n = n_bytes + page_size - (n_bytes % page_size); } else { n = n_bytes; } }#if 0 fprintf(stderr, "n_bytes = %d\n" "n = %u\n" "a_div = %d\n" "page_size = %d\n", n_bytes, n, a_div, page_size);#endif for (addr = 0; addr < n; addr += page_size) { report_progress (addr, n_bytes, NULL); if (addr + page_size > n_bytes) { block_size = n_bytes % page_size; } else { block_size = page_size; } /* Only skip on empty page if programming flash. */ if (flash) { if (stk500_is_page_empty(addr, block_size, m->buf)) { continue; } } tries = 0; retry: tries++; stk500_loadaddr(pgm, addr/a_div); buf[0] = Cmnd_STK_PROG_PAGE; buf[1] = (block_size >> 8) & 0xff; buf[2] = block_size & 0xff; buf[3] = memtype; stk500_send(pgm, buf, 4); stk500_send(pgm, &m->buf[addr], block_size); buf[0] = Sync_CRC_EOP; stk500_send(pgm, buf, 1); stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_NOSYNC) { if (tries > 33) { fprintf(stderr, "\n%s: stk500_paged_write(): can't get into sync\n", progname); return -3; } stk500_getsync(pgm); goto retry; } else if (buf[0] != Resp_STK_INSYNC) { fprintf(stderr, "\n%s: stk500_paged_write(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -4; } stk500_recv(pgm, buf, 1); if (buf[0] != Resp_STK_OK) { fprintf(stderr, "\n%s: stk500_paged_write(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -5; } } return n_bytes;}static int stk500_is_page_empty(unsigned int address, int page_size, const unsigned char *buf){ int i; for(i = 0; i < page_size; i++) { if(buf[address + i] != 0xFF) { /* Page is not empty. */ return(0); } } /* Page is empty. */ return(1);}static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes){ unsigned char buf[16]; int memtype; unsigned int addr; int a_div; int tries; unsigned int n; int block_size; if (strcmp(m->desc, "flash") == 0) { memtype = 'F'; } else if (strcmp(m->desc, "eeprom") == 0) { memtype = 'E'; } else { return -2; } if ((m->op[AVR_OP_LOADPAGE_LO]) || (m->op[AVR_OP_READ_LO])) a_div = 2; else a_div = 1; if (n_bytes > m->size) { n_bytes = m->size; n = m->size; } else { if ((n_bytes % page_size) != 0) { n = n_bytes + page_size - (n_bytes % page_size); } else { n = n_bytes; } } for (addr = 0; addr < n; addr += page_size) { report_progress (addr, n_bytes, NULL); if (addr + page_size > n_bytes) { block_size = n_bytes % page_size; } else { block_size = page_size; } tries = 0; retry: tries++; stk500_loadaddr(pgm, addr/a_div); buf[0] = Cmnd_STK_READ_PAGE; buf[1] = (block_size >> 8) & 0xff; buf[2] = block_size & 0xff; buf[3] = memtype; buf[4] = Sync_CRC_EOP; stk500_send(pgm, buf, 5); stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_NOSYNC) { if (tries > 33) { fprintf(stderr, "\n%s: stk500_paged_load(): can't get into sync\n", progname); return -3; } stk500_getsync(pgm); goto retry; } else if (buf[0] != Resp_STK_INSYNC) { fprintf(stderr, "\n%s: stk500_paged_load(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -4; } stk500_recv(pgm, &m->buf[addr], block_size); stk500_recv(pgm, buf, 1); if (buf[0] != Resp_STK_OK) { fprintf(stderr, "\n%s: stk500_paged_load(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -5; } } return n_bytes;}static int stk500_set_vtarget(PROGRAMMER * pgm, double v){ unsigned uaref, utarg; utarg = (unsigned)((v + 0.049) * 10); if (stk500_getparm(pgm, Parm_STK_VADJUST, &uaref) != 0) { fprintf(stderr, "%s: stk500_set_vtarget(): cannot obtain V[aref]\n", progname); return -1; } if (uaref > utarg) { fprintf(stderr, "%s: stk500_set_vtarget(): reducing V[aref] from %.1f to %.1f\n", progname, uaref / 10.0, v); if (stk500_setparm(pgm, Parm_STK_VADJUST, utarg) != 0) return -1; } return stk500_setparm(pgm, Parm_STK_VTARGET, utarg);}static int stk500_set_varef(PROGRAMMER * pgm, double v){ unsigned uaref, utarg; uaref = (unsigned)((v + 0.049) * 10); if (stk500_getparm(pgm, Parm_STK_VTARGET, &utarg) != 0) { fprintf(stderr, "%s: stk500_set_varef(): cannot obtain V[target]\n", progname); return -1; } if (uaref > utarg) { fprintf(stderr, "%s: stk500_set_varef(): V[aref] must not be greater than " "V[target] = %.1f\n", progname, utarg / 10.0); return -1; } return stk500_setparm(pgm, Parm_STK_VADJUST, uaref);}static int stk500_set_fosc(PROGRAMMER * pgm, double v){ unsigned prescale, cmatch, fosc; static unsigned ps[] = { 1, 8, 32, 64, 128, 256, 1024 }; int idx, rc; prescale = cmatch = 0; if (v > 0.0) { if (v > STK500_XTAL / 2) { const char *unit; if (v > 1e6) { v /= 1e6; unit = "MHz"; } else if (v > 1e3) { v /= 1e3; unit = "kHz"; } else unit = "Hz"; fprintf(stderr, "%s: stk500_set_fosc(): f = %.3f %s too high, using %.3f MHz\n", progname, v, unit, STK500_XTAL / 2e6); fosc = STK500_XTAL / 2; } else fosc = (unsigned)v; for (idx = 0; idx < sizeof(ps) / sizeof(ps[0]); idx++) { if (fosc >= STK500_XTAL / (256 * ps[idx] * 2)) { /* this prescaler value can handle our frequency */ prescale = idx + 1; cmatch = (unsigned)(STK500_XTAL / (2 * fosc * ps[idx])) - 1; break; } } if (idx == sizeof(ps) / sizeof(ps[0])) { fprintf(stderr, "%s: stk500_set_fosc(): f = %u Hz too low, %u Hz min\n", progname, fosc, STK500_XTAL / (256 * 1024 * 2)); return -1; } } if ((rc = stk500_setparm(pgm, Parm_STK_OSC_PSCALE, prescale)) != 0 || (rc = stk500_setparm(pgm, Parm_STK_OSC_CMATCH, cmatch)) != 0) return rc; return 0;}/* This code assumes that each count of the SCK duration parameter represents 8/f, where f is the clock frequency of the STK500 master processors (not the target). This number comes from Atmel application note AVR061. It appears that the STK500 bit bangs SCK. For small duration values, the actual SCK width is larger than expected. As the duration value increases, the SCK width error diminishes. */static int stk500_set_sck_period(PROGRAMMER * pgm, double v){ int dur; double min, max; min = 8.0 / STK500_XTAL; max = 255 * min; dur = v / min + 0.5; if (v < min) { dur = 1; fprintf(stderr, "%s: stk500_set_sck_period(): p = %.1f us too small, using %.1f us\n", progname, v / 1e-6, dur * min / 1e-6); } else if (v > max) { dur = 255; fprintf(stderr, "%s: stk500_set_sck_period(): p = %.1f us too large, using %.1f us\n", progname, v / 1e-6, dur * min / 1e-6); } return stk500_setparm(pgm, Parm_STK_SCK_DURATION, dur);}static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value){ unsigned char buf[16]; unsigned v; int tries = 0; retry: tries++; buf[0] = Cmnd_STK_GET_PARAMETER; buf[1] = parm; buf[2] = Sync_CRC_EOP; stk500_send(pgm, buf, 3); stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_NOSYNC) { if (tries > 33) { fprintf(stderr, "\n%s: stk500_getparm(): can't get into sync\n", progname); return -1; } stk500_getsync(pgm); goto retry; } else if (buf[0] != Resp_STK_INSYNC) { fprintf(stderr, "\n%s: stk500_getparm(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -2; } stk500_recv(pgm, buf, 1); v = buf[0]; stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_FAILED) { fprintf(stderr, "\n%s: stk500_getparm(): parameter 0x%02x failed\n", progname, v); return -3; } else if (buf[0] != Resp_STK_OK) { fprintf(stderr, "\n%s: stk500_getparm(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -3; } *value = v; return 0;} static int stk500_setparm(PROGRAMMER * pgm, unsigned parm, unsigned value){ unsigned char buf[16]; int tries = 0; retry: tries++; buf[0] = Cmnd_STK_SET_PARAMETER; buf[1] = parm; buf[2] = value; buf[3] = Sync_CRC_EOP; stk500_send(pgm, buf, 4); stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_NOSYNC) { if (tries > 33) { fprintf(stderr, "\n%s: stk500_setparm(): can't get into sync\n", progname); return -1; } stk500_getsync(pgm); goto retry; } else if (buf[0] != Resp_STK_INSYNC) { fprintf(stderr, "\n%s: stk500_setparm(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -2; } stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_OK) return 0; parm = buf[0]; /* if not STK_OK, we've been echoed parm here */ stk500_recv(pgm, buf, 1); if (buf[0] == Resp_STK_FAILED) { fprintf(stderr, "\n%s: stk500_setparm(): parameter 0x%02x failed\n", progname, parm); return -3; } else { fprintf(stderr, "\n%s: stk500_setparm(): (a) protocol error, " "expect=0x%02x, resp=0x%02x\n", progname, Resp_STK_INSYNC, buf[0]); return -3; }} static void stk500_display(PROGRAMMER * pgm, char * p){ unsigned maj, min, hdw, topcard; stk500_getparm(pgm, Parm_STK_HW_VER, &hdw); stk500_getparm(pgm, Parm_STK_SW_MAJOR, &maj); stk500_getparm(pgm, Parm_STK_SW_MINOR, &min); stk500_getparm(pgm, Param_STK500_TOPCARD_DETECT, &topcard); fprintf(stderr, "%sHardware Version: %d\n", p, hdw); fprintf(stderr, "%sFirmware Version: %d.%d\n", p, maj, min); if (topcard < 3) { const char *n = "Unknown"; switch (topcard) { case 1: n = "STK502"; break; case 2: n = "STK501"; break; } fprintf(stderr, "%sTopcard : %s\n", p, n); } stk500_print_parms1(pgm, p); return;}static void stk500_print_parms1(PROGRAMMER * pgm, char * p){ unsigned vtarget, vadjust, osc_pscale, osc_cmatch, sck_duration; stk500_getparm(pgm, Parm_STK_VTARGET, &vtarget); stk500_getparm(pgm, Parm_STK_VADJUST, &vadjust); stk500_getparm(pgm, Parm_STK_OSC_PSCALE, &osc_pscale); stk500_getparm(pgm, Parm_STK_OSC_CMATCH, &osc_cmatch); stk500_getparm(pgm, Parm_STK_SCK_DURATION, &sck_duration); fprintf(stderr, "%sVtarget : %.1f V\n", p, vtarget / 10.0); fprintf(stderr, "%sVaref : %.1f V\n", p, vadjust / 10.0); fprintf(stderr, "%sOscillator : ", p); if (osc_pscale == 0) fprintf(stderr, "Off\n"); else { int prescale = 1; double f = STK500_XTAL / 2; const char *unit; switch (osc_pscale) { case 2: prescale = 8; break; case 3: prescale = 32; break; case 4: prescale = 64; break; case 5: prescale = 128; break; case 6: prescale = 256; break; case 7: prescale = 1024; break; } f /= prescale; f /= (osc_cmatch + 1); if (f > 1e6) { f /= 1e6; unit = "MHz"; } else if (f > 1e3) { f /= 1000; unit = "kHz"; } else unit = "Hz"; fprintf(stderr, "%.3f %s\n", f, unit); } fprintf(stderr, "%sSCK period : %.1f us\n", p, sck_duration * 8.0e6 / STK500_XTAL + 0.05); return;}static void stk500_print_parms(PROGRAMMER * pgm){ stk500_print_parms1(pgm, "");}void stk500_initpgm(PROGRAMMER * pgm){ strcpy(pgm->type, "STK500"); /* * mandatory functions */ pgm->initialize = stk500_initialize; pgm->display = stk500_display; pgm->enable = stk500_enable; pgm->disable = stk500_disable; pgm->program_enable = stk500_program_enable; pgm->chip_erase = stk500_chip_erase; pgm->cmd = stk500_cmd; pgm->open = stk500_open; pgm->close = stk500_close; /* * optional functions */ pgm->paged_write = stk500_paged_write; pgm->paged_load = stk500_paged_load; pgm->print_parms = stk500_print_parms; pgm->set_vtarget = stk500_set_vtarget; pgm->set_varef = stk500_set_varef; pgm->set_fosc = stk500_set_fosc; pgm->set_sck_period = stk500_set_sck_period; pgm->page_size = 256;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?