![]() |
Forum Index : Microcontroller and PC projects : How about a PROGRAM command?
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Geoff (also needs Jim) Thinking about the cost of Micromite issue, the fact that they need updating and that they sometimes get "bricked" how about putting a bit of code into all Micromites that allow them to program a second chip. This is something commonly done with Arduino. The Micromite would need a small amount of code and a new command to wiggle three data lines connected to PGD, PGC and RESET on the new chip. MMEdit would need a small update to execute the command and take a hex file and send it to the "host" Micromite. MicroBlock has done the work on a PIC16 to waggle the lines so it is clearly doable. Doing this would mean that anyone would only ever need to buy one Micromite and then they would be able to program any variant (MM2 and MM+). Keeping this one chip for programming only would also ensure that if they ever bricked a chip it could be recovered. |
||||
dasyar Regular Member ![]() Joined: 13/04/2015 Location: United StatesPosts: 58 |
This sounds like an excellent idea, I give it a +1, for the idea. I started with the uMite by purchasing four 28 pin chips from CircuitGizmos, now these chips are almost out of date, because of the new version of MMbasic that is available. I do not know how, or would I even consider reprogramming the chips, in the PicKit method. So, hopefully the above mentioned method could be a simple, fool-proof method of getting my chips up to date. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
Don't be scared of programming the chips. With a PK3 and IPE, or Rob's ascii ICSP and PIC32PROG, it is really very painless. ![]() Rob's method is definitely the cheapest and easiest way. I might be missing something here, but if you had a chip - lets say a 170 - with the ability to program a virgin chip with it's software, that still won't get you around the update process. You can clone what you have, but you could not update to a new firmware as the 170 has no SD card. The MM+ might be a different story, cos it does have SD card support, so could read the HEX file. I have a feeling speed is a big, big issue here, and although conceptually one MM can program another, did I not read somewhere in all that discussion that the program time was expected to be 15-20 MINUTES per chip? PK3 does it in a few seconds, and Rob's method is only slightly slower then that. ...not to insult anyone or put down any efforts - I am just saying, is all, and I could well be wrong on that time I mention for all I know... Smoke makes things work. When the smoke gets out, it stops! |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
I'm proposing the hex file is downloaded from MMEdit so a 170 could program a 470 and visa versa with any version of the software i.e. updates I think you are thinking of a Basic program PeterC wrote many years ago. I'm talking about code as part of the MM firmware which would be at least as fast as Rob/MicroBlocks approach. Remember a PicKit3 is just a PIC24FJ256 with some hardware that does things like generate VPP voltages for old PICs that don't have low voltage programming. We don't need anything other than 3.3V signals. |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9610 |
Understood. ![]() Looks like I had my wires a bit twisted there. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
twofingers![]() Guru ![]() Joined: 02/06/2014 Location: GermanyPosts: 1593 |
@Peter: I would expect a CFunction would be fine to do that job. That's more flexible than a additional firmware command, IMHO. ed: I like the idea to use a MM as programmer! ![]() @Grogs: PeterCs (G8JCF) MMProg32RPC (in THIS famous thread) made it in ~4 min (MX170). Not bad, i think. ![]() Regards Michael causality ≠ correlation ≠ coincidence |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
I am having a bit of an unlucky experience with my PCB provider. Already sent but i never received it. The solution i made for programming the PIC32 range is combined with a USB-Serial, so instead of buying a USB-Serial and a programmer it is all in one. Currently i have only the preprogrammed chip available (4.95US$) and if i get that pcb problem sorted it will be 9.95US$ for the USB-Serial/Programmer module. At a bare minimum you need the chip and a capacitor to get both the USB-Serial AND the programmer function to work. A little fancier is adding some LEDs and a switch to have some visual feedback. Details here:http://www.thebackshed.com/forum/forum_posts.asp?TID=7990&PN=4&TPN=2 Just to clarify. It is not only wiggling some pins, there is a lot of logic needed and the way Rob solved that is by using the pic32prog programm as the brains and then sending commands over USB so the chip can execute those commands. If you need a PROGRAM command all that logic that is in pic32prog has to be programmed in the firmware which would need a lot more flash capacity. You would then still need a USB-Serial to transfer the HEX file. Microblocks. Build with logic. |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
I have thought about making a MMEdit style wrapper for pic32prog. The Arduino it uses (complete with USB-serial) is cheaper than a bare MX150/MX170 and readily available. The few extra components still make it the cheapest and easiest system to use. A CFUNCTION which emulates the Arduino and lets you use the pic32prog program would be a nice addition to the choices. Jim VK7JH MMedit |
||||
CircuitGizmos![]() Guru ![]() Joined: 08/09/2011 Location: United StatesPosts: 1427 |
That would be pretty cool, really. If you have two micromites you could load the c function and use your wrapper to program the other chip with the newest code. Then turn around and use the second chip to update the first. Micromites and Maximites! - Beginning Maximite |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
I'll have a go at it tomorrow. Coupled with a wrapper for Pic32prog in MMEdit that sounds like a good compromise ![]() |
||||
Geoffg![]() Guru ![]() Joined: 06/06/2011 Location: AustraliaPosts: 3292 |
A CFunction would be the perfect solution. There is not enough spare flash in the MX170 to make this function a permanent part of MMBasic but a CFunction would do the job almost as well. Geoff Graham - http://geoffg.net |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
this should get you started: [code] typedef enum _AI_STATES {AI_IDLE, AI_ACTIVE} AI_STATE; typedef enum _AI_EVENTS {AI_ACTIVATE, AI_DEACTIVATE} AI_EVENT; //Define pins that are used for programming #define PGC_INACTIVE TRISAbits.TRISA4 = 1 #define PGC_OUTPUT TRISAbits.TRISA4 = 0 #define PGC_LOW LATAbits.LATA4 = 0 #define PGC_HIGH LATAbits.LATA4 = 1 #define PGC_PULSE PGC_HIGH;PGC_LOW /* //Define pins that are used for programming #define PGC_INACTIVE TRISCbits.TRISC0 = INPUT_PIN #define PGC_OUTPUT TRISCbits.TRISC0 = OUTPUT_PIN #define PGC_LOW LATCbits.LATC0 = 0 #define PGC_HIGH LATCbits.LATC0 = 1 #define PGC_PULSE PGC_HIGH;PGC_LOW */ #define PGD_INACTIVE TRISAbits.TRISA5 = INPUT_PIN #define PGD_OUTPUT TRISAbits.TRISA5 = OUTPUT_PIN #define PGD_INPUT TRISAbits.TRISA5 = INPUT_PIN #define PGD_LOW LATAbits.LATA5 = 0 #define PGD_HIGH LATAbits.LATA5 = 1 #define PGD_READ PORTAbits.RA5 //Simulate OC output #define MCLR_INACTIVE TRISCbits.TRISC3 = INPUT_PIN #define MCLR_INPUT TRISCbits.TRISC3 = INPUT_PIN #define MCLR_LOW LATCbits.LATC3 = 0;TRISCbits.TRISC3 = OUTPUT_PIN #define MCLR_HIGH TRISCbits.TRISC3 = INPUT_PIN #define MCLR_OUTPUT MCLR_LOW #define MCLR_PULSE MCLR_LOW;Nop();Nop();MCLR_HIGH #define C4_NOREAD PGD_INPUT;PGC_PULSE;PGC_PULSE;PGD_OUTPUT #define C4_00 PGD_LOW; PGC_PULSE; PGC_PULSE;C4_NOREAD #define C4_01 PGD_LOW; PGC_PULSE;PGD_HIGH;PGC_PULSE;C4_NOREAD #define C4_10 PGD_HIGH;PGC_PULSE;PGD_LOW; PGC_PULSE;C4_NOREAD #define C4_11 PGD_HIGH;PGC_PULSE; PGC_PULSE;C4_NOREAD #define C4R_READ PGD_INPUT;PGC_PULSE;B=PGD_READ;PGC_PULSE;PGD_OUTPUT #define C4R_00 PGD_LOW; PGC_PULSE; PGC_PULSE;C4R_READ #define C4R_01 PGD_LOW; PGC_PULSE;PGD_HIGH;PGC_PULSE;C4R_READ #define C4R_10 PGD_HIGH;PGC_PULSE;PGD_LOW; PGC_PULSE;C4R_READ #define C4R_11 PGD_HIGH;PGC_PULSE; PGC_PULSE;C4R_READ char RS232_Out_Data[CDC_DATA_IN_EP_SIZE]; BOOL AI_RaiseEvent(AI_EVENT e); void AI_Timer1ms(); char AI_isStartSequence(char c); void AI_Activate(); void AI_DeActivate(); char AI_ProcessUSBToProgrammer(void); BYTE clockIn1(BYTE D); [/code] [code] /******************************************************************* * A port of the ascii ICSP protocol for a PIC16F145(4/5/9) * by Microblocks. 2015-09-22 * * This is part of the U2SP5 Microblock that contains * a USB-Serial adapter, PIC32 programmer, Analog current logging * and maybe a few more.... :) * * Details can be found on https://github.com/MicroBlocks/BBM-Series * * Original code for arduino nano by Robert Rozee. Source on github * (https://github.com/robert-rozee/pic32prog/blob/master/bitbang/ICSP_v1E.ino) * * Software license..... what software license? It is on the internet! * I would appreciate if you left this header with the source code. *******************************************************************/ /** INCLUDES *******************************************************/ #include "USB/usb.h" #include "USB/usb_function_cdc.h" #include "HardwareProfile.h" #include "Mode.h" #include "ASCII_ICSP.h" const UINT16 AI_TimeOut = 10000; //Ten seconds of inactivity will drop the //module out of Programmer mode and into USBSerial mode unsigned char SequenceCounter; AI_STATE AI_State = AI_IDLE; UINT16 TimerTicks; BYTE LastDelay = 0; BYTE BufferIndex= 0; BOOL BufferEmpty = TRUE; BYTE BufferLength = 0; int PrAcc = 1; // accumulated PrAcc flag //Activate/Deactivate PROGRAMMER Mode. //This is under control of 'Main ProcessIO' BOOL AI_RaiseEvent(AI_EVENT e) { switch(e) { case AI_ACTIVATE: AI_Activate(); //Setup all the Programmer Pins AI_State = AI_ACTIVE; break; case AI_DEACTIVATE: AI_DeActivate(); //Set all pins into high impedance input mode AI_State = AI_IDLE; break; } return AI_State == AI_ACTIVE; } void AI_Activate() { //Setup variables and PINS TimerTicks = 0; LastDelay = 0; PGC_LOW;PGC_OUTPUT; PGD_LOW;PGD_OUTPUT; //MCLR_LOW;MCLR_OUTPUT; } void AI_DeActivate() { //put all pins in high impedance mode PGC_INACTIVE; PGD_INACTIVE; MCLR_INACTIVE; //POWER_OFF } //Copy data from the USB to the shared buffer char AI_ProcessUSBToProgrammer(void) { char v = 0;BYTE J; BYTE B; if(AI_State != AI_ACTIVE) return 0; if (BufferEmpty == TRUE) { BufferLength = getsUSBUSART(RS232_Out_Data, CDC_DATA_IN_EP_SIZE); if(BufferLength > 0) { BufferEmpty = FALSE; BufferIndex = 0; } } while(v == 0 && BufferEmpty == FALSE && LastDelay == 0) { //Read character from buffer and process it. //Unless a delay is requested then skip processing //and leave character in buffer for next time. char c = RS232_Out_Data[BufferIndex]; TimerTicks = 0; //Keep PROGRAMMER Mode active. BufferIndex += 1; if (BufferIndex == BufferLength) { BufferEmpty = TRUE; } //Check the character, most often used ones first for increased speed. if(c >= 'i') { if(c <='x') { J = (c - 'i') & 15; if (J & 1) {C4_10;} else {C4_00;} if (J & 2) {C4_10;} else {C4_00;} if (J & 4) {C4_10;} else {C4_00;} if (J & 8) {C4_10;} else {C4_00;} continue; } else if (c == 'z') { C4_01;C4_00; continue; } } else if (c == 'a') { C4_01;C4_00;C4_00; continue; } else if (c == 'e') { C4_01; continue; } else if (c == 'g') { C4_11; continue; } else if (c >= 'I') { if (c <= 'Z') { J = (c - 'i' & 15); //v = 'I' + clockIn16(J); if(J & 1) {C4R_10;} else {C4R_00;} v = B; if(J & 2) {C4R_10;} else {C4R_00;} v |= B << 1; if(J & 4) {C4R_10;} else {C4R_00;} v |= B << 2; if(J & 8) {C4R_10;} else {C4R_00;} v |= B << 3; v += 'I'; break; } } if (c == 'd'){ C4_00; continue; } else if (c == 'f') { C4_10; continue; } switch (c) { case 'D': C4R_00;v = '0' + B; // TDI = 0, TMS = 0, read_flag = 1 break; case 'E': C4R_01;v = '0' + B; // TDI = 0, TMS = 1, read_flag = 1 break; case 'F': C4R_10;v = '0' + B; // TDI = 1, TMS = 0, read_flag = 1 break; case 'G': C4R_11;v = '0' + B; // TDI = 1, TMS = 1, read_flag = 1 break; case 'A': C4_01;C4_00;C4R_00; // TDI = 0, TMS = 1-0-0, read_flag = 1 v = '0' + B; break; case '+': C4_00;if (!B) {PrAcc = 0;} // TDI = 0, TMS = 0, accumulate PrAcc // remember if any error ('0') continue; // '>', '.', '=': handshake and formatting commands, placed here for possible speed case '>': v = '<'; // request a sync response of '<' break; case '=': v = PrAcc ? '1' : '0'; // retrieve value of PrAcc PrAcc = 1; break; // '0','1': used to clock out "MCHP" signature for ICSP entry case '0': PGD_LOW; PGC_PULSE; continue; // clock out a 0 bit on PGD pin case '1': PGD_HIGH; PGC_PULSE; continue; // clock out a 1 bit on PGD pin case '-': v = '0' + clockIn1(1); break; // clock in single PGD bit // '2','3': pulse MCLR high, clock out signature, set MCLR high case '2': MCLR_LOW; continue; // set MCLR low case '3': MCLR_HIGH; continue; // set MCLR high // '4','5': control power supply to target case '4': // turn power to target OFF PGC_LOW; // PGC = 0 PGD_LOW; // PGD = 0 MCLR_LOW; // hold target in reset //POWER_OFF; continue; case '5': // turn power to target ON PGC_LOW; // PGC = 0 PGD_LOW; // PGD = 0 MCLR_LOW; // hold target in reset //POWER_ON; continue; // miscellaneous other commands case '8': LastDelay = 10; continue; // insert 10mS delay case '?': v = '?';break; // return ID string, "ascii ICSP v1X" default: continue; // invalid input - skip it } if(v != 0) { // If a return value is available break out of the while break; // The value will then be placed in the output buffer. } } return v; } // USBCB_SOF Hook. HS USB will call this every 1 millisecond. // It is used for delays and timeouts. void AI_Timer1ms() { if(LastDelay > 0) { LastDelay -= 1; } } [/code] Microblocks. Build with logic. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Microblock Thanks for the code. Unfortunately this doesn't convert to a Cfunction very easily. Switch statements generate non-position independent code and I'm fairly sure that "continue" doesn't work either for the same reason. Personally, I never use either break (other than in switch statements) or continue as I find they make the code very difficult to read. In your code above am I correct in understanding the continue commands cause the program flow to immediately exit all further processing of the block " while(v == 0 && BufferEmpty == FALSE && LastDelay == 0) { } " so that the while clause is then retested? Thanks Peter |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
It exits the while when there is no more data in the input buffer (in this case the USB input buffer). When new data arrives this function is called again,and the first thing it does is reading from the buffer. LastDelay is a way of creating a non-blocking delay. It exits the while also until LastDelay is counted down to 0, which is done in a routine that is called every 1Ms by the USB driver. For use in a MicroMite you would need to setup a timer for that and also use a serial input buffer. It might even be possible to do this in BASIC and only implement the wiggling of the IO pins in a CFunction. The switch statements could be changed into a bunch of If Then Else's but it gets a bit more difficult to read and it is also slower. The continue and breaks are used for speed improvements. Maybe the source for the Nano might be a better starting point as i optimized this code for speed only, not for readability. :) Microblocks. Build with logic. |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |