Main Page | Modules | Related Pages | Examples

avrprog/module-src/isp.c

/*
 * Turbo Programmer Utilities, turbo-prog-utils, www.bladox.com 
 *
 * Copyright (C) 2004 BLADOX, s.r.o.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 */

/*
 * This file is based on uisp by Uros Platise
 * (c) 1997-1999 Uros Platise, 2000-2003 Marek Michalkiewicz
 * http://savannah.nongnu.org/download/uisp/
 */


#include <config.h>
#include <tprog/tprog.h>

#include "../../usbprog/pins.h"

#include "isp.h"

#include <avr/io.h>

void ispSckDelay ()
{
//    delayUs(3);
  delayUs (10);
}

void ispOutReset (u8 resetValue)
{
  u8 tmpResetValue;

  tmpResetValue = inb (PROG_RESETn_PORT);
  if (resetValue == 0)
    tmpResetValue = tmpResetValue & ~(1 << PROG_RESETn_PORT_PIN);
  else
    tmpResetValue = tmpResetValue | (1 << PROG_RESETn_PORT_PIN);
  outb (PROG_RESETn_PORT, tmpResetValue);
}

void ispOutSck (u8 sckValue)
{
  u8 tmpSckValue;

  tmpSckValue = inb (PROG_SCK_PORT);
  if (sckValue == 0)
    tmpSckValue = tmpSckValue & ~(1 << PROG_SCK_PORT_PIN);
  else
    tmpSckValue = tmpSckValue | (1 << PROG_SCK_PORT_PIN);
  outb (PROG_SCK_PORT, tmpSckValue);
}

u8 ispSendRecv (u8 b)
{
  // clear flag
  inb (SPSR);
  inb (SPDR);
  // send char to SPI
  outb (SPDR, b);
  // wait until char was transmitted
  loop_until_bit_is_set (SPSR, SPIF);
  // return received value
  return inb (SPDR);
}

u16 ispSend (u8 * queue, int queueSize)
{
  u8 *p = queue, ch;
  int i = queueSize;

  while (i--)
  {
    ch = ispSendRecv (*p);
    *p++ = ch;
  }
  return queueSize;
}

void ispPulseSck (void)
{
  ispSckDelay ();
//    __asm__ __volatile__ ("nop");
//    __asm__ __volatile__ ("nop");
  ispOutSck (1);
  ispSckDelay ();
//    __asm__ __volatile__ ("nop");
//    __asm__ __volatile__ ("nop");
  ispOutSck (0);
}

void ispPulseReset (void)
{
  ispOutReset (1);
  ispOutReset (0);
}

u8 ispEnableAvr (void)
{
  u8 prg[4] = { 0xAC, 0x53, 0, 0 };
  int try_number = 32;

  do
  {
    prg[0] = 0xAC;
    prg[1] = 0x53;
    prg[2] = prg[3] = 0;
    ispSend (prg, 4);
    if (prg[2] == 0x53)
      break;
    ispPulseSck ();
//    __asm__ __volatile__ ("nop");
//    __asm__ __volatile__ ("nop");
//    __asm__ __volatile__ ("nop");
  }
  while (try_number--);
  if (try_number >= 0)
    //OK
    return 1;
  else
    //ERROR
    return 0;
}

u8 ispGetPartInfo (u8 addr)
{
  u8 info[4] = { 0x30, 0, addr, 0 };

  ispSend (info, 4);
  return info[3];
}

u8 ispReadByteFlash (unsigned long addr)
{
  u8 readback = 0xFF;
  u8 hl = (addr & 1) ? 0x28 : 0x20;
  u8 flash[4] =
    { hl, (u8) ((addr >> 9) & 0xFF), (u8) ((addr >> 1) & 0xFF), 0 };

  ispSend (flash, 4);
  readback = flash[3];
  return readback;
}

u8 ispReadChunkFlash (unsigned long addr, u8 * chunk, u8 chunkSize)
{
  u8 readback = 0xFF;
  u8 i;
  unsigned long tmpAddr;

  tmpAddr = addr;
  for (i = 0; i < chunkSize; i++)
  {
    readback = ispReadByteFlash (tmpAddr);
    chunk[i] = readback;
    tmpAddr++;
  }
//    return readback;
  return 1;
}

u8 ispReadByteEeprom (unsigned long addr)
{
  u8 readback = 0xFF;
  u8 eeprom[4] = { 0xA0, (u8) ((addr >> 8) & 0xFF), (u8) (addr & 0xFF), 0 };

  ispSend (eeprom, 4);
  readback = eeprom[3];
  return readback;
}

u8 ispReadChunkEeprom (unsigned long addr, u8 * chunk, u8 chunkSize)
{
  u8 readback = 0xFF;
  u8 i;
  unsigned long tmpAddr;

  tmpAddr = addr;
  for (i = 0; i < chunkSize; i++)
  {
    readback = ispReadByteEeprom (tmpAddr);
    chunk[i] = readback;
    tmpAddr++;
  }
  return 1;
}

u8 ispReadLockBits ()
{
  u8 lockfuse[4] = { 0x58, 0, 0, 0 };

  ispSend (lockfuse, 4);
  return lockfuse[3];
}

u8 ispReadFuseLowBits ()
{
  u8 fuselow[4] = { 0x50, 0, 0, 0 };

  ispSend (fuselow, 4);
  return fuselow[3];
}

u8 ispReadFuseHighBits ()
{
  u8 fusehigh[4] = { 0x58, 0x08, 0, 0 };

  ispSend (fusehigh, 4);
  return fusehigh[3];
}

u8 ispReadFuseExtBits ()
{
  u8 fuseext[4] = { 0x50, 0x08, 0, 0 };

  ispSend (fuseext, 4);
  return fuseext[3];
}

u8 ispReadCalByte (u8 addr)
{
  u8 cal[4] = { 0x38, 0, addr, 0 };

  ispSend (cal, 4);
  return cal[3];
}

void ispWriteOldFuseBits (u8 val)
{
  u8 oldfuse[4] = { 0xAC, (val & 0x1F) | 0xA0, 0, 0xD2 };
  ispSend (oldfuse, 4);
}

void ispWriteFuseLowBits (u8 val)
{
  u8 fuselow[4] = { 0xAC, 0xA0, 0, val };
  ispSend (fuselow, 4);
}

void ispWriteFuseHighBits (u8 val)
{
  u8 fusehigh[4] = { 0xAC, 0xA8, 0, val };
  ispSend (fusehigh, 4);
}

void ispWriteFuseExtBits (u8 val)
{
  u8 fuseext[4] = { 0xAC, 0xA4, 0, val };
  ispSend (fuseext, 4);
}

void ispChipErase ()
{
  u8 chip_erase[4] = { 0xAC, 0x80, 0x00, 0x00 };
  ispSend (chip_erase, 4);
  delayUs (9000);
  delayUs (9000);
  ispPulseReset ();
  ispEnableAvr ();
}

void ispWriteLockBits (u8 bits)
{
  u8 lock[4] = { 0xAC, 0xF9 | ((bits << 1) & 0x06), 0xFF, bits };
  u8 rbits;

  ispSend (lock, 4);
  delayUs (9000);
  ispPulseReset ();
  ispEnableAvr ();
}

void ispWriteByteFlash (unsigned long addr, u8 val)
{
  u8 flash[4] = { 0x40 | ((addr & 0x01) << 3), 0, ((addr >> 1) & 0xFF), val };
  ispSend (flash, 4);
}

u8 ispWriteChunkFlash (unsigned long addr, u8 * chunk, u8 chunkSize)
{
  u8 readback;
  u8 i;
  unsigned long tmpAddr;
  u16 j;

  tmpAddr = addr;
  for (i = 0; i < chunkSize; i++)
  {
    ispWriteByteFlash (tmpAddr, chunk[i]);
    tmpAddr++;
  }
  return 1;
}

u8 ispWriteByteEeprom (unsigned long addr, u8 val)
{
  u8 readback;
  u8 eeprom[4] = { 0xC0, (addr >> 8), (addr & 0xFF), val };
  u16 j;

  readback = ispReadByteEeprom (addr);
  if (readback == val)
    return 0;

  ispSend (eeprom, 4);
  for (j = 0; j < 100; j++)
  {
    delayUs (1000);
    readback = ispReadByteEeprom (addr);
    if (readback == val)
      j = 100;
  }

  if (readback != val)
    return 1;
  return 0;
}

// 1 OK
// 0 ERROR
u8 ispWriteChunkEeprom (unsigned long addr, u8 * chunk, u8 chunkSize)
{
  u8 readback;
  u8 i;
  unsigned long tmpAddr;
  u16 j;
  u8 err;

  tmpAddr = addr;
  for (i = 0; i < chunkSize; i++)
  {
    err = ispWriteByteEeprom (tmpAddr, chunk[i]);
    if (err == 1)
      return 0;
    tmpAddr++;
  }
  return 1;
}

void ispWriteProgramMemoryPage (unsigned long pageAddr)
{
  u8 prg_page[4] =
    { 0x4C, (u8) ((pageAddr >> 9) & 0xFF), (u8) ((pageAddr >> 1) & 0xFF), 0 };

  ispSend (prg_page, 4);
  delayUs (5000);
}


Copyright © 2004 BLADOX
Turbo Programmer version 2.0