Skip to main content
Topic: Added Support for USBASP in picprog (Read 22030 times) previous topic - next topic

Added Support for USBASP in picprog

Hi,

I added support for another programmer named usbasp (WoW.fischl.de/usbasp) to picprog.
If you have a USBASP programmer you need to download the attached modified firmware (make your own changes like assign USB and ISP pins, different clock?), build it and flash it into your usbasp.
The next step would be to checkout picprog from here: code.google.com/p/dangerous-prototypes-open-hardware/source/checkout
apply the attached patch, build it and test it.

(I had to encrypt urls party because: "Your post looks too spamy for a new user, please remove off-site URLs")

EDIT: for now only reading from the device works, but I will fix this asap
EDIT2: fixed and updated attachements. There is one issue: it seems like the write buffer doesnt get cleared to 0xff so if the length of the file mod 64 isn't 0 you get some garbage at the end.

Thanks!


Re: Added Support for USBASP in picprog

Reply #2
Nice :-). If you would clean-up the code a bit, it might even get to the repo ;)

Re: Added Support for USBASP in picprog

Reply #3
Of course I am aiming for the repo! ;-)

I have some more PICs here for testing (PIC16F628A, PIC24FJ32GB002, PIC32MX220, DSPI33FJ128MC804) so I guess I will implement all the PIC types (24 and dspic are the same?), clean it up and request access to repo heaven afterwards. :-)

Has somebody actually tried it? Shall I supply some HEX files here for the most common configurations?

Re: Added Support for USBASP in picprog

Reply #4
AMX,

yes, please do that.
I'm currently struggling with flashing a PIC32MX220f032B.
It isn't well supported by the Microchip tools yet.
So your code would ve really helpful, and I'd like to try it.

Cheers
Cyk

Re: Added Support for USBASP in picprog

Reply #5
Awesome! Except nothing to test it on. :/

Guess I'd only need it once, to flash a proper PIC programmer.

Re: Added Support for USBASP in picprog

Reply #6
Thanks for the feedback, so I will implement PIC32 support next. When it is done I will post it here, stay tuned! :-)

Re: Added Support for USBASP in picprog

Reply #7
AMX,

as I'm currently trying to get OpenOCD running with PIC32, I'd be interested to stay in touch with you.
Is there any forum, blog, mailing list, or whatever we could use for this project?

OpenOCD is interesting in this case, because the PGD/PCD interface of the PIC32 is in fact a JTAG
interface.
The MIPS core of the PIC32 already had a JTAG implementation.
Instead of adding a separate 2-wire programming interface, Microchip added a 2-wire to 4-wire
extension logic to the chip.
So, to programm or debug a PIC32, you have to use the usual JTAG functions, reduce the signals
from 4-wire to 2-wire, send it to the chip, the chip extends it to 4-wire again, and sends it to
it's JTAG interface.

So, if you want to use a 2-wire interface for flashing and debugging, all you would have to do
is adding a 4-wire to 2-wire translation to OpenOCD.
This way, you could use any Interface that OOCD already supports, even the cheap USB Blaster
clones (5$) from china.

Not only for flashing, but also for debugging.

Re: Added Support for USBASP in picprog

Reply #8
Hi Cyk,

I read the PIC32 programming specification (61145J.pdf). So far I implemented a 4-phase/2-wire function in the usbasp firmware plus a readback function (to readback TDO response in case its needed) but I havent tested it yet. The PIC32 is wired up already and I am currently modifying my test program to see if I can get some feedback from device.

Regarding OpenOCD, I guess the aforementioned 4ph/2w function is exactly what you were looking for, a simple 4-wrire -> 2wire translation. I checked ebay for the USB Blaster, seems like they are using the Cy7C68013 (or FT232) and by accident I just ordered one of these Cy7C68013 "Logic Analyzer" boards a few weeks ago (got sdcc installed already). I also have one of these FT232 Sparkfun breakout boards.

I registered on the OpenOCD mailing list.

Re: Added Support for USBASP in picprog

Reply #9
Hey!

Regarding the PIC32MX flash programming specification. I am struggling to build a simple PIC32 flasher and found some issues with this spec. I have PIC32MX210F016B which has only 4kB of RAM, and I am not so sure whether the PE-method will serve due to too small amount of RAM. So, I was about to go with the direct method of flashing (without Programming Executive), but it seems that the table 13-1 describing the flashing part contains errors (see the microchip forum as well) :-O If you have any progress on the latter method please keep me in the loop.

-T

Re: Added Support for USBASP in picprog

Reply #10
tekaikko,

I don't know about this error, but OpenOCD is using their own code instead of the PE.
You can find it in /contrib/loaders/flashpic32mx.s

It seems to be rather small.

Re: Added Support for USBASP in picprog

Reply #11
Tekaikko, You should be able post links soon, please can you provide the links for the datasheet discrepency?  I only managed to turn up one thread and it listed everything but programming spec. (http://www.microchip.com/forums/tm.aspx ... 79&mpage=1)

Below is the implementation I'm using, it might not be a "drop in" It was pulled out of it's project and cleaned up here in the forum editor so I may of missed something.. Seems most of the changes are BNE offsets, IIRC I had to fine tune these in the MPLAB simulator.
Code: [Select]

uint32_t NVMcommands[] = {
// Prime SRAM
//Step 1
  0x3c10A000 // Sram base //0
//Step 2
, 0x3c080000 // data H //1
, 0x35080000 // data L //2
, 0xAE080000 // offset (inc by 4) //3

// flash
//Step 1: Initialize some constants.
, 0x3c04bf80 //lui a0,0xbf80 //4
, 0x3484f400 //ori a0,a0,0xf400 //5
, 0x34050000 //ori a1,$0,0x4001 //6
, 0x34068000 //ori a2,$0,0x8000 //7
, 0x34074000 //ori a3,$0,0x4000 //8
, 0x3c11aa99 //lui s1,0xaa99 //9
, 0x36316655 //ori s1,s1,0x6655 //10
, 0x3c125566 //lui s2,0x5566 //11
, 0x365299aa //ori s2,s2,0x99aa //12
, 0x3c13ff20 //lui s3,0xff20 //13
, 0x3c100000 //lui s0,0x0000 //14
//Step 2: Set NVMADDR with the address
, 0x3c080000 //lui t0,<FLASH_ROW_ADDR(31:16)> //15
, 0x35080000 //ori t0,t0,<FLASH_ROW_ADDR(15:0)> //16
, 0xac880020 //sw t0,32(a0) //17
//Step 3: Set NVMSRCADDR with the physical source SRAM address.
, 0x36100000 // ori s0,s0,<RAM_ADDR(15:0)> //18
//Step 4: Set up NVMCON for write operation and poll LVDSTAT.
, 0xac850000 //sw a1,0(a0) //19
// delay (6 us)
//here1:
, 0x8C880000 //lw t0,0(a0) //20
, 0x31080800 //andit0,t0,0x0800 //21
//, 0x1500fffd //bne t0,$0,<here1> //22
, 0x1500fff4 //bne t0,$0,<here1> //22
, 0x00000000 //nop //23
//Step 5: Unlock NVMCON and start write operation.
, 0xac910010 //sw s1,16(a0) //24
, 0xac920010 //sw s2,16(a0) //25
, 0xac860008 //sw a2,8(a0) //26
//Step 6: Repeatedly read the NVMCON register and poll for WR bit to get cleared.
//here2:
, 0x8c880000 //lw t0,0(a0) //27
, 0x01064024 //and t0,t0,a2 //28
//, 0x1500fffd //bne t0,$0,<here2> //29
, 0x1500fff4 //bne t0,$0,<here2> //29
, 0x00000000 //nop //30
//Step 7: Wait at least 500 ns after seeing a 0 in NVMCON<15> before writing to any NVM registers. This requires inserting NOP in the execution.
, 0x00000000 //nop //31
, 0x00000000 //nop //32
, 0x00000000 //nop //33
, 0x00000000 //nop //34
//Step 8: Clear NVMCON.WREN bit.
, 0xac870004 //sw a3,4(a0) //35
//Step 9: Check the NVMCON.WRERR bit
, 0x8c880000 //lw t0,0(a0) //36
, 0x30082000 //andit0,zero,0x2000 //37
//, 0x1500ffdc //bne t0, $0, <err_proc_offset>//38
, 0x1500FF64 //bne t0, $0, <err_proc_offset>//38
, 0x00000000 //nop //39
};

void program_word (unsigned addr, unsigned word)
{
uint16_t addrH, addrL, dataH, dataL;
addrH = addr >> 16;
addrL = addr;
dataH = word >> 16;
dataL = word;

// if (debug_level > 0)
{
fprintf (stderr
, "stampit2: program word at %04x:%04x %04x:%04x n"
, addrH, addrL
, dataH, dataL
);
}
/* Without PE. */
uint16_t bufferOffset = 0;
uint16_t c = 0;

// ram buffer
fprintf(stderr, "stampIT2: ram buffern");
// : 0-3
xferinst(NVMcommands[0]);
xferinst(NVMcommands[1] | dataH);
xferinst(NVMcommands[2] | dataL);
xferinst(NVMcommands[3] | bufferOffset);
// flash write
fprintf(stderr, "stampIT2: flash write startn");
// Step1: 4-14 Init
xferinst(NVMcommands[4]);
xferinst(NVMcommands[5]);
uint32_t optype = 0x4001;//word write
//uint32_t optype = 0x4003;//row write 128 words
//uint32_t optype = 0x4004;//page erase
//uint32_t optype = 0x4005;//PFM erase
xferinst(NVMcommands[6] | optype);
for(c=7;c<=14;c++)
xferinst(NVMcommands[c]);
// Step2: 15-17
xferinst(NVMcommands[15] | addrH);
xferinst(NVMcommands[16] | addrL);
xferinst(NVMcommands[17]);
// Step3: 18
xferinst(NVMcommands[18] | bufferOffset);
// Step4: 19-23
xferinst(NVMcommands[19]);
usleep(600);
for(c=20;c<=23;c++)
xferinst(NVMcommands[c]);
// Step5: 24-26
for(c=24;c<=26;c++)
xferinst(NVMcommands[c]);
// Step6: 27-30
for(c=27;c<=30;c++)
xferinst(NVMcommands[c]);
// Step7: 31-34
for(c=31;c<=34;c++)
xferinst(NVMcommands[c]);
// Step8: 35
xferinst(NVMcommands[35]);
// Step9: 36-39
for(c=36;c<=39;c++)
xferinst(NVMcommands[c]);
fprintf(stderr, "stampIT2: flash write endn");
return;
}

/*
 * Flash write, 1-kbyte blocks.
 */
void program_block (unsigned addr, unsigned *data)
{
unsigned nwords = 256;
unsigned words_written;

// if (debug_level > 0)
fprintf (stderr, "stampIT2: program %d bytes at %08xn", nwords*4, addr);

uint16_t addrH, addrL, dataH, dataL;
addrH = addr >> 16;
addrL = addr;
/* Without PE. */

uint16_t c = 0;
// data = 1024 bytes, 256 words
// row = 128 words
uint8_t rowCur = 0,rowNeed = 2;
uint32_t dataOffset = 0, bufferOffset = 0;
for(;rowCur<rowNeed;rowCur++)
{
// ram buffer
fprintf(stderr, "stampIT2: ram buffern");
uint16_t wordCur = 0, wordNeed = 128;
dataOffset += bufferOffset;
uint32_t* row = data+dataOffset;
bufferOffset = 0;
uint32_t rowValid = 0;
for(wordCur=0;wordCur<wordNeed;wordCur++)
{
uint32_t word = *(row+bufferOffset);
//fprintf(stderr," %08x -> %08x <- %08xn",addr+dataOffset+bufferOffset,word,bufferOffset);
if(word!=0xFFFFFFFF)
{
rowValid += 1;
}
bufferOffset += 4;
}
if(!rowValid)
{
fprintf(stderr,"stampIT2: Skipping empty rown");
continue;
}
else {
fprintf(stderr, "stampIT2: row=%u words=%un",rowCur,rowValid);
}
bufferOffset = 0;
///////////
// TODO
// rowValid is a word count
// write small count as words not rows
///////////
uint32_t lastWord = 0;

xferinst(NVMcommands[0]); // Ram base

for(wordCur=0;wordCur<wordNeed;wordCur++)
{
uint32_t word = *(row+bufferOffset);
dataH = word >> 16;
dataL = word;
if(wordCur==0 || word != lastWord)
{ // Already buffered only need cmd3
    xferinst(NVMcommands[1] | dataH);
    xferinst(NVMcommands[2] | dataL);
}
fprintf(stderr," %08x -> %08x <- %08xn",addr+dataOffset+bufferOffset,word,bufferOffset);
lastWord = word;
xferinst(NVMcommands[3] | bufferOffset);
bufferOffset = bufferOffset + 4;
}
// flash write
fprintf(stderr, "stampIT2: flash write startn");
// Step1: 4-14 Init
xferinst(NVMcommands[4]);
xferinst(NVMcommands[5]);
//uint32_t optype = 0x4001;//word write
uint32_t optype = 0x4003;//row write 128 words
//uint32_t optype = 0x4004;//page erase
//uint32_t optype = 0x4005;//PFM erase
xferinst(NVMcommands[6] | optype);
for(c=7;c<=14;c++)
xferinst(NVMcommands[c]);
// Step2: 15-17
xferinst(NVMcommands[15] | addrH);
xferinst(NVMcommands[16] | addrL);
xferinst(NVMcommands[17]);
// Step3: 18
xferinst(NVMcommands[18] | bufferOffset);
// Step4: 19-23
xferinst(NVMcommands[19]);
usleep(600);
for(c=20;c<=23;c++)
xferinst(NVMcommands[c]);
// Step5: 24-26
for(c=24;c<=26;c++)
xferinst(NVMcommands[c]);
// Step6: 27-30
for(c=27;c<=30;c++)
xferinst(NVMcommands[c]);
// Step7: 31-34
for(c=31;c<=34;c++)
xferinst(NVMcommands[c]);
// Step8: 35
xferinst(NVMcommands[35]);
// Step9: 36-39
for(c=36;c<=39;c++)
xferinst(NVMcommands[c]);
}

fprintf(stderr, "stampIT2: flash write endn");
return;
}


Regarding the PE I haven't got around to pulling it apart, I expect there are multiple hard coded addresses and sizes. The word program might function correctly without modifications, but the row/page functions are the wrong sizes.
  I had some issues getting the PE to load, turned out I followed a bad example of someone who followed mchp bad example, the datasheet gives correct procedure to setup BMX Pickit and copies are likely hardcoded to 32k.

Re: Added Support for USBASP in picprog

Reply #12
Thanks a lot both of you!

AndThen, this is the piece of code I was referring to (more or less like in Flash Programming Spec 61145J). I've been taking a further look at it today, and finally I think there are two minor "issues" there.

1) In the spec (and in the code you posted), step 18, NVMSRCADDR is not really written. However, by default I guess this should work if you use RAM offset zero since NVMSRCADDR has zero in it after processor reset. I would put "0xac900040        // sw  $s0, 64($a0)" after step 18.

2) the spec 61145J mentions a jump to error processing routine, but this part is not defined. This was confusing me a bit as well. I was thinking of just leaving out the last few commands and believe blindly that everything is ok, I really just want to get a bootloader flashed into the PIC32 for now...

I should be able to test the code later this week, right now I'm too tired.

Thanks again for your help!!

Re: Added Support for USBASP in picprog

Reply #13
I cant get the patch to work. is it outdated or something? im under Win7 so trying to use gnu patcher without success..

Is it possible to get the compiled binaries somewhere? Also, does this work with the pic16? are there any limitations like, do i need other libraries etc?

Thank you!

Re: Added Support for USBASP in picprog

Reply #14
I know I am bumping and that people don't like that, but for those that might read this now or in the future:

The command to checkout svn to get the patch file working:
svn co http://dangerous-prototypes-open-hardwa ... atePICprog -r 1533 picprog
(put the whole url in there)

then put the patchfile in the just created picprog directory and run this:
patch -p0 < picprog-usbasp.patch

Works for me.