PCM Hammer P12 development

They go by many names, P01, P10, P12, P59, E38, VPW, '0411 etc.
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

Nice picture ... Pretty blurry, my eyes don't have time to focus as it flies so fast over my head! :roll:

Naw, I get some of it, not enough to write code from.

Edit;
I have noticed that there is a right bit shift in the calling routines ... one is asr (Arithmetic Shift Right), the other is lsr (Logical Shift Right), to d0 whatever is there ...
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 9012
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: PCM Hammer P12 development

Post by antus »

well the point is we need:

WE# in the second line to go high and low at the right times according to the mode and address commands in the top row.

To do that, we probably still need to set the SIM register, but its not doing VPP, it needs to be doing WE#.

So we need to compare timings against older AMD chip, and if the same probably its ok. But if we see anything different or obviously wrong with the timing of the writes to SIM_CSOR0 we might be on to something.

Also, I might just be going around in circles. Like you elude too, reading code to understand the hardware interface can be easier than reading datasheets. Its a thought though, 'till we have something better.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

They appear to be the same as the AM29F800B (P59).

ATM I'm open for any bites ... I'm at a loss, I'm hitting the limits of my intelligence on the matter!

And just for clarity, this is what I've changed, erase seems to work, the sector is blank, we get a success response,

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Erase the given block.
///////////////////////////////////////////////////////////////////////////////
uint8_t Amd_EraseBlock(uint32_t address)
{
	// Return zero if successful, anything else is an error code.
	unsigned short status = 0;

	uint16_t volatile * flashBase = (uint16_t*)address;

	// Tell the chip to erase the given block.
+#if defined P12
+	SIM_CSOR0 |= 0x4;
+#else
	SIM_CSOR0 = 0x7060;
+#endif
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;
	COMMAND_REG_AAA = 0x8080;
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;

	*flashBase = 0x3030;

	uint16_t read1 = 0;
	uint16_t read2 = 0;

	for (int iterations = 0; iterations < 0x640000; iterations++)
	{
		read1 = *flashBase & 0x40;

		ScratchWatchdog();

		read2 = *flashBase & 0x40;

		if (read1 == read2)
		{
			// Success!
			break;
		}

		uint16_t read3 = *flashBase & 0x20;
		if (read3 == 0)
		{
			continue;
		}

		status = 0xA0;
		break;
	}

	if (status == 0xA0)
	{
		read1 = *flashBase & 0x40;
		read2 = *flashBase & 0x40;
		if (read1 != read2)
		{
			status = 0xB0;
		}
		else
		{
			// Success!
			status = 0;
		}
	}

	// Return to array mode.
	*flashBase = 0xF0F0;
	*flashBase = 0xF0F0;
+#if defined P12
+	SIM_CSOR0 = 0xA332;
+#else
	SIM_CSOR0 = 0x1060;
+#endif

	return status;
}
Chip ID works,

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Get the manufacturer and type of flash chip.
///////////////////////////////////////////////////////////////////////////////
uint32_t Amd_GetFlashId()
{
	SIM_CSBAR0 = 0x0007;
	SIM_CSORBT = 0x6820;

	// Switch to flash into ID-query mode.
+#if defined P12
+	SIM_CSOR0 = 0xF322;
+#else
	SIM_CSOR0 = 0x7060;
+#endif
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;
	COMMAND_REG_AAA = 0x9090;

	// Read the identifier from address zero.
	//flashIdentifier = FLASH_IDENTIFIER;
	uint16_t manufacturer = FLASH_MANUFACTURER;
	uint16_t device = FLASH_DEVICE;
	uint32_t id = ((uint32_t)manufacturer << 16) | device;

	// Switch back to standard mode.
	FLASH_BASE = READ_ARRAY_COMMAND;
+#if defined P12
+	SIM_CSOR0 = 0xA332;
+#else
	SIM_CSOR0 = 0x1060;
+#endif
	return id;
}
Write does not,

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Write data to flash memory.
// This is invoked by HandleWriteMode36 in common-readwrite.c
///////////////////////////////////////////////////////////////////////////////
uint8_t Amd_WriteToFlash(unsigned int payloadLengthInBytes, unsigned int startAddress, unsigned char *payloadBytes, int testWrite)
{
	char errorCode = 0;
	unsigned short status;

	unsigned short* payloadArray = (unsigned short*) payloadBytes;
	unsigned short* flashArray = (unsigned short*) startAddress;

	for (unsigned index = 0; index < payloadLengthInBytes / 2; index++)
	{
		unsigned short volatile  *address = &(flashArray[index]);
		unsigned short value = payloadArray[index];

		if (!testWrite)
		{
+#if defined P12
+			SIM_CSOR0 |= 0x4;
+#else
			SIM_CSOR0 = 0x7060;
+#endif
			COMMAND_REG_AAA = 0xAAAA;
			COMMAND_REG_554 = 0x5555;
			COMMAND_REG_AAA = 0xA0A0;
			*address = value;
		}

		char success = 0;
		for(int iterations = 0; iterations < 0x1000; iterations++)
		{
			ScratchWatchdog();

			uint16_t read = testWrite ? value : *address;

			if (read == value)
			{
				success = 1;
				break;
			}
		}

		if (!success)
		{
			// Return flash to normal mode and return the error code.
			errorCode = 0xAA;

			if (!testWrite)
			{
				*address = 0xF0F0;
				*address = 0xF0F0;
+#if defined P12
+				SIM_CSOR0 = 0xA332;
+#else
				SIM_CSOR0 = 0x1060;
+#endif
			}

			return errorCode;
		}
	}

	if (!testWrite)
	{
		// Return flash to normal mode.
		unsigned short* address = (unsigned short*)startAddress;
		*address = 0xF0F0;
		*address = 0xF0F0;
+#if defined P12
+	SIM_CSOR0 = 0xA332;
+#else
	SIM_CSOR0 = 0x1060;
+#endif
	}

	return 0;
}
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 9012
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: PCM Hammer P12 development

Post by antus »

Try skipping the get flash ID stage. Its touching 3 registers and it might be changing something that breaks the later write stage. Since you can assume what chip we have I think you could hard code the chip id in pcmhammer and skip sending the vpw to trigger that function in the kernel. see if that makes any difference to erase and program.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
kur4o
Posts: 1044
Joined: Sun Apr 10, 2016 9:20 pm

Re: PCM Hammer P12 development

Post by kur4o »

Prerequisites before programming event

1)

Code: Select all

andi.w  #$FEFF,(word_FFFFFA50).w
2)

Code: Select all

move.w  (word_FFFFFA7E).w,word_FFFFFFFC(a6)
bset    #4,var_4(a6)
move.w  var_4(a6),(word_FFFFFA7E).w
move.w  (word_FFFFFA7C).w,dword_FFFFFFF8(a6)
andi.b  #$F8,dword_FFFFFFF8+1(a6)
ori.b   #5,dword_FFFFFFF8+1(a6)
move.w  dword_FFFFFFF8(a6),(word_FFFFFA7C).
Programming event a0 looks to be data that is written a1 is the flash register, d1 is the flash cycles. Some more digging will be needed to get exact meaning. You can see the a1 a0 are increased by 2, so word based, but the cycles are decreased by 1 which implies byte count cycles.
3)

Code: Select all

loc_FFFF215C:
move.w  #$AAAA,($AAA).w
move.w  #$5555,($554).w
move.w  #$A0A0,($AAA).w
move.w  (a0),(a1)
move.w  (a0),d5
There is some checks and watchdog waiting between the 2, so some delay may be needed and check if the data is actually written and verified.

4)

Code: Select all

loc_FFFF2212:
addq.l  #2,a1
addq.l  #2,a0
subq.l  #1,d1
bne.w   loc_FFFF215C
Prerequisites after programming event
5)

Code: Select all

move.w  (word_FFFFFA7E).w,var_4(a6)
bclr    #4,var_4(a6)
move.w  var_4(a6),(word_FFFFFA7E).w
6)

Code: Select all

loc_FFFF2598:
moveq   #1,d0
lsl.l   #8,d0
move.w  (word_FFFFFA50).w,d1
and.l   #$100,d0
and.l   #unk_FFFFFEFF,d1
or.l    d0,d1
move.w  d1,(word_FFFFFA50).w
antus edit: numbered each block so we can talk about it
User avatar
antus
Site Admin
Posts: 9012
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: PCM Hammer P12 development

Post by antus »

Thanks for that. Some quick notes.

I think we are missing this, and likely need it. It may be the problem. We dont have an equivalent in P01/P59 and dont know whats there.

Code: Select all

andi.w  #$FEFF,(word_FFFFFA50).w
Following might be a disassembly failure? I think the first 3 lines are equivalent of "FFFFFA7E |= 0x1000;"

and I think the word_FFFFFFFC(a6) is supposed to be var_4(a6) but its missed it somehow.

if word_FFFFFFFC is a linked variable, then word_FFFFFFF8 is likely another linked variable that is used to process the register word_FFFFFA7C.

Code: Select all

move.w  (word_FFFFFA7E).w,word_FFFFFFFC(a6)
bset    #4,var_4(a6)
move.w  var_4(a6),(word_FFFFFA7E).w
move.w  (word_FFFFFA7C).w,dword_FFFFFFF8(a6)
andi.b  #$F8,dword_FFFFFFF8+1(a6)
ori.b   #5,dword_FFFFFFF8+1(a6)
move.w  dword_FFFFFFF8(a6),(word_FFFFFA7C).
So above word_FFFFFA7C (SIM_CSBAR0) gets

first byte: andi.b 1111 1000 (F8)
second byte: ori.b 0000 0101 (05)

so is that just the same as a bset 6, bset 8? because if im reading it correctly, which is hard to be sure of, the AND clears the last 3 bits, so then the OR can only set the two bits which are 1 in the second octet - bit7 must already be 0 from the AND?

<snip>

This is "FFFFFA7E |= 0x1000;" again toggling bit 4 off.

Prerequisites after programming event

Code: Select all

move.w  (word_FFFFFA7E).w,var_4(a6)
bclr    #4,var_4(a6)
move.w  var_4(a6),(word_FFFFFA7E).w
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
antus
Site Admin
Posts: 9012
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: PCM Hammer P12 development

Post by antus »

SIM_BASE is 0x00FFFA30

so 00FFFA50 is definately part of the SIM (System Integration Module) and its part of an external interface to something else. Perhaps the slave cpu? perhaps it holds the reset line or something like that to get it off the bus?

Lets put an (*(unsigned short *)(0xFFFFFA50)) &= 0xFEFF; in the first P12 blocks that talk to hardware in Amd_WriteToFlash(); as the first thing.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

Code: Select all

///////////////////////////////////////////////////////////////////////////////
// Write data to flash memory.
// This is invoked by HandleWriteMode36 in common-readwrite.c
///////////////////////////////////////////////////////////////////////////////
uint8_t Amd_WriteToFlash(unsigned int payloadLengthInBytes, unsigned int startAddress, unsigned char *payloadBytes, int testWrite)
{
	char errorCode = 0;
	unsigned short status;
	unsigned short saveFA50 = (*(unsigned short *)(0xFFFFFA50)); // Save value at FA50

	unsigned short* payloadArray = (unsigned short*) payloadBytes;
	unsigned short* flashArray = (unsigned short*) startAddress;

	for (unsigned index = 0; index < payloadLengthInBytes / 2; index++)
	{
		unsigned short volatile  *address = &(flashArray[index]);
		unsigned short value = payloadArray[index];

		if (!testWrite)
		{
#if defined P12
			(*(unsigned short *)(0xFFFFFA50)) &= 0xFEFF;
			SIM_CSOR0 |= 0x4;
#else
			SIM_CSOR0 = 0x7060;
#endif
			COMMAND_REG_AAA = 0xAAAA;
			COMMAND_REG_554 = 0x5555;
			COMMAND_REG_AAA = 0xA0A0;
			*address = value;
		}

		char success = 0;
		for(int iterations = 0; iterations < 0x1000; iterations++)
		{
			ScratchWatchdog();

			uint16_t read = testWrite ? value : *address;

			if (read == value)
			{
				success = 1;
				break;
			}
		}

		if (!success)
		{
			// Return flash to normal mode and return the error code.
			errorCode = 0xAA;

			if (!testWrite)
			{
				*address = 0xF0F0;
				*address = 0xF0F0;
#if defined P12
				(*(unsigned short *)(0xFFFFFA50)) = saveFA50; // Restore with saved value
				SIM_CSOR0 = 0xA332;
#else
				SIM_CSOR0 = 0x1060;
#endif
			}

			return errorCode;
		}
	}

	if (!testWrite)
	{
		// Return flash to normal mode.
		unsigned short* address = (unsigned short*)startAddress;
		*address = 0xF0F0;
		*address = 0xF0F0;
#if defined P12
	(*(unsigned short *)(0xFFFFFA50)) = saveFA50; // Restore with saved value
	SIM_CSOR0 = 0xA332;
#else
	SIM_CSOR0 = 0x1060;
#endif
	}

	return 0;
}
The chip ID is also hard coded in the kernel to prevent it from asking the chip.

Building test and sending now ...
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
User avatar
antus
Site Admin
Posts: 9012
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: PCM Hammer P12 development

Post by antus »

there is some code space optimisation to be had there, but I dont see any problems from just reading it. fingers crossed.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

antus wrote:there is some code space optimisation to be had there
Where, inquiring minds would like to know!
Intelligence is in the details!

It is easier not to learn bad habits, then it is to break them!

If I was here to win a popularity contest, their would be no point, so I wouldn't be here!
Post Reply