?? fab_custom.c
字號:
/***************************************************************************** * $Id: fab_custom.c,v 1.2 1998/07/28 23:08:48 mcculley Exp $ * * File: fab.c * * Author: Max Okumoto <okumoto@ucsd.edu> * * Abstract: This program generates the code that simulates the dragonball's * intelligent peripheral modules and system interface logic. * * Note: All the registers have specified size and all simulated code * should access the registers appropriately. However we can't * control what pilot programers do :-) In these cases the * *_get_xxx() and *_put_xxx() have to be written. * * 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 <stdarg.h>#include <stdlib.h>#include "../config.h"struct Fab;struct Reg;typedef void Reg_Op(struct Fab *, const struct Reg *);typedef struct Fab { FILE *f_c; /* fp to generated custom.c file */ FILE *f_h; /* fp to generated custom.h file */ int bo; /* byte order */#define FAB_LITTLEENDIAN 0#define FAB_BIGENDIAN 1 int lvl; /* indent level */} Fab;typedef const struct Reg { char *name; /* name of hardware register */ int addr; /* address of hardware register */ int size; /* size of hardware register */ int init; /* reset value of hardware register */ struct { Reg_Op *get; Reg_Op *put; } b; /* byte operations */ struct { Reg_Op *get; Reg_Op *put; } w; /* word operations */ struct { Reg_Op *get; Reg_Op *put; } l; /* word operations */ char *fields;} Reg;/*---------------------------------------------------------------------------* * Helper functions *---------------------------------------------------------------------------*//*===========================================================================* * Function: putln * * Abstract: This function adds indention to each line. * * Note: No state is kept between calls, so each fmt must contain * complete lines. *===========================================================================*/static voidputln(Fab *f, const char fmt[], ...){ const char *p; int count; char *new_fmt; char *s; va_list ap; va_start(ap, fmt); /* * Calc the size of new_fmt string. (fmt.len + #newlines * #lvl) */ count = 0; for (p = fmt; *p != '\0'; p++) { count += (*p == '\n') ? (1 + f->lvl) : 1; } new_fmt = malloc(count + 1 + f->lvl); s = new_fmt; /* * Add tab characters to the begining of each line. */ if (fmt[0] == '\n' && fmt[1] == '\0') { /* do nothing */ } else { int i; for (i = 0; i < f->lvl; i++) *s++ = '\t'; } for (p = fmt; *p != '\0'; p++) { *s++ = *p; if (p[0] == '\n' && p[1] != '\0' && p[1] != '\n') { int i; for (i = 0; i < f->lvl; i++) *s++ = '\t'; } } *s++ = '\0'; /* * Output line. */ vfprintf(f->f_c, new_fmt, ap); free(new_fmt); va_end(ap);}/*---------------------------------------------------------------------------* * Operation generators *---------------------------------------------------------------------------*//* * Generic */static voidreg_get(Fab *f, Reg *r){ putln(f,"return db_%s.x;\n", r->name);}static voidreg_put(Fab *f, Reg *r){ putln(f,"db_%s.x = value;\n", r->name);}/* * System Control */static voidscr_put(Fab *f, Reg *r){ putln(f,"db_%s.x = value & ~(value & 0xe0);\n", r->name);}/* * Chip Select */static voidcsa1_put(Fab *f, Reg *r){ reg_put(f, r); putln(f,"sram_protect = (value & 0x0008) != 0;\n", r->name);}/* * Phase Locked Loop */static voidpllfsr_get(Fab *f, Reg *r){ putln(f,"db_%s.anon.CLK32 ^= 1;\n", r->name); reg_get(f, r);}/* * Interrupt controller */static voidimr_get_xxx(Fab *f, Reg *r){ putln(f,"return db_%s.x >> 16;\n", r->name); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"return db_%s.x;\n", r->name);}static voidimr_put(Fab *f, Reg *r){ reg_put(f, r); putln(f,"updateisr();\n", r->name);}static voidimr_put_xxx(Fab *f, Reg *r){ putln(f,"db_%s.x &= 0x0000ffff;\n", r->name); putln(f,"db_%s.x |= value << 16;\n", r->name); putln(f,"updateisr();\n", r->name); putln(f,"break;\n"); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"db_%s.x &= 0xffff0000;\n", r->name); putln(f,"db_%s.x |= value;\n", r->name); putln(f,"updateisr();\n", r->name);}static voidiwr_get_xxx(Fab *f, Reg *r){ putln(f,"return db_%s.x >> 16;\n", r->name); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"return db_%s.x;\n", r->name);}static voidiwr_put_xxx(Fab *f, Reg *r){ putln(f,"db_%s.x &= 0x0000ffff;\n", r->name); putln(f,"db_%s.x |= value << 16;\n", r->name); putln(f,"break;\n"); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"db_%s.x &= 0xffff0000;\n", r->name); putln(f,"db_%s.x |= value;\n", r->name);}static voidisr_get_xxx(Fab *f, Reg *r){ putln(f,"return db_%s.x >> 16;\n", r->name); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"return db_%s.x;\n", r->name);}static voidisr_put(Fab *f, Reg *r){ putln(f,"if (db_ICR.anon.ET1 && (value & 0x00010000)) {\n" " db_IPR.anon.IRQ1 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET2 && (value & 0x00020000)) {\n" " db_IPR.anon.IRQ2 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET3 && (value & 0x00040000)) {\n" " db_IPR.anon.IRQ3 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET6 && (value & 0x00080000)) {\n" " db_IPR.anon.IRQ6 = 0;\n" " updateisr();\n" "}\n" "if (value & 0x00800000) {\n" " db_IPR.anon.IRQ7 = 0;\n" " updateisr();\n" "}\n");}static voidisr_put_xxx(Fab *f, Reg *r){ putln(f,"if (db_ICR.anon.ET1 && (value & 0x0001)) {\n" " db_IPR.anon.IRQ1 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET2 && (value & 0x0002)) {\n" " db_IPR.anon.IRQ2 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET3 && (value & 0x0004)) {\n" " db_IPR.anon.IRQ3 = 0;\n" " updateisr();\n" "}\n" "if (db_ICR.anon.ET6 && (value & 0x0008)) {\n" " db_IPR.anon.IRQ6 = 0;\n" " updateisr();\n" "}\n" "if (value & 0x0080) {\n" " db_IPR.anon.IRQ7 = 0;\n" " updateisr();\n" "}\n"); putln(f,"break;\n"); f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"/* updateisr(); */\n");}static voidipr_get(Fab *f, Reg *r){ putln(f,"db_%s.anon.PEN = CustShptr->pen;\n", r->name); reg_get(f, r);}static voidipr_get_xxx(Fab *f, Reg *r){ putln(f,"db_%s.anon.PEN = CustShptr->pen;\n", r->name); putln(f,"return db_%s.x >> 16;\n", r->name);#if CHECKME f->lvl -= 2; putln(f," case %s + 2:\n", r->name); f->lvl += 2; putln(f,"db_%s.anon.PEN = CustShptr->pen;\n", r->name); putln(f,"return db_%s.x;\n", r->name);#endif}static voidipr_put(Fab *f, Reg *r){ putln(f,"/* do nothing */\n", r->name);}/* * Parallel IO */static voidpcdata_get(Fab *f, Reg *r){ putln(f,"db_%s.anon.NMI = 1; /* who knows, this makes the power on key work */\n", r->name); reg_get(f, r);}static voidpddata_put(Fab *f, Reg *r){ putln(f,"db_PDDATA_edge &= ~value;\n" "db_IPR.anon.PEN = CustShptr->pen;\n" "db_IPR.x = (db_IPR.x & 0xffff00ff) |\n" " ((((db_PDDATA_edge & db_PDIRQEDGE.x) |\n" " (db_PDDATA.x & ~db_PDIRQEDGE.x)) & db_PDIRQEN.x) << 8);\n" "updateisr();\n");}static voidpdirqen_put(Fab *f, Reg *r){ reg_put(f, r); putln(f,"db_IPR.anon.PEN = CustShptr->pen;\n" "db_IPR.x = (db_IPR.x & 0xffff00ff) |\n" " ((((db_PDDATA_edge & db_PDIRQEDGE.x) |\n" " (db_PDDATA.x & ~db_PDIRQEDGE.x)) & db_PDIRQEN.x) << 8);\n" "updateisr();\n");}static voidpgdata_put(Fab *f, Reg *r){ reg_put(f, r); putln(f,"CustShptr->Backlight = (value & 0x80);\n");}/* * Pulse Width Modulator */static voidpwmc_get_xxx(Fab *f, Reg *r){ putln(f,"return db_%s.x >> 8;\n", r->name); f->lvl -= 2; putln(f," case %s + 1:\n", r->name); f->lvl += 2; putln(f,"return db_%s.x;\n", r->name);}static voidpwmc_put_xxx(Fab *f, Reg *r){ putln(f,"db_%s.x &= 0x00ff;\n", r->name); putln(f,"db_%s.x |= value << 8;\n", r->name); putln(f,"break;\n"); f->lvl -= 2; putln(f," case %s + 1:\n", r->name); f->lvl += 2; putln(f,"db_%s.x &= 0xff00;\n", r->name); putln(f,"db_%s.x |= value;\n", r->name);}/* * Timer */static voidtstat1_get(Fab *f, Reg *r){ putln(f,"db_TCN1.anon.COUNT += 16;\n" "if (db_TCN1.anon.COUNT - db_TCMP1.anon.COMPARE < 16) {\n" " db_TSTAT1.anon.COMP = 1;\n" " if (db_TCTL1.anon.FRR == 0) {\n" " db_TCN1.anon.COUNT = 0;\n" " }\n" "}\n" "db_TSTAT1_lastseen |= db_TSTAT1.x;\n"); reg_get(f, r);}static voidtstat1_put(Fab *f, Reg *r){ putln(f,"db_TSTAT1.x = db_TSTAT1.x & (value | ~db_TSTAT1_lastseen);\n" "db_TSTAT1_lastseen = 0;\n" "if (db_TSTAT1.anon.COMP == 0) {\n" " db_IPR.anon.TMR1 = 0;\n" " updateisr();\n" "}\n");}static voidtstat2_get(Fab *f, Reg *r){ putln(f,"db_TSTAT2_lastseen |= db_TSTAT2.x;\n"); reg_get(f, r);}static voidtstat2_put(Fab *f, Reg *r){ putln(f,"db_TSTAT2.x = db_TSTAT2.x & (value | ~db_TSTAT2_lastseen);\n" "db_TSTAT2_lastseen = 0;\n" "if (db_TSTAT2.anon.COMP == 0) {\n" " db_IPR.anon.TMR2 = 0;\n" " updateisr();\n" "}\n");}/* * Watchdog */static voidwcn_put(Fab *f, Reg *r){ putln(f,"db_WCN.x = 0;\n");}/* * Serial Peripheral Interface Slave *//*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -