Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***********************************************************************
  2.  *
  3.  *  avra - Assembler for the Atmel AVR microcontroller series
  4.  *
  5.  *  Copyright (C) 1998-2004 Jon Anders Haugum, Tobias Weber
  6.  *
  7.  *  This program is free software; you can redistribute it and/or modify
  8.  *  it under the terms of the GNU General Public License as published by
  9.  *  the Free Software Foundation; either version 2 of the License, or
  10.  *  (at your option) any later version.
  11.  *
  12.  *  This program is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *  GNU General Public License for more details.
  16.  *
  17.  *  You should have received a copy of the GNU General Public License
  18.  *  along with this program; see the file COPYING.  If not, write to
  19.  *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20.  *  Boston, MA 02111-1307, USA.
  21.  *
  22.  *
  23.  *  Authors of avra can be reached at:
  24.  *     email: jonah@omegav.ntnu.no, tobiw@suprafluid.com
  25.  *     www: http://sourceforge.net/projects/avra
  26.  */
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <time.h>
  32. #include <unistd.h> /* B.A. for unlink function */
  33.  
  34.  
  35. #include "misc.h"
  36. #include "avra.h"
  37. #include "args.h"
  38.  
  39.  
  40. int open_out_files(struct prog_info *pi, char *filename)
  41. {
  42.         int length;
  43.         char *buff;
  44.         int ok = True; /* flag for coff results */
  45.  
  46.         length = strlen(filename);
  47.         buff = malloc(length + 9);
  48.         if(buff == NULL) {
  49.           print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  50.     return(False);
  51.   }
  52.   strcpy(buff, filename);
  53.   if(length < 4) {
  54.     printf("Error: wrong input file name\n");
  55.   }
  56.   if(!nocase_strcmp(&buff[length - 4], ".asm")) {
  57.           length -= 4;
  58.           buff[length] = '\0';
  59.         }
  60.   //printf("pi->cseg_count = %i\n", pi->cseg_count);
  61.   //printf("pi->eseg_count = %i\n", pi->eseg_count);
  62.        
  63.         /* open files for code output */
  64.   strcpy(&buff[length], ".hex");
  65.         if(!(pi->hfi = open_hex_file(buff))) { /* check if open failed */
  66.     print_msg(pi, MSGTYPE_ERROR, "Could not create output hex file!");
  67.     ok = False;
  68.   }
  69.   strcpy(&buff[length], ".obj");
  70.   if(!(pi->obj_file = open_obj_file(pi, buff))) {
  71.     print_msg(pi, MSGTYPE_ERROR, "Could not create object file!");
  72.     ok = False;
  73.   }  
  74.        
  75.         /* open files for eeprom output */
  76.   strcpy(&buff[length], ".eep.hex");
  77.   if(!(pi->eep_hfi = open_hex_file(buff))) {
  78.                 print_msg(pi, MSGTYPE_ERROR, "Could not create eeprom hex file!");
  79.     ok = False;
  80.   }  
  81.   /* coff file is always generated */
  82.   strcpy(&buff[length], ".cof");
  83.         pi->coff_file = open_coff_file(pi, buff);
  84.   /* open list file */
  85.         if (pi->list_on) {
  86.     strcpy(buff, GET_ARG(pi->args, ARG_LISTFILE));
  87.     pi->list_file = fopen(buff, "w");
  88.     if(pi->list_file == NULL) {
  89.                         print_msg(pi, MSGTYPE_ERROR, "Could not create list file!");
  90.       ok = False;
  91.     }
  92.     /* write list file header */
  93.     fprintf(pi->list_file, "\nAVRA   Ver. %i.%i.%i %s %s\n\n",VER_MAJOR, VER_MINOR, VER_RELEASE, filename, ctime(&pi->time));
  94.   }
  95.   else {
  96.     pi->list_file = NULL;
  97.   }
  98.   free(buff);
  99.  
  100.         if(ok)
  101.           return(True);
  102.   else
  103.           close_out_files(pi);
  104.   return(False);
  105. }
  106.  
  107. /* delete all output files */
  108. void unlink_out_files(struct prog_info *pi, char *filename)
  109. {
  110.         char *buff;
  111.         int length;
  112.  
  113.   close_out_files(pi);
  114.  
  115.         length = strlen(filename);
  116.         buff = malloc(length + 9);
  117.         if(buff == NULL) {
  118.           print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
  119.     return;
  120.   }
  121.   strcpy(buff, filename);
  122.   if(!nocase_strcmp(&buff[length - 4], ".asm")) {
  123.           length -= 4;
  124.           buff[length] = '\0';
  125.         }
  126. #if debug == 1
  127.   printf("unlinking files");
  128. #endif
  129.   strcpy(&buff[length], ".hex");
  130.   unlink(buff);
  131.   strcpy(&buff[length], ".obj");
  132.   unlink(buff);
  133.   strcpy(&buff[length], ".eep.hex");
  134.   unlink(buff);
  135.   strcpy(&buff[length], ".cof");
  136.   unlink(buff);
  137.   strcpy(&buff[length], ".lst");
  138.   unlink(buff);
  139.   strcpy(&buff[length], ".map");
  140.   unlink(buff);
  141. }  
  142.  
  143. void close_out_files(struct prog_info *pi)
  144. {
  145.   char stmp[2048];
  146.  
  147.         if(pi->error_count == 0) {
  148.                 sprintf(stmp,
  149.       "Segment usage:\n"
  150.                   "   Code      :   %7d words (%d bytes)\n"
  151.                   "   Data      :   %7d bytes\n"
  152.                   "   EEPROM    :   %7d bytes\n",
  153.                   pi->cseg_count, pi->cseg_count * 2, pi->dseg_count, pi->eseg_count);
  154.     printf("%s", stmp);
  155.         }
  156.         if(pi->hfi)
  157.     close_hex_file(pi->hfi);
  158.         if(pi->eep_hfi)
  159.     close_hex_file(pi->eep_hfi);
  160.         if(pi->list_file) {
  161.           fprintf(pi->list_file, "\n\n%s", stmp);
  162.                 if(pi->error_count == 0)
  163.                         fprintf(pi->list_file, "\nAssembly completed with no errors.\n");
  164.                 fclose(pi->list_file);
  165.         }
  166.         if(pi->obj_file)
  167.     close_obj_file(pi, pi->obj_file);
  168.         if(pi->coff_file)
  169.     close_coff_file(pi, pi->coff_file);
  170. }
  171.  
  172.  
  173. struct hex_file_info *open_hex_file(char *filename)
  174. {
  175.         struct hex_file_info *hfi;
  176.  
  177.         hfi = calloc(1, sizeof(struct hex_file_info));
  178.         if(hfi) {
  179.                 hfi->segment = -1;
  180.                 hfi->fp = fopen(filename, "wb");
  181.                 if(!hfi->fp) {
  182.                         close_hex_file(hfi);
  183.                         hfi = NULL;
  184.                 }
  185.         }
  186.         return(hfi);
  187. }
  188.  
  189.  
  190. void close_hex_file(struct hex_file_info *hfi)
  191. {
  192.         if(hfi->fp) {
  193.                 if(hfi->count != 0)
  194.                   do_hex_line(hfi);
  195.                 fprintf(hfi->fp, ":00000001FF\x0d\x0a");
  196.                 fclose(hfi->fp);
  197.         }
  198.         free(hfi);
  199. }
  200.  
  201.  
  202. void write_ee_byte(struct prog_info *pi, int address, unsigned char data)
  203. {
  204.         if((pi->eep_hfi->count == 16) || ((address != (pi->eep_hfi->linestart_addr + pi->eep_hfi->count)) && (pi->eep_hfi->count != 0)))
  205.                 do_hex_line(pi->eep_hfi);
  206.         if(pi->eep_hfi->count == 0)
  207.                 pi->eep_hfi->linestart_addr = address;
  208.         pi->eep_hfi->hex_line[pi->eep_hfi->count++] = data;
  209.  
  210.         if(pi->coff_file)
  211.                 write_coff_eeprom(pi, address, data);
  212. }
  213.  
  214. void write_prog_word(struct prog_info *pi, int address, int data)
  215. {
  216.         write_obj_record(pi, address, data);
  217.         address *= 2;
  218.         if(pi->hfi->segment != (address >> 16)) {
  219.           if(pi->hfi->count != 0)
  220.             do_hex_line(pi->hfi);
  221.           pi->hfi->segment = address >> 16;
  222.           if(pi->hfi->segment >= 16) // Use 04 record for addresses above 1 meg since 02 can support max 1 meg
  223.             fprintf(pi->hfi->fp, ":02000004%04X%02X\x0d\x0a", pi->hfi->segment & 0xffff,
  224.                     (0 - 2 - 4 - ((pi->hfi->segment >> 8) & 0xff) - (pi->hfi->segment & 0xff)) & 0xff);
  225.           else // Use 02 record for addresses below 1 meg since more programmers know about the 02 instead of the 04
  226.             fprintf(pi->hfi->fp, ":02000002%04X%02X\x0d\x0a", (pi->hfi->segment << 12) & 0xffff,
  227.                     (0 - 2 - 2 - ((pi->hfi->segment << 4) & 0xf0)) & 0xff);
  228.         }
  229.         if((pi->hfi->count == 16) || ((address != (pi->hfi->linestart_addr + pi->hfi->count)) && (pi->hfi->count != 0)))
  230.                 do_hex_line(pi->hfi);
  231.         if(pi->hfi->count == 0)
  232.                 pi->hfi->linestart_addr = address;
  233.         pi->hfi->hex_line[pi->hfi->count++] = data & 0xff;
  234.         pi->hfi->hex_line[pi->hfi->count++] = (data >> 8) & 0xff;
  235.  
  236.         if(pi->coff_file != 0)
  237.                 write_coff_program(pi, address, data);
  238. }
  239.  
  240.  
  241. void do_hex_line(struct hex_file_info *hfi)
  242. {
  243.         int i;
  244.         unsigned char checksum = 0;
  245.  
  246.         fprintf(hfi->fp, ":%02X%04X00", hfi->count, hfi->linestart_addr & 0xffff);
  247.         checksum -= hfi->count + ((hfi->linestart_addr >> 8) & 0xff) + (hfi->linestart_addr & 0xff);
  248.         for(i = 0; i < hfi->count; i++) {
  249.                 fprintf(hfi->fp, "%02X", hfi->hex_line[i]);
  250.                 checksum -= hfi->hex_line[i];
  251.         }
  252.         fprintf(hfi->fp, "%02X\x0d\x0a", checksum);
  253.         hfi->count = 0;
  254. }
  255.  
  256.  
  257. FILE *open_obj_file(struct prog_info *pi, char *filename)
  258. {
  259.         int i;
  260.         FILE *fp;
  261.         struct include_file *include_file;
  262.  
  263.         fp = fopen(filename, "wb");
  264.         if(fp) {
  265.                 i = pi->cseg_count * 9 + 26;
  266.                 fputc((i >> 24) & 0xff, fp);
  267.                 fputc((i >> 16) & 0xff, fp);
  268.                 fputc((i >> 8) & 0xff, fp);
  269.                 fputc(i & 0xff, fp);
  270.                 i = 26;
  271.                 fputc((i >> 24) & 0xff, fp);
  272.                 fputc((i >> 16) & 0xff, fp);
  273.                 fputc((i >> 8) & 0xff, fp);
  274.                 fputc(i & 0xff, fp);
  275.                 fputc(9, fp);
  276.                 i = 0;
  277.                 for(include_file = pi->first_include_file; include_file; include_file = include_file->next)
  278.                         i++;
  279.                 fputc(i, fp);
  280.                 fprintf(fp, "AVR Object File");
  281.                 fputc('\0', fp);
  282.         }
  283.         return(fp);
  284. }
  285.  
  286.  
  287. void close_obj_file(struct prog_info *pi, FILE *fp)
  288. {
  289.         struct include_file *include_file;
  290.  
  291.         for(include_file = pi->first_include_file; include_file; include_file = include_file->next) {
  292.                 fprintf(fp, "%s", include_file->name);
  293.                 fputc('\0', fp);
  294.         }
  295.         fputc('\0', fp);
  296.         fclose(fp);
  297. }
  298.  
  299.  
  300. void write_obj_record(struct prog_info *pi, int address, int data)
  301. {
  302.         fputc((address >> 16) & 0xff, pi->obj_file);
  303.         fputc((address >> 8) & 0xff, pi->obj_file);
  304.         fputc(address & 0xff, pi->obj_file);
  305.         fputc((data >> 8) & 0xff, pi->obj_file);
  306.         fputc(data & 0xff, pi->obj_file);
  307.         fputc(pi->fi->include_file->num & 0xff, pi->obj_file);
  308.         fputc((pi->fi->line_number >> 8) & 0xff, pi->obj_file);
  309.         fputc(pi->fi->line_number & 0xff, pi->obj_file);
  310.         if(pi->macro_call)
  311.                 fputc(1, pi->obj_file);
  312.         else
  313.                 fputc(0, pi->obj_file);
  314. }
  315.  
  316. /* end of file.c */
  317.  
  318.