Logo Search packages:      
Sourcecode: s51dude version File versions

s51dude.c

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
/*
 * s51dude - A Downloader/Uploader for 8051 device programmers
 * Copyright (C) 2008 Lucas Chiesa.
 *
 * 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 of the License, 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <usb.h>

#include "parts.h"
#include "s51dude.h"
#include "usbtiny.h"

global_options    options;
int verify_flag = 1;
int verbose_flag = 0;
int dry_run_flag = 0;
int debug_flag = 0;

static unsigned char* code_buffer;
static unsigned char* read_buffer;

usb_dev_handle *usb_handle;
int   sck_period = 10;

void print_if_verbose (char *msg)
{
      if (verbose_flag) fprintf(stderr,"%s\n",msg);
}

inline void print_error(char *msg)
{
      fprintf(stderr,"%s\n",msg);
}

void check_open_file (void)
{
      if (!options.file) {
            print_error ("ERROR: Can't open file!!");
            exit_nice();
      }
}

inline void usbtiny_configure(int ind)
{
      usb_control(CONFIGURE_MSG, options.val, ind);
}

void enable_programing()
{     
      unsigned char res[4];         
      usbtiny_trasnparent_spi(options.enable_programing,res);
      usleep(10000);
}

void erase_target()
{
      unsigned char res[4];         
      usbtiny_trasnparent_spi(options.erase,res);
      sleep(1); //TODO: pasar el tiempo como parametro del micro.
}

uint16_t read_hex_file()
{

      int   salida_parser;
      IHexRecord buffer_hex;
      uint16_t buffer_size = 0;

      int i;

      // Alocamos un buffer del tamano de la memoria del micro.
      code_buffer = (unsigned char*) malloc (options.mem_micro * sizeof(unsigned char));
      if (!code_buffer)  {
            print_error ("Tenes un problema muy feo...");
            exit_nice();
      }
      // Cargo el buffer con 0xFF.
      memset(code_buffer,0xFF,options.mem_micro);

      i = 1;
      while ( i ) {
            salida_parser = Read_IHexRecord(&buffer_hex, options.file);
            switch (salida_parser) {
                  case IHEX_ERROR_FILE:
                  case IHEX_ERROR_INVALID_ARGUMENTS:
                  case IHEX_ERROR_INVALID_RECORD:
                        print_error ("ERROR: Bad hex file");
                        exit_nice();
                        break;
                  case IHEX_ERROR_EOF:
                        i = 0;
                  case IHEX_OK:
                        if (buffer_hex.type == IHEX_TYPE_00) {
                              // Guardo el ultimo address para saber el tamano del buffer
                              // del codigo.
                              buffer_size = buffer_hex.address + buffer_hex.dataLen;
                              // Valido que el archivo sea menor que la memoria del micro.
                              if (buffer_size > options.mem_micro)
                              {
                                    print_error ("ERROR: file too large for target");
                                    exit_nice();
                              }
                              memcpy(code_buffer+buffer_hex.address, &(buffer_hex.data), buffer_hex.dataLen);
                        }
                        break;
            }
      }

      if (debug_flag) {
            printf("\n%s\n","DEBUG>> Buffer to progam");
            for (i = 0; i < buffer_size; i++)
                  printf("0x%02X, ", code_buffer[i]);
            printf("\n%s\n","DEBUG>> END buffer to program");
      }

      return buffer_size;
}


uint16_t upload(void)
{
      uint16_t buffer_size;
      uint16_t chunk;   
      
      int i;
      
      buffer_size = read_hex_file();
      
      /* Configure the usbtiny */
      if (!dry_run_flag) {
            usbtiny_configure(options.ind_w_flash);
            enable_programing();
            erase_target();
      }
      /* Upload the code to the target device */

      for ( i = 0; i < buffer_size;i+= chunk )
      {
            chunk = CHUNK_SIZE;
            if ( CHUNK_SIZE > (buffer_size - i) )
                  chunk = buffer_size - i;
            
            if (!dry_run_flag)
            {
                  usb_out(USBTINY_FLASH_WRITE,options.delay,i,code_buffer + i, chunk, 32 * sck_period + options.delay);
            }
      }
      
      return buffer_size;
}

void read_mem(unsigned int size_mem)
{
      unsigned int i,chunk;

      read_buffer = (unsigned char*) malloc (size_mem * sizeof(unsigned char));
      // Seteo la memoria con 0xFF para no usar memoria sin inicializar cuando
      // se usa el dry_run.
      memset(read_buffer,0xFF,size_mem);

      /* Configure the usbtiny */
      if (!dry_run_flag) {
            usbtiny_configure(options.ind_r_flash);
            enable_programing();          
      }

      for ( i = 0; i < size_mem;i+= chunk )
      {
            chunk = CHUNK_SIZE;
            if ( CHUNK_SIZE > (options.mem_micro - i) )
                  chunk = options.mem_micro - i;
            
            if (!dry_run_flag)
            {
                  usb_in(USBTINY_FLASH_READ,0,i,read_buffer + i, chunk, 32 * sck_period);
            }
      }

      if (debug_flag) {
            printf("\n%s\n","DEBUG>> Read buffer");
            for (i = 0; i < size_mem; i++)
                  printf("0x%02X, ", read_buffer[i]);
            printf("\n%s\n","DEBUG>> END read buffer");
      }
      
}

void write_hex_file(uint16_t file_size)
{
      uint16_t i, record_size;
      
      IHexRecord temp;
      
      for ( i = 0; i < file_size; i+= record_size )
      {
            record_size = RECORD_SIZE;
            if ( RECORD_SIZE > (file_size - i) )
                  record_size = file_size - i;
            
            New_IHexRecord(0, i, read_buffer+i, record_size, &temp);
            Write_IHexRecord (temp, options.file);
      }
      
      New_IHexRecord(1, 0, NULL, 0, &temp);
      Write_IHexRecord (temp, options.file);
}


int verify(uint16_t size)
{
      read_mem (size);
      return !(memcmp(read_buffer,code_buffer,size));
}

void print_params()
{
      printf("%s","Target part: ");
      printf("%s\n",options.text_micro);
      
      printf("%s","Action: ");
      if (options.operation == UPLOAD) printf("%s\n", "UPLOAD");
      if (options.operation == READ) printf("%s\n","READ");
      if (options.operation == ERASE) printf("%s\n","ERASE");
      
      printf("%s","Verify: ");
      if (verify_flag) printf("%s\n", "YES");
      if (!verify_flag) printf("%s\n", "NO");
      
      printf("%s","Dry-run: ");
      if (dry_run_flag) printf("%s\n", "YES");
      if (!dry_run_flag) printf("%s\n", "NO");
}

int main(int argc, char * argv [])
{
      options.operation = NAA;
      options.micro = NAP;
      
      int aux;
      
      get_params (argc, argv);
      if (options.micro == NAP) {
            print_error ("Error: You must specify a part name");
            exit_nice();
      }
      if (verbose_flag) print_params();

      if (!dry_run_flag) {
            if ( ! usbtiny_open()) {
                  print_error("Error: Could not find USBtiny device");
                  exit_nice();
            }
            usbtiny_powerup();
            if (verbose_flag) printf("%s\n","* Found USB programmer");;
      }
      
      switch (options.operation) {
            case UPLOAD:
                  options.file = fopen (options.path, "r");
                  check_open_file();
                  aux = upload();
                  fclose(options.file);
                  if (verify_flag) {
                        if (verify(aux)) {
                              printf("%s\n","* Upload completed successfully!! :)");
                        } else {
                              print_error ("ERROR: Verify error! :(");
                        }
                  } else {
                        printf("%s\n","* Upload completed but not verified.");
                  }
                  break;
            case READ:
                  options.file = fopen (options.path, "w");
                  check_open_file();
                  read_mem(options.mem_micro);
                  write_hex_file(options.mem_micro);
                  fclose(options.file);
                  break;
            case ERASE:
                  if (!dry_run_flag) {
                        usbtiny_configure(options.ind_w_flash);
                        enable_programing();
                        erase_target();
                        printf("%s\n","* Target erased.");
                  }
                  break;
            case NAA:
                  print_error ("ERROR: You should give me something to do!");
                  exit_nice();
      }

      if (!dry_run_flag) usbtiny_powerdown ();
      free_mem();
      return 0;
}

void exit_nice (void)
{
      if (!dry_run_flag && usb_handle) usbtiny_powerdown ();
      free_mem();
      exit(1);
}

void free_mem (void)
{
      if (read_buffer) free(read_buffer);
      if (code_buffer) free(code_buffer);
      if (options.text_micro) free(options.text_micro);
      if (usb_handle) free(usb_handle);
      if (options.path) free(options.path);
}

Generated by  Doxygen 1.6.0   Back to index