PCM Hammer P12 development

They go by many names, P01, P10, P12, P59, E38, VPW, '0411 etc.
User avatar
antus
Site Admin
Posts: 9009
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 »

Im keen to start playing this game. My P12 has transited through 4 US states, cleared the customs house and just left the country. Dont know yet if its coming by ship or air. To quote Tazzi "Impatiently taps foot...."
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 »

To sum,
Chip ID

Code: Select all

	asm("ORI #0x700, %SR");
	SIM_CSOR0 = 0xF322;
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;
	COMMAND_REG_AAA = 0x9090;
Chip Erase

Code: Select all

	asm("ORI #0x700, %SR");
	SIM_CSOR0 |= 0x4;
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;
	COMMAND_REG_AAA = 0x8080;
	COMMAND_REG_AAA = 0xAAAA;
	COMMAND_REG_554 = 0x5555;
	*flashBase = 0x3030;
Chip Write

Code: Select all

	asm("ORI #0x700, %SR");
			SIM_CSOR0 |= 0x4;
			COMMAND_REG_AAA = 0xAAAA;
			COMMAND_REG_554 = 0x5555;
			COMMAND_REG_AAA = 0xA0A0;
			*address = value;
PCM Hammer kernel diffs,

Code: Select all

diff -u Kernels/common-readwrite.c ../Test Builds/P12/Kernels/Kernels/common-readwrite.c
--- Kernels/common-readwrite.c	2021-01-29 09:32:23.970935000 -0500
+++ ../Test Builds/P12/Kernels/Kernels/common-readwrite.c	2022-03-21 10:43:41.713417000 -0400
@@ -65,7 +65,11 @@
 void SendWriteSuccess(unsigned char code)
 {
 	// Send response
+#if defined P12
+	MessageBuffer[0] = 0x6C;
+#else
 	MessageBuffer[0] = 0x6D;
+#endif
 	MessageBuffer[1] = 0xF0;
 	MessageBuffer[2] = 0x10;
 	MessageBuffer[3] = 0x76;
@@ -76,7 +80,11 @@
 
 void SendWriteFail(unsigned char callerError, unsigned char flashError)
 {
+#if defined P12
+	MessageBuffer[0] = 0x6C;
+#else
 	MessageBuffer[0] = 0x6D;
+#endif
 	MessageBuffer[1] = 0xF0;
 	MessageBuffer[2] = 0x10;
 	MessageBuffer[3] = 0x7F;
diff -u Kernels/common.c ../Test Builds/P12/Kernels/Kernels/common.c
--- Kernels/common.c	2022-01-15 14:51:22.409295399 -0500
+++ ../Test Builds/P12/Kernels/Kernels/common.c	2022-03-21 10:16:13.150448000 -0400
@@ -26,8 +26,12 @@
 {
 	WATCHDOG1 = 0x55;
 	WATCHDOG1 = 0xAA;
+#if defined P12
+	WATCHDOG2 ^= 0x80;
+#else
 	WATCHDOG2 &= 0x7F;
 	WATCHDOG2 |= 0x80;
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff -u Kernels/common.h ../Test Builds/P12/Kernels/Kernels/common.h
--- Kernels/common.h	2021-12-19 17:41:26.237953561 -0500
+++ ../Test Builds/P12/Kernels/Kernels/common.h	2022-03-12 09:45:01.878596000 -0500
@@ -15,14 +15,34 @@
 typedef int            int32_t;
 
 #ifndef DLC_CONFIGURATION
-	#define DLC_CONFIGURATION          (*(unsigned char *)0x00FFF600)
-	#define DLC_INTERRUPTCONFIGURATION (*(unsigned char *)0x00FFF606)
-	#define DLC_TRANSMIT_COMMAND       (*(unsigned char *)0x00FFF60C)
-	#define DLC_TRANSMIT_FIFO          (*(unsigned char *)0x00FFF60D)
-	#define DLC_STATUS                 (*(unsigned char *)0x00FFF60E)
-	#define DLC_RECEIVE_FIFO           (*(unsigned char *)0x00FFF60F)
-	#define WATCHDOG1                  (*(unsigned char *)0x00FFFA27)
-	#define WATCHDOG2                  (*(unsigned char *)0x00FFD006)
+	#if defined P01
+		#define DLC_CONFIGURATION          (*(unsigned char *)0x00FFF600)
+		#define DLC_INTERRUPTCONFIGURATION (*(unsigned char *)0x00FFF606)
+		#define DLC_TRANSMIT_COMMAND       (*(unsigned char *)0x00FFF60C)
+		#define DLC_TRANSMIT_FIFO          (*(unsigned char *)0x00FFF60D)
+		#define DLC_STATUS                 (*(unsigned char *)0x00FFF60E)
+		#define DLC_RECEIVE_FIFO           (*(unsigned char *)0x00FFF60F)
+		#define WATCHDOG1                  (*(unsigned char *)0x00FFFA27)
+		#define WATCHDOG2                  (*(unsigned char *)0x00FFD006)
+	#elif defined P04
+		#define DLC_CONFIGURATION          (*(unsigned char *)0x00FFE800)
+		#define DLC_INTERRUPTCONFIGURATION (*(unsigned char *)0x00FFE800)
+		#define DLC_TRANSMIT_COMMAND       (*(unsigned char *)0x00FFE800)
+		#define DLC_TRANSMIT_FIFO          (*(unsigned char *)0x00FFE801)
+		#define DLC_STATUS                 (*(unsigned char *)0x00FFE800)
+		#define DLC_RECEIVE_FIFO           (*(unsigned char *)0x00FFE801)
+		#define WATCHDOG1                  (*(unsigned char *)0x00FFFA27)
+		#define WATCHDOG2                  (*(unsigned char *)0x00FFC006)
+	#elif defined P12
+		#define DLC_CONFIGURATION          (*(unsigned char *)0x00FFF600)
+		#define DLC_INTERRUPTCONFIGURATION (*(unsigned char *)0x00FFF606)
+		#define DLC_TRANSMIT_COMMAND       (*(unsigned char *)0x00FFF60C)
+		#define DLC_TRANSMIT_FIFO          (*(unsigned char *)0x00FFF60D)
+		#define DLC_STATUS                 (*(unsigned char *)0x00FFF60E)
+		#define DLC_RECEIVE_FIFO           (*(unsigned char *)0x00FFF60F)
+		#define WATCHDOG1                  (*(unsigned char *)0x00FFFA55)
+		#define WATCHDOG2                  (*(unsigned char *)0x00FFFA21)
+	#endif
 #endif
 
 ///////////////////////////////////////////////////////////////////////////////
diff -u Kernels/flash-amd.c ../Test Builds/P12/Kernels/Kernels/flash-amd.c
--- Kernels/flash-amd.c	2020-11-23 13:52:17.375198000 -0500
+++ ../Test Builds/P12/Kernels/Kernels/flash-amd.c	2022-03-21 15:56:59.900184000 -0400
@@ -13,11 +13,15 @@
 ///////////////////////////////////////////////////////////////////////////////
 uint32_t Amd_GetFlashId()
 {
+#if defined P12
+	SIM_CSOR0 = 0xF322;
+#else
 	SIM_CSBAR0 = 0x0007;
 	SIM_CSORBT = 0x6820;
 
 	// Switch to flash into ID-query mode.
 	SIM_CSOR0 = 0x7060;
+#endif
 	COMMAND_REG_AAA = 0xAAAA;
 	COMMAND_REG_554 = 0x5555;
 	COMMAND_REG_AAA = 0x9090;
@@ -30,7 +34,11 @@
 
 	// Switch back to standard mode.
 	FLASH_BASE = READ_ARRAY_COMMAND;
+#if defined P12
+	SIM_CSOR0 = 0xA332;
+#else
 	SIM_CSOR0 = 0x1060;
+#endif
 
 	return id;
 }
@@ -46,7 +54,11 @@
 	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;
@@ -100,7 +112,11 @@
 	// Return to array mode.
 	*flashBase = 0xF0F0;
 	*flashBase = 0xF0F0;
+#if defined P12
+	SIM_CSOR0 = 0xA332;
+#else
 	SIM_CSOR0 = 0x1060;
+#endif
 
 	return status;
 }
@@ -124,7 +140,11 @@
 
 		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;
@@ -154,7 +174,11 @@
 			{
 				*address = 0xF0F0;
 				*address = 0xF0F0;
+#if defined P12
+				SIM_CSOR0 = 0xA332;
+#else
 				SIM_CSOR0 = 0x1060;
+#endif
 			}
 
 			return errorCode;
@@ -167,8 +191,13 @@
 		unsigned short* address = (unsigned short*)startAddress;
 		*address = 0xF0F0;
 		*address = 0xF0F0;
+#if defined P12
+		SIM_CSOR0 = 0xA332;
+#else
 		SIM_CSOR0 = 0x1060;
+#endif
 	}
 
 	return 0;
 }
+
diff -u Kernels/flash.h ../Test Builds/P12/Kernels/Kernels/flash.h
--- Kernels/flash.h	2020-12-10 18:38:49.096283000 -0500
+++ ../Test Builds/P12/Kernels/Kernels/flash.h	2022-03-12 10:03:11.058439000 -0500
@@ -2,7 +2,11 @@
 // Functions for erasing and writing flash
 ///////////////////////////////////////////////////////////////////////////////
 
-#define SIM_BASE        0x00FFFA00
+#if defined P12
+	#define SIM_BASE        0x00FFFA30
+#else
+	#define SIM_BASE        0x00FFFA00
+#endif
 #define SIM_CSBARBT     (*(unsigned short *)(SIM_BASE + 0x48)) // CSRBASEREG, boot chip select, chip select base addr boot ROM reg,
 															   // must be updated to $0006 on each update of flash CE/WE states
 #define SIM_CSORBT      (*(unsigned short *)(SIM_BASE + 0x4a)) // CSROPREG, Chip select option boot ROM reg., $6820 for normal op
@@ -54,8 +58,10 @@
 uint8_t Intel_WriteToFlash(unsigned int payloadLengthInBytes, unsigned int startAddress, unsigned char *payloadBytes, int testWrite);
 
 // Functions prefixed with Amd1024 work with this chip ID
-#define FLASH_ID_AMD_1024  0x00012258
+#define FLASH_ID_AMD_AM29BL802C 0x00012281 // AM29BL802C
+#define FLASH_ID_AMD_1024       0x00012258
 
 uint32_t Amd_GetFlashId();
 uint8_t Amd_EraseBlock(uint32_t address);
 uint8_t Amd_WriteToFlash(unsigned int payloadLengthInBytes, unsigned int startAddress, unsigned char *payloadBytes, int testWrite);
+
diff -u Kernels/write-kernel.c ../Test Builds/P12/Kernels/Kernels/write-kernel.c
--- Kernels/write-kernel.c	2022-03-12 09:09:44.324447000 -0500
+++ ../Test Builds/P12/Kernels/Kernels/write-kernel.c	2022-03-21 15:06:55.970887000 -0400
@@ -168,7 +168,11 @@
 {
 	ElmSleep();
 
+#if defined P12
+	uint8_t *osid = (uint8_t*)0x8004;
+#else
 	uint8_t *osid = (uint8_t*)0x504;
+#endif
 
 	MessageBuffer[0] = 0x6C;
 	MessageBuffer[1] = 0xF0;
@@ -198,6 +202,7 @@
 			break;
 
 		case FLASH_ID_AMD_1024:
+		case FLASH_ID_AMD_AM29BL802C:  // P12 1m
 			status = Amd_EraseBlock(address);
 			break;
 
@@ -267,6 +275,7 @@
 		return Intel_WriteToFlash(payloadLengthInBytes, startAddress, payloadBytes, testWrite);
 
 	case FLASH_ID_AMD_1024:
+	case FLASH_ID_AMD_AM29BL802C:  // P12 1m
 		return Amd_WriteToFlash(payloadLengthInBytes, startAddress, payloadBytes, testWrite);
 
 	default:
@@ -293,10 +302,12 @@
 
 	switch (MessageBuffer[3])
 	{
+#if !defined P12
 	case 0x20:
 		LongSleepWithWatchdog();
 		Reboot(0xCC000000 | iterations);
 		break;
+#endif
 
 	case 0x34:
 		HandleWriteRequestMode34();
@@ -459,9 +472,20 @@
 		lastMessage = iterations;
 		lastActivity = iterations;
 
+#if defined P12
+		// Did the tool just request a reboot?
+		if (MessageBuffer[3] == 0x20)
+		{
+			// Yes
+			break;
+		}
+#endif
+
 		ProcessMessage(iterations);
 	}
 
+#if !defined P12
 	// This shouldn't happen. But, just in case...
 	Reboot(0xFF000000 | iterations);
+#endif
 }
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
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

Apparently my understanding/translation of the following is failing ...

Code: Select all

ROM:00FF2052                 move.w  (word_FFFFFA7C).w,dword_FFFFFFF8(a6)
ROM:00FF2058                 andi.b  #$F8,-7(a6)
ROM:00FF205E                 ori.b   #5,-7(a6)
ROM:00FF2064                 move.w  dword_FFFFFFF8(a6),(word_FFFFFA7C).w
If 0x00FFFA7C = 0x00000004, What is actually written to 0x00FFFA7C ??

The whole block it is out of,

Code: Select all

ROM:00FF203A sub_FF203A:
ROM:00FF203A                 nop
ROM:00FF203C                 link    a6,#$FFF8
ROM:00FF2040                 move.w  (word_FFFFFA7E).w,word_FFFFFFFC(a6)
ROM:00FF2046                 bset    #4,word_FFFFFFFC(a6)
ROM:00FF204C                 move.w  word_FFFFFFFC(a6),(word_FFFFFA7E).w
ROM:00FF2052                 move.w  (word_FFFFFA7C).w,dword_FFFFFFF8(a6)
ROM:00FF2058                 andi.b  #$F8,-7(a6)
ROM:00FF205E                 ori.b   #5,-7(a6)
ROM:00FF2064                 move.w  dword_FFFFFFF8(a6),(word_FFFFFA7C).w
ROM:00FF206A                 unlk    a6
ROM:00FF206C                 rts
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!
kur4o
Posts: 1044
Joined: Sun Apr 10, 2016 9:20 pm

Re: PCM Hammer P12 development

Post by kur4o »

Read word fa7c to a word buffer , example 0406

Take first byte 04 and apply
andi.b #$F8 [11111000 * 00000100 =0] [basically clear first 3 bits]
ori.b #5 [add 00000101 to 0 = 5]

buffer= 0506
Than write from buffer to fa7c.
You are done
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

kur4o,

Thank you for the math lesson, I'm sure some reader will learn something, unfortunately that reader is not me!

I know it's hard for you that are capable of doing the math to understand that some of us are not capable and don't get it!

In your example, the word buffer would be 0004.
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!
kur4o
Posts: 1044
Joined: Sun Apr 10, 2016 9:20 pm

Re: PCM Hammer P12 development

Post by kur4o »

Actually it is not that easy as it looks , especially on some frankestein math conversions.

Take 0004 as read from fffffa7c

split in 2 bytes 00 and 04

00 will be multiplied with f8, than result will be added with 5

So it will look like

buffer=00 04 convert first byte, second byte stays the same
=(00*f8)+5=05
so final result will be
05 04
that needs to be written back to FFFFFa7c
User avatar
Tazzi
Posts: 3550
Joined: Thu May 17, 2012 8:53 pm
cars: VE SS Ute
Location: WA
Contact:

Re: PCM Hammer P12 development

Post by Tazzi »

I believe it translates to this which is a bit more readable:

Code: Select all

bset    #4, (FFFFFA7E)   ;Set bit 4
move.w (FFFFFA7C), D1    ;Move value from A7C into D1
andi.w  #$FFF8, D1  ; clear bits 0,1,2.
ori.w    #5,D1      ;enable bits 0,2
move.w D1, (FFFFFA7C)   ;save back to A7C

Assuming I have this right...

A7E is bcsor1.. and enabling bit 4 is related to memory boundary.
A7C is bcsbar... clearing the bits is just to reset this setting, and enabling bits 0 and 2 (101) means block size 2MB.
Block size means the "extent of the address space from its space address". So it doesnt necessarily mean anything about the connected flashes memory size, just that the cpu is setup to deal with up to 2MB.
Your Local Aussie Reverse Engineer
Contact for Software/Hardware development and Reverse Engineering
Site:https://www.envyouscustoms.com
Mob:+61406 140 726
Image
User avatar
Gampy
Posts: 2332
Joined: Sat Dec 15, 2018 7:38 am

Re: PCM Hammer P12 development

Post by Gampy »

Maybe we are not as far along as we thought ...

We were able to erase the calibration sector starting at 020000 with a specific kernel version, we call it .11.
Before and after bins are in this thread ... they show it's clearly a proper erase of the right sector.

Since the PCM was recovered with the Tech2, we have been getting successful erase responses.
[12:01:40:886] TX: 6C 10 F0 3D 05 02 00 00
[12:01:40:902] RX: 6C F0 10 7D 05 00 00
However looking at the bin files, they are NOT erased, the range is corrupted, not erased (not all FF's).

Ok, this kernel version is stuffed ... I whip out the kernel that successfully erased previously (we call it .11), proceed to erase the same sector, nothing just more corruption!

The moral of the story ... We obviously don't have erase working either!
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
NSFW
Posts: 746
Joined: Fri Feb 02, 2018 3:13 pm

Re: PCM Hammer P12 development

Post by NSFW »

Is there any chance that voltage is dipping during the erase?
Corruption sounds more like an electrical problem than a software problem.
I'm just guessing though.
Please don't PM me with technical questions - start a thread instead, and send me a link to it. That way I can answer in public, and help other people who have the same question. Thanks!
kur4o
Posts: 1044
Joined: Sun Apr 10, 2016 9:20 pm

Re: PCM Hammer P12 development

Post by kur4o »

The erase command seems accurate, I think it is time of waiting till the erase is done, Usually 2-3 seconds per segment.

You can also check if the erase is done with reading register where 3030 is loaded, And wait for specific response.

Code: Select all

RAM:FFFF2110 loc_FFFF2110:                           ; CODE XREF: eraASE1_sub_FFFF2070+8Cj
RAM:FFFF2110                 tst.b   d5
RAM:FFFF2112                 bpl.s   loc_FFFF2118
RAM:FFFF2114                 moveq   #1,d4
RAM:FFFF2116                 bra.s   loc_FFFF2130
RAM:FFFF2118 ; ---------------------------------------------------------------------------
RAM:FFFF2118
RAM:FFFF2118 loc_FFFF2118:                           ; CODE XREF: eraASE1_sub_FFFF2070+A2j
RAM:FFFF2118                 btst    #5,d5
RAM:FFFF211C                 beq.w   loc_FFFF20AC
This is the check when erase is done. test bit5 on d5 or test on plus. Not sure which one is success.
Some example

You want to erase segment 20000

you push 20000 to a0 register
Than push 3030 to a0 register

Than read a word from a0[push to d5] and do a check wait some time with COP and repeat till erase is done confirmation.
Post Reply