Context
Following a tutorial, I build a simple PIC programmer hardware using the Raspberry Pi (google: rpp programmer). I tested it with the provided software for a PIC16F628A,and the result is working.
I am currently implementing my own software, with the goal to program the Pic16F170x family. The new software is able to read correctly the Pic16F628A, but on the Pic16F1703 it only read up to the first value>=0x2000 (MSB=1), after that, all values return 0. If the program skip those values, it read all the pic program memory "correctly", so I guess the writing is correct.
Question
Why the programmer stop reading correctly after the first program word with MSB=1?
Or in a more generic way:
How to read the PIC16F170X program memory?
Program
I use the following program to read the pic (simplified code):
// Values only used for Pic16F1703
int delay= 2; //us
uint8_t ReadDataFromProgramMemory = 0x04;
uint8_t IncrementAddress = 0x06;
// End values
virtual void readProgram() const
{
// Enter programming mode
gpio->set(pinMclr);
usleep(delay);
// Read
for ( int i=0; i<30; i++)
{
sendCommand(ReadDataFromProgramMemory);
uint16_t data = receive14();
usleep(delay);
std::cout << " " << +data;
sendCommand(IncrementAddress);
}
// Exit programming mode
gpio->clr(pinMclr);
usleep(delay);
}
// Read 14bit program memory word
virtual uint16_t receive14() const
{
uint16_t word = 0x00;
for( int i=0; i<16; ++i)
{
gpio->set(pinClk);
usleep(delay);
gpio->clr(pinClk);
word |= gpio->getLevel(pinDataIn) << i;
usleep(delay);
}
word = (word >> 1 ) & 0x3fff;
usleep(delay);
return word;
}
// Send a command to the pic
virtual void sendCommand( uint8_t cmd ) const
{
for( int i=0; i<6; ++i )
{
gpio->set(pinClk);
if ((cmd>>i) & 0x01) gpio->set(pinData);
else gpio->clr(pinData);
usleep(delay);
gpio->clr(pinClk);
usleep(delay);
}
gpio->clr(pinData);
usleep(delay);
}
// Send 14bit data for writing the pic. suppose mclr already set
virtual void send14( uint16_t word) const
{
word = (word << 1) & 0x7FFE;
for( int i=0; i<16; ++i )
{
gpio->set(pinClk);
if ((word>>i) & 0x01) gpio->set(pinData);
else gpio->clr(pinData);
usleep(delay);
gpio->clr(pinClk);
usleep(delay);
}
}
Pic content
:01000000 2804 D3
:04000400 018C 3037 008E 303F 07
:08000800 008C 118E 200E 158E 200E 2809 30FF 00A1 C5
:06001000 00A0 0BA0 2811 0BA1 2810 0008 7A
:02002000 3FFF 3FFF 62
:00000001FF
Note: This is the program that is supposed to be in the PIC (I may read all correctly skipping values>=0x2000). The program is probably not working, I did not really pushed on that for now.
As an example, if I skip addresses 0,1,2,3 and 5, I read:
04=0x018c, 06=0x008e, 07=0x303f, 08=0x046, 09 and further = 0x0000
If I skip addresses 0,1,2,3,5,7, I read:
04=0x018c, 06=0x008e, 08=0x008c, 09=0x118e, 10=0x200e, 11=0x0ac7, 12 and further = 0x0000
Following a full test, with X when value is skipped:
Data: 2804 3fff 0 0
Data: X 3fff 3fff 0 0
Data: X X 3fff 3fff 0 0
Data: X X X 3fff c6 0 0
Data: X X X X 18c 3037 47 0 0
Data: X X X X 18c X 8e 303f 46 0 0
Data: X X X X 18c X 8e X 8c 118e 200e ac7 0 0
Data: X X X X 18c X 8e X 8c 118e X 158e 200e 3404 0 0
Data: X X X X 18c X 8e X 8c 118e X 158e X 2809 387f 0 0
Data: X X X X 18c X 8e X 8c 118e X 158e X X 30ff 50 0 0
Data: X X X X 18c X 8e X 8c 118e X 158e X X X a1 a0 ba0 2811 5d0 0 0
Data: X X X X 18c X 8e X 8c 118e X 158e X X X a1 a0 ba0 X ba1 2810 4 0 0