First up: Thank you for all your help in this, I am enjoying the challenge this puzzle holds and much of the info that has been shared made things much easier....

I have generated comment for most of the download code now. Still a few questions, but working through them. The project has grown larger because it is my belief that the ELM327 I have been using to attempt download will not cut it. The ELM device is set up for frames of seven or at most eight data bytes. I get as far as the response "Ready for Download" Code $44. I didn't figure out how the data got in until reading the posts.

The three byte header + 7 data + crc is OBDII standard. Looks like the programming modes uses a format outside the ELM's capability. For download an arbitrary number of bytes are generated in the frame and the number could be over 2000 if using the ram provided by the port replacement unit (space between the PRU registers at $1810 and start of FLASH at $2000). As a result of this, I plan to build a download board <sigh>
If anyone knows of programming of GM PCMs using the ELM327 PLEASE let us know. IF I am wrong about this, I am spinning my wheels...


Ok so once over the shock of the scope creep, I started planning. If you look at Kur4o's post #43 from yesterday, he outlines all the requirements. I worked through the CRC part today. If anyone is interested, I will put the code at the bottom of this post.

My understanding of the code is that the Tside download is not used for FLASH. It looks to me like the Eside (0x18) is used to transfer from tester to RAM. The code we develop or find to program can target Eside or Tside.

I will post snips of the code once confirmed.

OK, so here is the CRC code. There is no CRC code in my PCM beacause this all is done inside the DLC in hardware. The DLC can receive and/or transmit frames of any size. The command register is used to set up data transfer. Once done, a frame can be any length as long as the tx fifo is not permitted to under run. This is true on the receive side as well. The status byte checked with each receive byte tells if a completion code is ready, this signals EOF.


This is just used to test the CRC class...
Code:
// J1850.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

using namespace std;


int main(int argc, char *argv[] )
{
	UINT8	uR;
	UINT8	uLength;
	CRC_Gen	crc;

//	UINT8	uFrame[] = { 0x00, 0x00, 0x00, 0x00 };	// 59
//	UINT8	uFrame[] = { 0xF2, 0x01, 0x83 };		// 37
//	UINT8	uFrame[] = { 0x0F, 0xAA, 0x00, 0x55 };	// 79
//	UINT8	uFrame[] = { 0x00, 0xFF, 0x55, 0x11 };	// B8
//	UINT8	uFrame[] = { 0x33, 0x22, 0x55, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};	// CB
//	UINT8	uFrame[] = { 0x92, 0x6B, 0x55 };		// 8C
	UINT8	uFrame[] = { 0xFF, 0xFF, 0xFF, 0xFF };	// 74

	uLength = sizeof(uFrame) / sizeof(UINT8);

	crc.Initialize();
	uR = crc.CalcCRC(uFrame, uLength);

    return 0;

Simple class so I can re-use the CRC generator as needed
Code:
#include "stdafx.h"


CRC_Gen::CRC_Gen()
{
}


CRC_Gen::~CRC_Gen()
{
}


void CRC_Gen::Initialize()
{
	uRemainder = 0xFF;
}


UINT8	CRC_Gen::CalcCRC(UINT8* pFrame, UINT8 uLength)
{
	while (uLength > 0)
	{
		uData = *pFrame;

		uData = crc_lut[uData];
		uRemainder = crc_lut[uRemainder];

		uRemainder = uData ^ uRemainder;

		uLength--;
		pFrame++;
	}

	return(~uRemainder);
}

Note that the table crc_lut is where all the action is
Code:
/*
8 Bit CRC
Polynom 0x1D
Inital value 0xFF direct
Final XOR value 0xFF
Reflection IN false
Reflection Out false

X8 + X4 + X3 + X2 + 1
X7 + X6 + X2(C4 hex)
*/

#include "stdafx.h"

class CRC_Gen
{
public:
	 CRC_Gen();
	~CRC_Gen();
	void	Initialize();
	UINT8	CalcCRC(UINT8* pFrame, UINT8 uLength);

private:
	UINT8			uData;
	UINT8			uRemainder;
	const UINT8		crc_lut[256] = {
		0x00, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53,
		0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb,
		0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e,
		0x25, 0x38, 0x1f, 0x02, 0x51, 0x4c, 0x6b, 0x76,
		0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4,
		0x6f, 0x72, 0x55, 0x48, 0x1b, 0x06, 0x21, 0x3c,
		0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x04, 0x19,
		0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1,
		0x13, 0x0e, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40,
		0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8,
		0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d,
		0x36, 0x2b, 0x0c, 0x11, 0x42, 0x5f, 0x78, 0x65,
		0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7,
		0x7c, 0x61, 0x46, 0x5b, 0x08, 0x15, 0x32, 0x2f,
		0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0x0a,
		0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2,
		0x26, 0x3b, 0x1c, 0x01, 0x52, 0x4f, 0x68, 0x75,
		0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d,
		0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8,
		0x03, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50,
		0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2,
		0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x07, 0x1a,
		0x6c, 0x71, 0x56, 0x4b, 0x18, 0x05, 0x22, 0x3f,
		0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7,
		0x35, 0x28, 0x0f, 0x12, 0x41, 0x5c, 0x7b, 0x66,
		0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e,
		0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab,
		0x10, 0x0d, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43,
		0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1,
		0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x09,
		0x7f, 0x62, 0x45, 0x58, 0x0b, 0x16, 0x31, 0x2c,
		0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4 };
};

I don't claim to be a software guy, but I have tested this code and I think it's OK.

-Tom