Page 32 of 56

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 7:37 pm
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 ...

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 8:39 pm
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.

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 9:07 pm
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;
}

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 9:48 pm
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.

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 9:53 pm
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

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 10:01 pm
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

Re: PCM Hammer P12 development

Posted: Thu Mar 10, 2022 11:33 pm
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.

Re: PCM Hammer P12 development

Posted: Fri Mar 11, 2022 1:21 am
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 ...

Re: PCM Hammer P12 development

Posted: Fri Mar 11, 2022 1:39 am
by antus
there is some code space optimisation to be had there, but I dont see any problems from just reading it. fingers crossed.

Re: PCM Hammer P12 development

Posted: Fri Mar 11, 2022 1:59 am
by Gampy
antus wrote:there is some code space optimisation to be had there
Where, inquiring minds would like to know!