Do we really need to fully send the value for IHRCR?
Wouldn't it be sufficient if we always start with 0xFF and allow the programmer to decrease the value by 1 when setting PA.6 high for one cycle?
That way the programmer has still control over IHRCR, albeit a tad slower, but a few milliseconds don't matter during calibration. But you wouldn't need to reset A to 0 and you wouldn't need the SL. Or do I miss something?
_STARTUP:
MOV A,0xFF ;immediate value 0xFF with all bits 1, will be changed to MOV A,0x12 (0x12 = determined calibration value) after calibration was done
_STARTUP_IHRCR:
MOV IHRCR, A ;set the calibration value
GOTO _CALIBRATION ;jump to calibration code, will be overwritten with NOP after calibration
;user code here
_CALIBRATION:
SET1 PAC.5 ;PA.5 as output, rest as input => this pin should exist on all devices, it is same as RESET pin
SET1 PA.5 ;set output of PA.5 to 1
T0SN PA.6 ;read bit from PA.6
ADD A,1 ;increment A
SET0 PA.5 ;set output of PA.5 to 0
GOTO _STARTUP_IHRCR
_STARTUP:
MOV A,0xFF ;immediate value 0xFF with all bits 1, will be changed to MOV A,0x12 (0x12 = determined calibration value) after calibration was done
_STARTUP_IHRCR:
MOV IHRCR, A ;set the calibration value
GOTO _CALIBRATION ;jump to calibration code, will be overwritten with NOP after calibration
;user code here
_CALIBRATION:
T0SN PA.6 ;read bit from PA.6
ADD A,1 ;increment A
SET1 PAC.5 ;PA.5 as output, rest as input => this pin should exist on all devices, it is same as RESET pin
SET1 PA.5 ;set output of PA.5 to 1
SET0 PA.5 ;set output of PA.5 to 0
GOTO _STARTUP_IHRCR
_STARTUP:
MOV A,0xFF ;immediate value 0xFF with all bits 1, will be changed to MOV A,0x12 (0x12 = determined calibration value) after calibration was done
_STARTUP_IHRCR:
MOV IHRCR, A ;set the calibration value
GOTO _CALIBRATION ;jump to calibration code, will be overwritten with NOP after calibration
;set SP, init .BSS, init .DATA, ...
;user code here
_CALIBRATION:
MOV A,0
SET1 PAC.5 ;PA.5 as output, rest as input => this pin should exist on all devices, it is same as RESET pin
_CAL_TOGGLE_LOOP:
SET1 PA.5 ;set output of PA.5 to 1
SET0 PA.5 ;set output of PA.5 to 0
SWAPC PA.6
SLC A
T0SN CF ;CF not set?
GOTO _CAL_TOGGLE_LOOP
GOTO _STARTUP_IHRCR
According to the PMS150C datasheet it boots with ILRC not IHRC. May need setting CLKMD before calibration.
To avoid strict timing requirements the loop can be rewritten to make it slower. In the code below it should be safe to change PA.6 any time PA.5 is low, and it should stay lowa lotlonger than high. On the programmer set a rising edge-triggered interrupt on PA.5, busy-wait until cleared, then change PA.6.
Also, accidentally shaved one instruction away. :-) At least if rewriting IHRCR and PAC with the same values has no side efects.
P.S.: Just figured what you guys meant by using the SPI to generate a pulse. It was supposed to be slave-mode on the programmer, right?
_STARTUP:
MOV A,0xFF ;immediate value 0xFF with all bits 1, will be changed to MOV A,0x12 (0x12 = determined calibration value) after calibration was done
_STARTUP_IHRCR:
MOV IHRCR, A ;set the calibration value
_CALIBRATION:
SET1 PAC.5 ;PA.5 as output (NOP after calibration)
SET1 PA.5 ;set output of PA.5 to 1 (NOP after calibration)
T0SN PA.6 ;read bit from PA.6 (NOP after calibration)
ADD A,1 ;increment A (NOP after calibration)
SET0 PA.5 ;set output of PA.5 to 0 (NOP after calibration)
GOTO _STARTUP_IHRCR
;user code here
* I also found 1 more instruction to "shave": we could now place the short calibration code in startup directly and overwrite all 6 instructions with NOP after calibration
* I also found 1 more instruction to "shave": we could now place the short calibration code in startup directly and overwrite all 6 instructions with NOP after calibration
Depends. For the 8-core pdk16, there is only 8 bytes in between the fppa7 entry point and the irq handler. You rourinte is 2 + 6 bytes, but once the 6 are overwritten by nop, the next instruction is already in the interrupt handler, so there is no space left for the goto to the startup routine.
Philipp
BTW: Somehow I managed with over voltage? to overwrite the PFS154 fixed chip ID section (with totally different value 0x0808). I still can read the IC reliable. The program inside does start but chip ERASE or WRITE to this section is not working anymore. Maybe I converted the flash part to OTP ?
BTW: Somehow I managed with over voltage? to overwrite the PFS154 fixed chip ID section (with totally different value 0x0808). I still can read the IC reliable. The program inside does start but chip ERASE or WRITE to this section is not working anymore. Maybe I converted the flash part to OTP ?
Did you try repeating the process (over volting) to change the ID?
@socram: I find the PNP transistors should be insufficient to block Vboost in reaching VPP and VDD. If Vboost>5V then the base voltage will be lower than the emitter's, there may be current, and the transistors may accidentally turn on.
I would suggest using 2 additional NPNs to connect VPP_EN and VDD_EN to ground when required.
An added bonus is that it would also work with 3.3V MCUs on the programmer.
digitalWrite(pin, LOW);
...
digitalWrite(pin, HIGH);
I'm using:digitalWrite(pin, LOW);
pinMode(pin, OUTPUT); // ground PNP base
...
pinMode(pin, INPUT); // high impedance PNP base
I'm open to suggestions and improvements. I had thought about getting an ATtiny261, running V-USB on it and have the smallest and simplest, all-DIP programmer.
uint16_t padauk_command(uint8_t cmd) {
padauk_spi_write( 0xA5A, 12);
padauk_spi_write(0x5A5A, 16);
padauk_spi_write(cmd, 4);
/*
padauk_spi_input();
padauk_spi_clock();
padauk_spi_clock();
padauk_spi_clock();
*/
padauk_spi_write(0, 3);
padauk_spi_input();
padauk_spi_clock();
uint16_t ack = padauk_spi_read(12);
padauk_spi_clock();
padauk_spi_output();
return ack;
}
uint16_t padauk_flash_read(uint16_t addr) {
padauk_spi_write(addr, 13);
padauk_spi_input();
uint16_t data = padauk_spi_read(14);
// padauk_spi_output();
padauk_spi_clock();
padauk_spi_output();
return data;
}
Well I received yesterday some PFS154s, and I already have managed to get have them programmed. I've made the programmer as simple and as hobbyist-friendly as possible, using only DIP parts.
For writing, after sending the command it sets VDD_33_EN to high impedance, and then immediately lowers VDD_SMPS_EN, thus connecting both VPP and VDD to 5.8V, which seems to be the required voltage for programming.
I'm open to suggestions and improvements. I had thought about getting an ATtiny261, running V-USB on it and have the smallest and simplest, all-DIP programmer.
Regarding the voltage generation, I am considering replacing the whole thing with two buck/boost 2-switch converters, so I can switch the VCC before going inside the converter, rather than the 8V coming from the converter. That would also let me remove the HT7133.
Version | LDOs | NMOS | PNPs | NPNs | Diodes | Inductors | Resistors | Capacitors | VDD range | VPP range |
v1 (original) | 1 | 1 | 3 | 0 | 1 | 1 | 8 | 2 | 3.3V + 5V~8V | 5V~8V |
v1 (fixed high-side) | 1 | 3 | 3 | 0 | 1 | 1 | 10 | 2 | 3.3V + 5V~8V | 5V~8V |
v2 | 0 | 0 | 2 | 2 | 2 | 2 | 8 | 2 | 0V~8V | 5V~8V |
I think you still need a way to switch on and off VDD. If you rely only on the boost converter there will be very slow ramps. This could lead to malfunctioning of the reset circuit in the MCU. This could be a rare occurence, though.
*Just to clarify, I am not looking into creating a "competing" github repository to free-pdk. I'd be happy to put relevant information there. But I was honestly not aware who is running it due to a lack of identifiable members on the site. Also someone would need to grant write access to me.
Tim
Added you to free-pdk organization on github*.