Trammell Hudson avatar Trammell Hudson committed fe1ccba Draft

ISP support can read ROM!

Comments (0)

Files changed (1)

 }
 
 
+/** Generate a 0.5 MHz clock on the XTAL pin to drive the chip
+ * if it does not have a built in oscillator enabled.
+ */
+static void
+isp_clock(
+	uint8_t cycles
+)
+{
+	const uint8_t xtal = prom_pin(prom->addr_pins[ISP_XTAL]);
+	for (uint8_t i = 0 ; i < cycles ; i++)
+	{
+		out(xtal, 1);
+		_delay_us(1);
+		out(xtal, 0);
+		_delay_us(1);
+	}
+}
+
+
+/** Send a byte to an AVR ISP enabled chip and read a result.
+ * Since the AVR ISP is bidirectional, every byte out is also a byte in.
+ * \todo Generate clock on XTAL1.
+ */
+static uint8_t
+isp_write(
+	uint8_t byte
+)
+{
+	const uint8_t mosi = prom_pin(prom->addr_pins[ISP_MOSI]);
+	const uint8_t sck = prom_pin(prom->addr_pins[ISP_SCK]);
+	const uint8_t miso = prom_pin(prom->data_pins[ISP_MISO]);
+	uint8_t rc = 0;
+
+	for (uint8_t i = 0 ; i < 8 ; i++, byte <<= 1)
+	{
+		out(mosi, (byte & 0x80) ? 1 : 0);
+		isp_clock(8);
+
+		out(sck, 1);
+		isp_clock(8);
+
+		rc = (rc << 1) | (in(miso) ? 1 : 0);
+		out(sck, 0);
+		//isp_clock(2);
+
+	}
+
+	return rc;
+}
+
+
+/** Enter programming mode for an ISP chip.
+ * \return 1 on success, 0 on failure.
+ */
+static int
+isp_setup(void)
+{
+	// Pulse the RESET pin, while holding SCK low.
+	const uint8_t sck = prom_pin(prom->addr_pins[ISP_SCK]);
+	const uint8_t reset = prom_pin(prom->addr_pins[ISP_RESET]);
+	const uint8_t miso = prom_pin(prom->data_pins[ISP_MISO]);
+	out(sck, 0);
+	out(reset, 1);
+	isp_clock(4);
+	out(reset, 0);
+	isp_clock(255);
+
+	// Now delay at least 20 ms
+	_delay_ms(20);
+
+	uint8_t rc1, rc2, rc3, rc4;
+
+	// Enter programming mode; enable pull up on the MISO pin
+	out(miso, 1);
+
+	rc1 = isp_write(0xAC);
+	rc2 = isp_write(0x53);
+	rc3 = isp_write(0x12);
+	rc4 = isp_write(0x34);
+
+	// Disable pull up
+	out(miso, 0);
+
+	if (rc3 == 0x53)
+		return 1;
+
+	// Now show what we read
+	uint8_t buf[10];
+	buf[0] = hexdigit(rc1 >> 4);
+	buf[1] = hexdigit(rc1 >> 0);
+	buf[2] = hexdigit(rc2 >> 4);
+	buf[3] = hexdigit(rc2 >> 0);
+	buf[4] = hexdigit(rc3 >> 4);
+	buf[5] = hexdigit(rc3 >> 0);
+	buf[6] = hexdigit(rc4 >> 4);
+	buf[7] = hexdigit(rc4 >> 0);
+
+	buf[8] = '\r';
+	buf[9] = '\n';
+
+	usb_serial_write(buf, sizeof(buf));
+	return 0;
+}
+
+
+/** Read a byte using the AVRISP, instead of the normal PROM format.
+ * \todo: prom_setup() to enter programming mode
+ * \todo: Clock on XTAL1
+ */
+static uint8_t
+isp_read(
+	uint32_t addr
+)
+{
+	uint8_t h = (addr >> 13) & 0x01;
+	uint8_t a = (addr >>  8) & 0x0F;
+	uint8_t b = (addr >>  0) & 0xFF;
+	isp_write(0x20 | (h ? 0x8 : 0));
+	isp_write(a);
+	isp_write(b);
+	return isp_write(0);
+}
+
+
+
 /** Configure all of the IO pins for the new PROM type */
 static void
 prom_setup(void)
 
 	// Let things stabilize for a little while
 	_delay_ms(250);
+
+	// If this is an AVR ISP chip, try to go into programming mode
+	if (prom->data_width == 0)
+		isp_setup();
 }
 
 
 }
 
 
-/** Generate a 0.5 MHz clock on the XTAL pin to drive the chip
- * if it does not have a built in oscillator enabled.
- */
-static void
-isp_clock(
-	uint8_t cycles
-)
-{
-	const uint8_t xtal = prom_pin(prom->addr_pins[ISP_XTAL]);
-	for (uint8_t i = 0 ; i < cycles ; i++)
-	{
-		out(xtal, 1);
-		_delay_us(1);
-		out(xtal, 0);
-		_delay_us(1);
-	}
-}
-
-
-/** Send a byte to an AVR ISP enabled chip and read a result.
- * Since the AVR ISP is bidirectional, every byte out is also a byte in.
- * \todo Generate clock on XTAL1.
- */
-static uint8_t
-isp_write(
-	uint8_t byte
-)
-{
-	const uint8_t mosi = prom_pin(prom->addr_pins[ISP_MOSI]);
-	const uint8_t sck = prom_pin(prom->addr_pins[ISP_SCK]);
-	const uint8_t miso = prom_pin(prom->data_pins[ISP_MISO]);
-	uint8_t rc = 0;
-
-	for (uint8_t i = 0 ; i < 8 ; i++, byte <<= 1)
-	{
-		out(mosi, (byte & 0x80) ? 1 : 0);
-		isp_clock(8);
-
-		out(sck, 1);
-		isp_clock(8);
-
-		rc = (rc << 1) | (in(miso) ? 1 : 0);
-		out(sck, 0);
-		//isp_clock(2);
-
-	}
-
-	return rc;
-}
-
-
-/** Read a byte using the AVRISP, instead of the normal PROM format.
- * \todo: prom_setup() to enter programming mode
- * \todo: Clock on XTAL1
- */
-static uint8_t
-isp_read(
-	uint32_t addr
-)
-{
-	prom_setup();
-
-	// Pulse the RESET pin, while holding SCK low.
-	const uint8_t sck = prom_pin(prom->addr_pins[ISP_SCK]);
-	const uint8_t reset = prom_pin(prom->addr_pins[ISP_RESET]);
-	const uint8_t miso = prom_pin(prom->data_pins[ISP_MISO]);
-	out(sck, 0);
-	out(reset, 1);
-	isp_clock(4);
-	out(reset, 0);
-	isp_clock(255);
-
-	// Now delay at least 20 ms
-	_delay_ms(20);
-
-	uint8_t rc1, rc2, rc3, rc4;
-
-	// Enter programming mode; enable pull up on the MISO pin
-	out(miso, 1);
-
-	rc1 = isp_write(0xAC);
-	rc2 = isp_write(0x53);
-	rc3 = isp_write(0x12);
-	rc4 = isp_write(0x34);
-
-	// Disable pull up
-	out(miso, 0);
-
-	// Now show what we read
-	uint8_t buf[10];
-	buf[0] = hexdigit(rc1 >> 4);
-	buf[1] = hexdigit(rc1 >> 0);
-	buf[2] = hexdigit(rc2 >> 4);
-	buf[3] = hexdigit(rc2 >> 0);
-	buf[4] = hexdigit(rc3 >> 4);
-	buf[5] = hexdigit(rc3 >> 0);
-	buf[6] = hexdigit(rc4 >> 4);
-	buf[7] = hexdigit(rc4 >> 0);
-
-	buf[8] = '\r';
-	buf[9] = '\n';
-
-	usb_serial_write(buf, sizeof(buf));
-	return 0;
-}
-
-
 /** Read a byte from the PROM at the specified address..
  * \todo Update this to handle wider than 8-bit PROM chips.
  */
 	uint32_t addr
 )
 {
-	if (prom->data_width == 1)
+	if (prom->data_width == 0)
 		return isp_read(addr);
 
 	prom_set_address(addr);
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.