ATTiny2313 Self-Programming Help

I’m trying to interface an ATTiny2313 IC directly with my FEZ Panda II, to try and manually use the Self-Programming SPI Interface, as a fun challenge for myself.

First, here is how it’s connected

FEZ   -> ATTiny2313
SCK1  -> Pin19(UCSK)
MISO1 -> Pin18(MISO)
MOSI1 -> Pin17(MOSI)
D52   -> Pin1(/RESET)
5V    -> Pin20(VCC)
GND   -> Pin10(GND)

Note that I don’t have any other components, just direct wires between the pins.

Here’s the actual code:

    public class Program
    {
        private static readonly OutputPort StatusLed = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.LED, false);

        private static readonly SPI.Configuration SPI1Config = new SPI.Configuration(
            // The chip select port.
            (Cpu.Pin)FEZ_Pin.Digital.Di52,

            // The active state for the chip select port.
            // If true, the chip select port will be set to high when accessing the chip.
            // If false, the chip select port will be set to low when accessing the chip.
            false, // Manual says /RESET must be pulled to GND when programming.

            // The setup time for the chip select port.
            // In other words, this parameter specifies the amount of time that will elapse between the time at which the device is selected and the time at which the clock and the clock data transmission will start.
            50, // Manual says wait at least 20 ms before data transmission.

            // The hold time for the chip select port.
            // In other words, this parameter specifies the amount of time that the chip select port must remain in the active state before the device is unselected, or the amount of time that the chip select will remain in the active state after the data read/write transaction has been completed.
            0,

            // The idle state of the clock. 
            // If true, the SPI clock signal will be set to high while the device is idle
            // If false, the SPI clock signal will be set to low while the device is idle.
            // The idle state occurs whenever the chip is not selected.
            false, // NOTE: I'm unsure about this value.

            // The sampling clock edge. 
            // If true, data is sampled on the SPI clock rising edge.
            // If false, the data is sampled on the SPI clock falling edge.
            true, // "When writing serial data to the ATtiny2313, data is clocked on the rising edge of SCK."

            // The SPI clock rate in KHz.
            1000, // 1MHz

            // The SPI bus used for the transaction.
            SPI.SPI_module.SPI1);

        private static readonly SPI SPI1 = new SPI(SPI1Config);

        private static readonly Byte[] ProgrammingEnable = new Byte[] { 0xAC, 0x53, 0x00, 0x00 };

        private static readonly Byte[] Response = new Byte[] { 0x00, 0x00, 0x00, 0x00 };

        public static void Main()
        {
            Thread.Sleep(500);

            StatusLed.Write(true);

            SPI1.WriteRead(ProgrammingEnable, Response);
            Debug.Print(Response[0].ToString());
            Debug.Print(Response[1].ToString());
            Debug.Print(Response[2].ToString());
            Debug.Print(Response[3].ToString());

            StatusLed.Write(false);

            Thread.Sleep(Timeout.Infinite);
        }
    }

Now, after testing that, all I get as the response is {0xFF, 0xFF, 0xFF, 0xFF}, which isn’t supposed to happen.

Now what I’m unsure about is the SPI configuration.
I choose the Di52 pin as the chip select port, since it connects directly to /RESET, as that’s what’s controlling if we’re programming or not, is this incorrect? Also, does it “pull to GND” when the select port is false?

I realize this may seem like a silly/odd project, and you’ll likely suggest I simply get an USB programmer, but I already have an USB programmer, I’m doing this just for the challenge, and to see if it’s possible.

[url=ATTiny2313 Manual]Smart | Connected | Secure | Microchip Technology
Page 172 explains the SPI interface.

This line declares the Response array as read only, which could cause the weird result:

private static readonly Byte[] Response = new Byte[] { 0x00, 0x00, 0x00, 0x00 };

SPI1.WriteRead must be able to change the content of the Response array. So just replace the line with the following:

private static Byte[] Response = new Byte[] { 0x00, 0x00, 0x00, 0x00 };

Are you sure that the response will only be four bytes long?

The “Response” being readonly only means you can’t create a new array, it doesn’t mean you can’t change the contents. Take this example:

...
    private static readonly Byte[] Response = new Byte[] { 0x00, 0x00, 0x00, 0x00 };
...

...
    ...
        // The following is legal code.
        Response[0] = 0xAC;
        Response[1] = 0x53;
        Response[2] = 0x00;
        Response[3] = 0x00;

        // The following isn't legal and wont compile.
        Response = new Byte[] { 0xAC, 0x53, 0x00, 0x00 };

        // Assume the hypothetical method
        // SPI.ReadWrite(Message, out Response);
        // This would be illegal again, as the "out" keyword requires write access to the variable.
    ...
... 

A quick lesson in C#. :wink:

Also, the response should be 4 bytes, as the Self-Programming protocol is a 4 byte protocol. Each outgoing message is 4 bytes, and the ingoing messages should be 4 bytes as well.

Ok, my mistake. Thanks for clarification. 8)