From dc796a209113c3fdc27de0211edcaa67faed7b5f Mon Sep 17 00:00:00 2001 From: oharboe Date: Sun, 6 Jul 2008 19:17:43 +0000 Subject: src/helper/configuration.h - Log output handlers now get a "const char *line" - Added "const" to parameter. src/helper/command.c src/helper/command.h - New function: 'command_output_text()' - Log output handlers now get a "const char *line" src/helper/options.c - Log output handlers now get a "const char *line" src/server/telnet_server.c - DO not transmit NULL bytes via TELNET. - Log output handlers now get a "const char *line" src/server/gdb_server.c - Log output handlers now get a "const char *line" *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/target/target.c *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/target/target.h *** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent previously to the mailing list for TCL users try src/openocd.c - **MAJOR** Work: New TCL/Jim function: mem2array - **MAJOR** Work: Redirect Tcl/Jim stdio output to remote users. - Previously: TCL output did not go to GDB. - Previously: TCL output did not go to TELNET - Previously: TCL output only goes to control console. - This fixes that problem. + Created callbacks: +openocd_jim_fwrite() +openocd_jim_fread() +openocd_jim_vfprintf() +openocd_jim_fflush() +openocd_jim_fgets() src/Makefile.am - New TCL files. - Future note: This should be more automated. As the list of 'tcl' files grows maintaning this list will suck. src/Jim.c - ** THIS INCLUDES A PREVIOUS PATCH I SENT EARLIER ** - that impliments many [format] specifies JIM did not support. - Jim_FormatString() - **MAJOR** work. - Previously only supported "%s" "%d" and "%c" - And what support existed had bugs. - NEW: *MANY* formating parameters are now supported. - TODO: The "precision" specifier is not supported. ** NEW ** This patch. - Jim_StringToWide() test if no conversion occured. - Jim_StringToIndex() test if no conversion occured. - Jim_StringToDouble() test if no conversion occured. ** NEW ** This Patch. Major Work. - Previously output from JIM did not get sent to GDB - Ditto: Output to Telnet session. - Above items are now fixed - By introducing callbacks new function pointers in the "interp" structure. - Helpers that call the callbacks. - New function: Jim_fprintf() - New function: Jim_vfprintf() - New function: Jim_fwrite() - New function: Jim_fread() - New function: Jim_fflush() - New function: Jim_fgets() By default: the output is to STDIO as previous. The "openocd.c" - redirects the output as needed. - Jim_Panic() - Send panic to both STDERR and the interps specified STDERR output as a 2nd choice. - Now JIM's "stdin/stdout/stderr" paramters are "void *" and are no longer "FILE *". src/Jim.h - **MAJOR** - New JIM STDIO callbacks in the "interp" structure. - change: "stdin/stdout/stderr" are now "void *" cookies. - New JIM stdio helper functions. git-svn-id: svn://svn.berlios.de/openocd/trunk@755 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/tcl/README_ABOUT_TCL.txt | 430 +++++++++++++++++++++++++++++++ src/tcl/bitsbytes.tcl | 63 +++++ src/tcl/chip/atmel/at91/aic.tcl | 101 ++++++++ src/tcl/chip/atmel/at91/at91sam7x128.tcl | 128 +++++++++ src/tcl/chip/atmel/at91/at91sam7x256.tcl | 126 +++++++++ src/tcl/chip/atmel/at91/pmc.tcl | 17 ++ src/tcl/chip/atmel/at91/rtt.tcl | 54 ++++ src/tcl/chip/atmel/at91/usarts.tcl | 135 ++++++++++ src/tcl/cpu/arm/arm7tdmi.tcl | 6 + src/tcl/cpu/arm/arm920.tcl | 6 + src/tcl/cpu/arm/arm946.tcl | 6 + src/tcl/cpu/arm/arm966.tcl | 6 + src/tcl/memory.tcl | 108 ++++++++ src/tcl/mmr_helpers.tcl | 59 +++++ src/tcl/readable.tcl | 25 ++ 15 files changed, 1270 insertions(+) create mode 100644 src/tcl/README_ABOUT_TCL.txt create mode 100644 src/tcl/bitsbytes.tcl create mode 100644 src/tcl/chip/atmel/at91/aic.tcl create mode 100644 src/tcl/chip/atmel/at91/at91sam7x128.tcl create mode 100644 src/tcl/chip/atmel/at91/at91sam7x256.tcl create mode 100644 src/tcl/chip/atmel/at91/pmc.tcl create mode 100644 src/tcl/chip/atmel/at91/rtt.tcl create mode 100644 src/tcl/chip/atmel/at91/usarts.tcl create mode 100644 src/tcl/cpu/arm/arm7tdmi.tcl create mode 100644 src/tcl/cpu/arm/arm920.tcl create mode 100644 src/tcl/cpu/arm/arm946.tcl create mode 100644 src/tcl/cpu/arm/arm966.tcl create mode 100644 src/tcl/memory.tcl create mode 100644 src/tcl/mmr_helpers.tcl create mode 100644 src/tcl/readable.tcl (limited to 'src/tcl') diff --git a/src/tcl/README_ABOUT_TCL.txt b/src/tcl/README_ABOUT_TCL.txt new file mode 100644 index 00000000..47131fef --- /dev/null +++ b/src/tcl/README_ABOUT_TCL.txt @@ -0,0 +1,430 @@ +**************************************** +**************************************** + +This is a short introduction to 'un-scare' you about the language +known as TCL. It is structured as a guided tour through the files +written by me [Duane Ellis] - in early July 2008 for OpenOCD. + +Which uses the "JIM" embedded Tcl clone-ish language. + +Thing described here are *totally* TCL generic... not Jim specific. + +The goal of this document is to encourage you to add your own set of +chips to the TCL package - and most importantly you should know where +you should put them - so they end up in an orginized way. + +--Duane Ellis. + duane@duaneellis.com + +**************************************** +**************************************** + +Adding "chip" support - Duane Ellis July 5 - 2008. + +The concept is this: + In your "openocd.cfg" file add something like this: + + source [find tcl/chip/VENDOR/FAMILY/NAME.tcl] + + For example... + source [find tcl/chip/atmel/at91/at91sam7x256.tcl] + + You'll notice that it makes use of: + + tcl/cpu/arm/.tcl. + + Yes, that is where you should put "core" specific things. + Be carefull and learn the difference: + + THE "CORE" - is not the entire chip! + +Definition: + That "file" listed above is called a "CHIP FILE". + + It may be standalone, or may need to "source" other "helper" files. + + The reference [7/5/2008] is the at91sam7x256.tcl file. + +**************************************** +**************************************** +=== TCL TOUR === +Open: at91sam7x256.tcl +=== TCL TOUR === + +A walk through --- For those who are new to TCL. + +Examine the file: at91sam7x256.tcl + +It starts with: + source [find path/filename.tcl] + +In TCL - this is very important. + + Rule #1 Everything is a string. + Rule #2 If you think other wise See #1. +Reminds you of: + Rule #1: The wife is correct. + Rule #2: If you think otherwise, See #1 + +Any text contained inside of [square-brackets] +is just like `back-ticks` in BASH. + +Hence, the [find FILENAME] executes the command find with a single +parameter the filename. + +======================================== + +Next you see a series of: + +set NAME VALUE + +It is mostly "obious" what is going on. + +Execption: The arrays. + + You would *THINK* Tcl supports arrays. + In fact, multi-dim arrays. That is false. + + For the index for"FLASH(0,CHIPSELECT)" is actually the string + "0,CHIPSELECT". This is problematic. In the normal world, you think + of array indexes as integers. + + For example these are different: + + set foo(0x0c) 123 + set foo(12) 444 + + Why? Because 0x0c {lowercase} is a string. + Don't forget UPPER CASE. + + You must be careful - always... always... use simple decimal + numbers. When in doubt use 'expr' the evaluator. These are all the + same. + + set x 0x0c + set foo([expr $x]) "twelve" + + set x 12 + set foo([expr $x]) "twelve" + + set x "2 * 6" + set foo([expr $x]) "twelve" + +************************************************** +*************************************************** +=== TCL TOUR === +Open the file: "bitsbytes.tcl" + +There is some tricky things going on. +=============== + +First, there is a "for" loop - at level 0 +{level 0 means: out side of a proc/function} + +This means it is evaluated when the file is parsed. + +== SIDEBAR: About The FOR command == +In TCL, "FOR" is a funny thing, it is not what you think it is. + +Syntatically - FOR is a just a command, it is not language +construct like for(;;) in C... + +The "for" command takes 4 parameters. + (1) The "initial command" to execute. + (2) the test "expression" + (3) the "next command" + (4) the "body command" of the FOR loop. + +Notice I used the words "command" and "expresion" above. + +The FOR command: +1) executes the "initial command" +2) evaluates the expression if 0 it stops. +3) executes the "body command" +4) executes the "next command" +5) Goto Step 2. + +As show, each of these items are in {curly-braces}. This means they +are passed as they are - KEY-POINT: un evaluated to the FOR +command. Think of it like escaping the backticks in Bash so that the +"under-lying" command can evaluate the contents. In this case, the FOR +COMMAND. + +== END: SIDEBAR: About The FOR command == + +You'll see two lines: + +LINE1: + set vn [format "BIT%d" $x] + +Format is like "sprintf". Because of the [brackets], it becomes what +you think. But here's how: + +First - the line is parsed - for {braces}. In this case, there are +none. The, the parser looks for [brackets] and finds them. The, +parser then evaluates the contents of the [brackets], and replaces +them. It is alot this bash statement. + + EXPORT vn=`date` + +LINE 2 & 3 + set $vn [expr (1024 * $x)] + global $vn + +In line 1, we dynamically created a variable name. Here, we are +assigning it a value. Lastly Line 3 we force the variable to be +global, not "local" the the "for command body" + +=============== +The PROCS + +proc create_mask { MSB LSB } { + ... body .... +} + +Like "for" - PROC is really just a command that takes 3 parameters. +The (1) NAME of the function, a (2) LIST of parameters, and a (3) BODY + +Again, this is at "level 0" so it is a global function. (Yes, TCL +supports local functions, you put them inside of a function} + +You'll see in some cases, I nest [brackets] alot and in others I'm +lazy or wanted it to be more clear... it is a matter of choice. +=============== + + +************************************************** +*************************************************** +=== TCL TOUR === +Open the file: "memory.tcl" +=============== + +Here is where I setup some 'memory definitions' that various targets can use. + +For example - there is an "unknown" memory region. + +All memory regions must have 2 things: + + (1) N_ + (2) NAME( array ) + And the array must have some specific names: + ( , THING ) + Where: THING is one of: + CHIPSELECT + BASE + LEN + HUMAN + TYPE + RWX - the access ablity. + WIDTH - the accessable width. + + ie: Some regions of memory are not 'word' + accessable. + +The function "address_info" - given an address should +tell you about the address. + + [as of this writing: 7/5/2008 I have done + only a little bit with this -Duane] + +=== +MAJOR FUNCTION: +== + +proc memread32 { ADDR } +proc memread16 { ADDR } +proc memread8 { ADDR } + +All read memory - and return the contents. + +[ fixme: 7/5/2008 - I need to create "memwrite" functions] + +************************************************** +*************************************************** +=== TCL TOUR === +Open the file: "mmr_helpers.tcl" +=============== + +This file is used to display and work with "memory mapped registers" + +For example - 'show_mmr32_reg' is given the NAME of the register to +display. The assumption is - the NAME is a global variable holding the +address of that MMR. + +The code does some tricks. The [set [set NAME]] is the TCL way +of doing double variable interpolation - like makefiles... + +In a makefile or shell script you may have seen this: + + FOO_linux = "Penguins rule" + FOO_winXP = "Broken Glass" + FOO_mac = "I like cat names" + + # Pick one + BUILD = linux + #BUILD = winXP + #BUILD = mac + FOO = ${FOO_${BUILD}} + +The "double [set] square bracket" thing is the TCL way, nothing more. + +---- + +The IF statement - and "CATCH" . + +Notice this IF COMMAND - (not statement) is like this: +[7/5/2008 it is this way] + + if ![catch { command } msg ] { + ...something... + } else { + error [format string...] + } + +The "IF" command expects either 2 params, or 4 params. + + === Sidebar: About "commands" === + + Take a look at the internals of "jim.c" + Look for the function: Jim_IfCoreCommand() + And all those other "CoreCommands" + + You'll notice - they all have "argc" and "argv" + + Yea, the entire thing is done that way. + + IF is a command. SO is "FOR" and "WHILE" and "DO" and the + others. That is why I keep using the prhase it is a "command" + + === END: Sidebar: About "commands" === + +Paramter 1 to the IF command is expected to be an expression. + +As such, I do not need to wrap it in {braces}. + +In this case, the "expression" is the resul of the "CATCH" command. + +CATCH - is an error catcher. + +You give CATCH 1 or 2 parameters. + The first 1st parameter is the "code to execute" + The 2nd (optional) is where to put the error message. + + CATCH returns 0 on success, 1 for failure. + The "![catch command]" is self explaintory. + + +The 3rd parameter to IF must be exacty "else" or "elseif" [I lied +above, the IF command can take many parameters they just have to +be joined by exactly the words "else" or "elseif". + +The 4th parameter contains: + + "error [format STRING....]" + +This lets me modify the previous lower level error by tacking more +text onto the end of it. In this case, i want to add the MMR register +name to make my error message look better. + +--------- +Back to something inside show_mmr32_reg{}. + +You'll see something 'set fn show_${NAME}_helper' Here I am +constructing a 'function name' Then - I look it up to see if it +exists. {the function: "proc_exists" does this} + +And - if it does - I call the function. + +In "C" it is alot like using: 'sprintf()' to construct a function name +string, then using "dlopen()" and "dlsym()" to look it up - and get a +function pointer - and calling the function pointer. + +In this case - I execute a dynamic command. You can do some cool +tricks with interpretors. + +---------- + +Function: show_mmr32_bits() + +In this case, we use the special TCL command "upvar" which tcl's way +of passing things by reference. In this case, we want to reach up into +the callers lexical scope and find the array named "NAMES" + +The rest of the function is pretty straight forward. + +First - we figure out the longest name. +Then print 4 rows of 8bits - with names. + + +************************************************** +*************************************************** +=== TCL TOUR === +Open the file: "chips/atmel/at91/usarts.tcl" +=============== + +First - about the AT91SAM series - all of the usarts +are basically identical... + +Second - there can be many of them. + +In this case - I do some more TCL tricks to dynamically +create functions out of thin air. + +Some assumptions: + +The "CHIP" file has defined some variables in a proper form. + +ie: AT91C_BASE_US0 - for usart0, + AT91C_BASE_US1 - for usart1 + ... And so on ... + +Near the end of the file - look for a large "foreach" loop that +looks like this: + + foreach WHO { US0 US1 US2 US3 US4 .... } { + + } + +In this case, I'm trying to figure out what USARTs exist. + +Step 1 - is to determine if the NAME has been defined. +ie: Does AT91C_BASE_USx - where X is some number exist? + +The "info exists VARNAME" tells you if the variable exists. Then - +inside the IF statement... There is another loop. This loop is the +name of various "sub-registers" within the USART. + +Some more trick are played with the [set VAR] backtick evaluation stuff. +And we create two variables + +We calculate and create the global variable name for every subregister in the USART. +And - declare that variable as GLOBAL so the world can find it. + +Then - we dynamically create a function - based on the register name. + +Look carefully at how that is done. You'll notice the FUNCTION BODY is +a string - not something in {braces}. Why? This is because we need TCL +to evaluate the contents of that string "*NOW*" - when $vn exists not +later, when the function "show_FOO" is invoked. + +Lastly - we build a "str" of commands - and create a single function - +with the generated list of commands for the entire USART. + +With that little bit of code - I now have a bunch of functions like: + + show_US0, show_US1, show_US2, .... etc ... + + And show_US0_MR, show_US0_IMR ... etc... + +And - I have this for every USART... without having to create tons of +boiler plate yucky code. + +**************************************** +**************************************** +END of the Tcl Intro and Walk Through +**************************************** +**************************************** + +FUTURE PLANS + + Some "GPIO" functions... diff --git a/src/tcl/bitsbytes.tcl b/src/tcl/bitsbytes.tcl new file mode 100644 index 00000000..b1771b4b --- /dev/null +++ b/src/tcl/bitsbytes.tcl @@ -0,0 +1,63 @@ +#---------------------------------------- +# Purpose - Create some $BIT variables +# Create $K and $M variables +# and some bit field extraction variables. +# Creat helper variables ... +# BIT0.. BIT31 + +for { set x 0 } { $x < 32 } { set x [expr $x + 1]} { + set vn [format "BIT%d" $x] + set $vn [expr (1 << $x)] + global $vn + +} + +# Create K bytes values +# __1K ... to __2048K +for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { + set vn [format "__%dK" $x] + set $vn [expr (1024 * $x)] + global $vn +} + +# Create M bytes values +# __1M ... to __2048K +for { set x 1 } { $x < 2048 } { set x [expr $x * 2]} { + set vn [format "__%dM" $x] + set $vn [expr (1024 * 1024 * $x)] + global $vn +} + +proc create_mask { MSB LSB } { + return [expr (((1 << ($MSB - $LSB + 1))-1) << $LSB)] + +} + +# Cut Bits $MSB to $LSB out of this value. +# Example: % format "0x%08x" [extract_bitfield 0x12345678 27 16] +# Result: 0x02340000 + +proc extract_bitfield { VALUE MSB LSB } { + return [expr [create_mask $MSB $LSB] & $VALUE] +} + + +# Cut bits $MSB to $LSB out of this value +# and shift (normalize) them down to bit 0. +# +# Example: % format "0x%08x" [normalize_bitfield 0x12345678 27 16] +# Result: 0x00000234 +# +proc normalize_bitfield { VALUE MSB LSB } { + return [expr [extract_bitfield $VALUE $MSB $LSB ] >> $LSB] +} + +proc show_normalize_bitfield { VALUE MSB LSB } { + set m [create_mask $MSB $LSB] + set mr [expr $VALUE & $m] + set sr [expr $mr >> $LSB] + puts [format "((0x%08x & 0x%08x) -> 0x%08x) >> %2d => (0x%x) %5d " $VALUE $m $mr $LSB $sr $sr] + return $sr +} + + diff --git a/src/tcl/chip/atmel/at91/aic.tcl b/src/tcl/chip/atmel/at91/aic.tcl new file mode 100644 index 00000000..245224a5 --- /dev/null +++ b/src/tcl/chip/atmel/at91/aic.tcl @@ -0,0 +1,101 @@ +set AIC_SMR [expr $AT91C_BASE_AIC + 0x00000000 ] +global AIC_SMR +set AIC_SVR [expr $AT91C_BASE_AIC + 0x00000080 ] +global AIC_SVR +set AIC_IVR [expr $AT91C_BASE_AIC + 0x00000100 ] +global AIC_IVR +set AIC_FVR [expr $AT91C_BASE_AIC + 0x00000104 ] +global AIC_FVR +set AIC_ISR [expr $AT91C_BASE_AIC + 0x00000108 ] +global AIC_ISR +set AIC_IPR [expr $AT91C_BASE_AIC + 0x0000010C ] +global AIC_IPR +set AIC_IMR [expr $AT91C_BASE_AIC + 0x00000110 ] +global AIC_IMR +set AIC_CISR [expr $AT91C_BASE_AIC + 0x00000114 ] +global AIC_CISR +set AIC_IECR [expr $AT91C_BASE_AIC + 0x00000120 ] +global AIC_IECR +set AIC_IDCR [expr $AT91C_BASE_AIC + 0x00000124 ] +global AIC_IDCR +set AIC_ICCR [expr $AT91C_BASE_AIC + 0x00000128 ] +global AIC_ICCR +set AIC_ISCR [expr $AT91C_BASE_AIC + 0x0000012C ] +global AIC_ISCR +set AIC_EOICR [expr $AT91C_BASE_AIC + 0x00000130 ] +global AIC_EOICR +set AIC_SPU [expr $AT91C_BASE_AIC + 0x00000134 ] +global AIC_SPU +set AIC_DCR [expr $AT91C_BASE_AIC + 0x00000138 ] +global AIC_DCR +set AIC_FFER [expr $AT91C_BASE_AIC + 0x00000140 ] +global AIC_FFER +set AIC_FFDR [expr $AT91C_BASE_AIC + 0x00000144 ] +global AIC_FFDR +set AIC_FFSR [expr $AT91C_BASE_AIC + 0x00000148 ] +global AIC_FFSR + + +proc aic_enable_disable_list { VAL ENAME DNAME } { + global AT91C_ID + + show_mmr32_bits AT91C_ID $VAL + +} + +proc show_AIC_IPR_helper { NAME ADDR VAL } { + aic_enable_disable_list $VAL "IRQ PENDING" "irq not-pending" +} + +proc show_AIC_IMR_helper { NAME ADDR VAL } { + aic_enable_disable_list $VAL "IRQ ENABLED" "irq disabled" +} + + +proc show_AIC { } { + global AIC_SMR + if [catch { mem2array aaa 32 $AIC_SMR [expr 32 * 4] } msg ] { + error [format "%s (%s)" $msg AIC_SMR] + } + puts "AIC_SMR: Mode & Type" + global AT91C_ID + for { set x 0 } { $x < 32 } { } { + puts -nonewline " " + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] + incr x + } + global AIC_SVR + if [catch { mem2array aaa 32 $AIC_SVR [expr 32 * 4] } msg ] { + error [format "%s (%s)" $msg AIC_SVR] + } + puts "AIC_SVR: Vectors" + for { set x 0 } { $x < 32 } { } { + puts -nonewline " " + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts -nonewline [format "%2d: %5s 0x%08x | " $x $AT91C_ID($x) $aaa($x)] + incr x + puts [format "%2d: %5s 0x%08x" $x $AT91C_ID($x) $aaa($x)] + incr x + } + + foreach REG { + AIC_IVR AIC_FVR AIC_ISR + AIC_IPR AIC_IMR AIC_CISR AIC_IECR AIC_IDCR + AIC_ICCR AIC_ISCR AIC_EOICR AIC_SPU AIC_DCR + AIC_FFER AIC_FFDR AIC_FFSR } { + if [catch { show_mmr32_reg $REG } msg ] { + error $msg + break + } + } +} + diff --git a/src/tcl/chip/atmel/at91/at91sam7x128.tcl b/src/tcl/chip/atmel/at91/at91sam7x128.tcl new file mode 100644 index 00000000..1cf7c1cf --- /dev/null +++ b/src/tcl/chip/atmel/at91/at91sam7x128.tcl @@ -0,0 +1,128 @@ +source [find tcl/bitsbytes.tcl] +source [find tcl/cpu/arm/arm7tdmi.tcl] +source [find tcl/memory.tcl] +source [find tcl/mmr_helpers.tcl] + +set CHIP_MAKER atmel +set CHIP_FAMILY at91sam7 +set CHIP_NAME at91sam7x128 +# how many flash regions. +set N_FLASH 1 +set FLASH(0,CHIPSELECT) -1 +set FLASH(0,BASE) 0x00100000 +set FLASH(0,LEN) $__128K +set FLASH(0,HUMAN) "internal flash" +set FLASH(0,TYPE) "flash" +set FLASH(0,RWX) $RWX_R_X +set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY +# how many ram regions. +set N_RAM 1 +set RAM(0,CHIPSELECT) -1 +set RAM(0,BASE) 0x00200000 +set RAM(0,LEN) $__32K +set RAM(0,HUMAN) "internal ram" +set RAM(0,TYPE) "ram" +set RAM(0,RWX) $RWX_RWX +set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY + +# I AM LAZY... I create 1 region for all MMRs. +set N_MMREGS 1 +set MMREGS(0,CHIPSELECT) -1 +set MMREGS(0,BASE) 0xfff00000 +set MMREGS(0,LEN) 0x000fffff +set MMREGS(0,HUMAN) "mm-regs" +set MMREGS(0,TYPE) "mmr" +set MMREGS(0,RWX) $RWX_RW +set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY + +# no external memory +set N_XMEM 0 + + + + +set AT91C_BASE_SYS 0xFFFFF000 +set AT91C_BASE_AIC 0xFFFFF000 +set AT91C_BASE_PDC_DBGU 0xFFFFF300 +set AT91C_BASE_DBGU 0xFFFFF200 +set AT91C_BASE_PIOA 0xFFFFF400 +set AT91C_BASE_PIOB 0xFFFFF600 +set AT91C_BASE_CKGR 0xFFFFFC20 +set AT91C_BASE_PMC 0xFFFFFC00 +set AT91C_BASE_RSTC 0xFFFFFD00 +set AT91C_BASE_RTTC 0xFFFFFD20 +set AT91C_BASE_PITC 0xFFFFFD30 +set AT91C_BASE_WDTC 0xFFFFFD40 +set AT91C_BASE_VREG 0xFFFFFD60 +set AT91C_BASE_MC 0xFFFFFF00 +set AT91C_BASE_PDC_SPI1 0xFFFE4100 +set AT91C_BASE_SPI1 0xFFFE4000 +set AT91C_BASE_PDC_SPI0 0xFFFE0100 +set AT91C_BASE_SPI0 0xFFFE0000 +set AT91C_BASE_PDC_US1 0xFFFC4100 +set AT91C_BASE_US1 0xFFFC4000 +set AT91C_BASE_PDC_US0 0xFFFC0100 +set AT91C_BASE_US0 0xFFFC0000 +set AT91C_BASE_PDC_SSC 0xFFFD4100 +set AT91C_BASE_SSC 0xFFFD4000 +set AT91C_BASE_TWI 0xFFFB8000 +set AT91C_BASE_PWMC_CH3 0xFFFCC260 +set AT91C_BASE_PWMC_CH2 0xFFFCC240 +set AT91C_BASE_PWMC_CH1 0xFFFCC220 +set AT91C_BASE_PWMC_CH0 0xFFFCC200 +set AT91C_BASE_PWMC 0xFFFCC000 +set AT91C_BASE_UDP 0xFFFB0000 +set AT91C_BASE_TC0 0xFFFA0000 +set AT91C_BASE_TC1 0xFFFA0040 +set AT91C_BASE_TC2 0xFFFA0080 +set AT91C_BASE_TCB 0xFFFA0000 +set AT91C_BASE_CAN_MB0 0xFFFD0200 +set AT91C_BASE_CAN_MB1 0xFFFD0220 +set AT91C_BASE_CAN_MB2 0xFFFD0240 +set AT91C_BASE_CAN_MB3 0xFFFD0260 +set AT91C_BASE_CAN_MB4 0xFFFD0280 +set AT91C_BASE_CAN_MB5 0xFFFD02A0 +set AT91C_BASE_CAN_MB6 0xFFFD02C0 +set AT91C_BASE_CAN_MB7 0xFFFD02E0 +set AT91C_BASE_CAN 0xFFFD0000 +set AT91C_BASE_EMAC 0xFFFDC000 +set AT91C_BASE_PDC_ADC 0xFFFD8100 +set AT91C_BASE_ADC 0xFFFD8000 + +set AT91C_ID(0) FIQ +set AT91C_ID(1) SYS +set AT91C_ID(2) PIOA +set AT91C_ID(3) PIOB +set AT91C_ID(4) SPI0 +set AT91C_ID(5) SPI1 +set AT91C_ID(6) US0 +set AT91C_ID(7) US1 +set AT91C_ID(8) SSC +set AT91C_ID(9) TWI +set AT91C_ID(10) PWMC +set AT91C_ID(11) UDP +set AT91C_ID(12) TC0 +set AT91C_ID(13) TC1 +set AT91C_ID(14) TC2 +set AT91C_ID(15) CAN +set AT91C_ID(16) EMAC +set AT91C_ID(17) ADC +set AT91C_ID(18) "" +set AT91C_ID(19) "" +set AT91C_ID(20) "" +set AT91C_ID(21) "" +set AT91C_ID(22) "" +set AT91C_ID(23) "" +set AT91C_ID(24) "" +set AT91C_ID(25) "" +set AT91C_ID(26) "" +set AT91C_ID(27) "" +set AT91C_ID(28) "" +set AT91C_ID(29) "" +set AT91C_ID(30) IRQ0 +set AT91C_ID(31) IRQ1 + +source [find tcl/chip/atmel/at91/aic.tcl] +source [find tcl/chip/atmel/at91/usarts.tcl] +source [find tcl/chip/atmel/at91/pmc.tcl] +source [find tcl/chip/atmel/at91/rtt.tcl] diff --git a/src/tcl/chip/atmel/at91/at91sam7x256.tcl b/src/tcl/chip/atmel/at91/at91sam7x256.tcl new file mode 100644 index 00000000..1cba4859 --- /dev/null +++ b/src/tcl/chip/atmel/at91/at91sam7x256.tcl @@ -0,0 +1,126 @@ +source [find tcl/bitsbytes.tcl] +source [find tcl/cpu/arm/arm7tdmi.tcl] +source [find tcl/memory.tcl] +source [find tcl/mmr_helpers.tcl] + +set CHIP_MAKER atmel +set CHIP_FAMILY at91sam7 +set CHIP_NAME at91sam7x256 +# how many flash regions. +set N_FLASH 1 +set FLASH(0,CHIPSELECT) -1 +set FLASH(0,BASE) 0x00100000 +set FLASH(0,LEN) $__256K +set FLASH(0,HUMAN) "internal flash" +set FLASH(0,TYPE) "flash" +set FLASH(0,RWX) $RWX_R_X +set FLASH(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY +# how many ram regions. +set N_RAM 1 +set RAM(0,CHIPSELECT) -1 +set RAM(0,BASE) 0x00200000 +set RAM(0,LEN) $__64K +set RAM(0,HUMAN) "internal ram" +set RAM(0,TYPE) "ram" +set RAM(0,RWX) $RWX_RWX +set RAM(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY + +# I AM LAZY... I create 1 region for all MMRs. +set N_MMREGS 1 +set MMREGS(0,CHIPSELECT) -1 +set MMREGS(0,BASE) 0xfff00000 +set MMREGS(0,LEN) 0x000fffff +set MMREGS(0,HUMAN) "mm-regs" +set MMREGS(0,TYPE) "mmr" +set MMREGS(0,RWX) $RWX_RW +set MMREGS(0,ACCESS_WIDTH) $ACCESS_WIDTH_ANY + +# no external memory +set N_XMEM 0 + +set AT91C_BASE_SYS 0xFFFFF000 +set AT91C_BASE_AIC 0xFFFFF000 +set AT91C_BASE_PDC_DBGU 0xFFFFF300 +set AT91C_BASE_DBGU 0xFFFFF200 +set AT91C_BASE_PIOA 0xFFFFF400 +set AT91C_BASE_PIOB 0xFFFFF600 +set AT91C_BASE_CKGR 0xFFFFFC20 +set AT91C_BASE_PMC 0xFFFFFC00 +set AT91C_BASE_RSTC 0xFFFFFD00 +set AT91C_BASE_RTTC 0xFFFFFD20 +set AT91C_BASE_PITC 0xFFFFFD30 +set AT91C_BASE_WDTC 0xFFFFFD40 +set AT91C_BASE_VREG 0xFFFFFD60 +set AT91C_BASE_MC 0xFFFFFF00 +set AT91C_BASE_PDC_SPI1 0xFFFE4100 +set AT91C_BASE_SPI1 0xFFFE4000 +set AT91C_BASE_PDC_SPI0 0xFFFE0100 +set AT91C_BASE_SPI0 0xFFFE0000 +set AT91C_BASE_PDC_US1 0xFFFC4100 +set AT91C_BASE_US1 0xFFFC4000 +set AT91C_BASE_PDC_US0 0xFFFC0100 +set AT91C_BASE_US0 0xFFFC0000 +set AT91C_BASE_PDC_SSC 0xFFFD4100 +set AT91C_BASE_SSC 0xFFFD4000 +set AT91C_BASE_TWI 0xFFFB8000 +set AT91C_BASE_PWMC_CH3 0xFFFCC260 +set AT91C_BASE_PWMC_CH2 0xFFFCC240 +set AT91C_BASE_PWMC_CH1 0xFFFCC220 +set AT91C_BASE_PWMC_CH0 0xFFFCC200 +set AT91C_BASE_PWMC 0xFFFCC000 +set AT91C_BASE_UDP 0xFFFB0000 +set AT91C_BASE_TC0 0xFFFA0000 +set AT91C_BASE_TC1 0xFFFA0040 +set AT91C_BASE_TC2 0xFFFA0080 +set AT91C_BASE_TCB 0xFFFA0000 +set AT91C_BASE_CAN_MB0 0xFFFD0200 +set AT91C_BASE_CAN_MB1 0xFFFD0220 +set AT91C_BASE_CAN_MB2 0xFFFD0240 +set AT91C_BASE_CAN_MB3 0xFFFD0260 +set AT91C_BASE_CAN_MB4 0xFFFD0280 +set AT91C_BASE_CAN_MB5 0xFFFD02A0 +set AT91C_BASE_CAN_MB6 0xFFFD02C0 +set AT91C_BASE_CAN_MB7 0xFFFD02E0 +set AT91C_BASE_CAN 0xFFFD0000 +set AT91C_BASE_EMAC 0xFFFDC000 +set AT91C_BASE_PDC_ADC 0xFFFD8100 +set AT91C_BASE_ADC 0xFFFD8000 + +set AT91C_ID(0) "FIQ" +set AT91C_ID(1) "SYS" +set AT91C_ID(2) "PIOA" +set AT91C_ID(3) "PIOB" +set AT91C_ID(4) "SPI0" +set AT91C_ID(5) "SPI1" +set AT91C_ID(6) "US0" +set AT91C_ID(7) "US1" +set AT91C_ID(8) "SSC" +set AT91C_ID(9) "TWI" +set AT91C_ID(10) "PWMC" +set AT91C_ID(11) "UDP" +set AT91C_ID(12) "TC0" +set AT91C_ID(13) "TC1" +set AT91C_ID(14) "TC2" +set AT91C_ID(15) "CAN" +set AT91C_ID(16) "EMAC" +set AT91C_ID(17) "ADC" +set AT91C_ID(18) "" +set AT91C_ID(19) "" +set AT91C_ID(20) "" +set AT91C_ID(21) "" +set AT91C_ID(22) "" +set AT91C_ID(23) "" +set AT91C_ID(24) "" +set AT91C_ID(25) "" +set AT91C_ID(26) "" +set AT91C_ID(27) "" +set AT91C_ID(28) "" +set AT91C_ID(29) "" +set AT91C_ID(30) "IRQ0" +set AT91C_ID(31) "IRQ1" + + +source [find tcl/chip/atmel/at91/aic.tcl] +source [find tcl/chip/atmel/at91/usarts.tcl] +source [find tcl/chip/atmel/at91/pmc.tcl] +source [find tcl/chip/atmel/at91/rtt.tcl] diff --git a/src/tcl/chip/atmel/at91/pmc.tcl b/src/tcl/chip/atmel/at91/pmc.tcl new file mode 100644 index 00000000..584acb80 --- /dev/null +++ b/src/tcl/chip/atmel/at91/pmc.tcl @@ -0,0 +1,17 @@ + +if [info exists AT91C_MAINOSC_FREQ] { + # user set this... let it be. +} { + # 18.432mhz is a common thing... + set AT91C_MAINOSC_FREQ 18432000 +} +global AT91C_MAINOSC_FREQ + +if [info exists AT91C_SLOWOSC_FREQ] { + # user set this... let it be. +} { + # 32khz is the norm + set AT91C_SLOWOSC_FREQ 32768 +} +global AT91C_SLOWOSC_FREQ + diff --git a/src/tcl/chip/atmel/at91/rtt.tcl b/src/tcl/chip/atmel/at91/rtt.tcl new file mode 100644 index 00000000..56abb29e --- /dev/null +++ b/src/tcl/chip/atmel/at91/rtt.tcl @@ -0,0 +1,54 @@ + +set RTTC_RTMR [expr $AT91C_BASE_RTTC + 0x00] +set RTTC_RTAR [expr $AT91C_BASE_RTTC + 0x04] +set RTTC_RTVR [expr $AT91C_BASE_RTTC + 0x08] +set RTTC_RTSR [expr $AT91C_BASE_RTTC + 0x0c] +global RTTC_RTMR +global RTTC_RTAR +global RTTC_RTVR +global RTTC_RTSR + +proc show_RTTC_RTMR_helper { NAME ADDR VAL } { + set rtpres [expr $VAL & 0x0ffff] + global BIT16 BIT17 + if { $rtpres == 0 } { + set rtpres 65536; + } + global AT91C_SLOWOSC_FREQ + set f [expr double($AT91C_SLOWOSC_FREQ) / double($rtpres)] + puts [format "\tPrescale value: 0x%04x (%5d) => %f Hz" $rtpres $rtpres $f] + if { $VAL & $BIT16 } { + puts "\tBit16 -> Alarm IRQ Enabled" + } else { + puts "\tBit16 -> Alarm IRQ Disabled" + } + if { $VAL & $BIT17 } { + puts "\tBit17 -> RTC Inc IRQ Enabled" + } else { + puts "\tBit17 -> RTC Inc IRQ Disabled" + } + # Bit 18 is write only. +} + +proc show_RTTC_RTSR_helper { NAME ADDR VAL } { + global BIT0 BIT1 + if { $VAL & $BIT0 } { + puts "\tBit0 -> ALARM PENDING" + } else { + puts "\tBit0 -> alarm not pending" + } + if { $VAL & $BIT1 } { + puts "\tBit0 -> RTINC PENDING" + } else { + puts "\tBit0 -> rtinc not pending" + } +} + +proc show_RTTC { } { + + show_mmr32_reg RTTC_RTMR + show_mmr32_reg RTTC_RTAR + show_mmr32_reg RTTC_RTVR + show_mmr32_reg RTTC_RTSR +} + diff --git a/src/tcl/chip/atmel/at91/usarts.tcl b/src/tcl/chip/atmel/at91/usarts.tcl new file mode 100644 index 00000000..19f4ed4c --- /dev/null +++ b/src/tcl/chip/atmel/at91/usarts.tcl @@ -0,0 +1,135 @@ +# the DBGU and USARTs are 'almost' indentical' +set DBGU_CR [expr $AT91C_BASE_DBGU + 0x00000000] +set DBGU_MR [expr $AT91C_BASE_DBGU + 0x00000004] +set DBGU_IER [expr $AT91C_BASE_DBGU + 0x00000008] +set DBGU_IDR [expr $AT91C_BASE_DBGU + 0x0000000C] +set DBGU_IMR [expr $AT91C_BASE_DBGU + 0x00000010] +set DBGU_CSR [expr $AT91C_BASE_DBGU + 0x00000014] +set DBGU_RHR [expr $AT91C_BASE_DBGU + 0x00000018] +set DBGU_THR [expr $AT91C_BASE_DBGU + 0x0000001C] +set DBGU_BRGR [expr $AT91C_BASE_DBGU + 0x00000020] +# no RTOR +# no TTGR +# no FIDI +# no NER +set DBGU_CIDR [expr $AT91C_BASE_DBGU + 0x00000040] +set DBGU_EXID [expr $AT91C_BASE_DBGU + 0x00000044] +set DBGU_FNTR [expr $AT91C_BASE_DBGU + 0x00000048] + + +set USx_CR 0x00000000 +set USx_MR 0x00000004 +set USx_IER 0x00000008 +set USx_IDR 0x0000000C +set USx_IMR 0x00000010 +set USx_CSR 0x00000014 +set USx_RHR 0x00000018 +set USx_THR 0x0000001C +set USx_BRGR 0x00000020 +set USx_RTOR 0x00000024 +set USx_TTGR 0x00000028 +set USx_FIDI 0x00000040 +set USx_NER 0x00000044 +set USx_IF 0x0000004C + +# Create all the uarts that exist.. +# we blow up if there are >9 + + +proc show_mmr_USx_MR_helper { NAME ADDR VAL } { + # First - just print it + + set x [show_normalize_bitfield $VAL 3 0] + if { $x == 0 } { + puts "\tNormal operation" + } else { + puts [format "\tNon Normal operation mode: 0x%02x" $x] + } + + set x [show_normalize_bitfield $VAL 11 9] + set s "unknown" + switch -exact $x { + 0 { set s "Even" } + 1 { set s "Odd" } + 2 { set s "Force=0" } + 3 { set s "Force=1" } + * { + set $x [expr $x & 6] + switch -exact $x { + 4 { set s "None" } + 6 { set s "Multidrop Mode" } + } + } + } + puts [format "\tParity: %s " $s] + + set x [expr 5 + [show_normalize_bitfield $VAL 7 6]] + puts [format "\tDatabits: %d" $x] + + set x [show_normalize_bitfield $VAL 13 12] + switch -exact $x { + 0 { puts "\tStop bits: 1" } + 1 { puts "\tStop bits: 1.5" } + 2 { puts "\tStop bits: 2" } + 3 { puts "\tStop bits: Illegal/Reserved" } + } +} + +# For every possbile usart... +foreach WHO { US0 US1 US2 US3 US4 US5 US6 US7 US8 US9 } { + set n AT91C_BASE_[set WHO] + set str "" + + # Only if it exists on the chip + if [ info exists $n ] { + # Hence: $n - is like AT91C_BASE_USx + # For every sub-register + foreach REG {CR MR IER IDR IMR CSR RHR THR BRGR RTOR TTGR FIDI NER IF} { + # vn = variable name + set vn [set WHO]_[set REG] + # vn = USx_IER + # vv = variable value + set vv [expr $$n + [set USx_[set REG]]] + # And VV is the address in memory of that register + + + # make that VN a GLOBAL so others can find it + global $vn + set $vn $vv + + # Create a command for this specific register. + proc show_$vn { } "show_mmr32_reg $vn" + + # Add this command to the Device(as a whole) command + set str "$str\nshow_$vn" + } + # Now - create the DEVICE(as a whole) command + set fn show_$WHO + proc $fn { } $str + } +} + +# The Debug Uart is special.. +set str "" + + +# For every sub-register +foreach REG {DBGU_CR DBGU_MR DBGU_IER DBGU_IDR DBGU_IMR + DBGU_CSR DBGU_RHR DBGU_THR DBGU_BRGR DBGU_CIDR DBGU_EXID DBGU_FNTR} { + + # Create a command for this specific register. + proc show_$REG { } "show_mmr32_reg $REG" + + # Add this command to the Device(as a whole) command + set str "$str\nshow_$REG" +} + +# Now - create the DEVICE(as a whole) command +proc show_DBGU { } $str + +unset str + +proc show_DBGU_MR_helper { NAME ADDR VAL } { show_mmr_USx_MR_helper $NAME $ADDR $VAL } + + + diff --git a/src/tcl/cpu/arm/arm7tdmi.tcl b/src/tcl/cpu/arm/arm7tdmi.tcl new file mode 100644 index 00000000..37db2661 --- /dev/null +++ b/src/tcl/cpu/arm/arm7tdmi.tcl @@ -0,0 +1,6 @@ +set CPU_TYPE arm +set CPU_NAME arm7tdmi +set CPU_ARCH armv4t +set CPU_MAX_ADDRESS 0xFFFFFFFF +set CPU_NBITS 32 + diff --git a/src/tcl/cpu/arm/arm920.tcl b/src/tcl/cpu/arm/arm920.tcl new file mode 100644 index 00000000..f19b20b3 --- /dev/null +++ b/src/tcl/cpu/arm/arm920.tcl @@ -0,0 +1,6 @@ +set CPU_TYPE arm +set CPU_NAME arm920 +set CPU_ARCH armv4t +set CPU_MAX_ADDRESS 0xFFFFFFFF +set CPU_NBITS 32 + diff --git a/src/tcl/cpu/arm/arm946.tcl b/src/tcl/cpu/arm/arm946.tcl new file mode 100644 index 00000000..52041017 --- /dev/null +++ b/src/tcl/cpu/arm/arm946.tcl @@ -0,0 +1,6 @@ +set CPU_TYPE arm +set CPU_NAME arm946 +set CPU_ARCH armv5te +set CPU_MAX_ADDRESS 0xFFFFFFFF +set CPU_NBITS 32 + diff --git a/src/tcl/cpu/arm/arm966.tcl b/src/tcl/cpu/arm/arm966.tcl new file mode 100644 index 00000000..83ce0f67 --- /dev/null +++ b/src/tcl/cpu/arm/arm966.tcl @@ -0,0 +1,6 @@ +set CPU_TYPE arm +set CPU_NAME arm966 +set CPU_ARCH armv5te +set CPU_MAX_ADDRESS 0xFFFFFFFF +set CPU_NBITS 32 + diff --git a/src/tcl/memory.tcl b/src/tcl/memory.tcl new file mode 100644 index 00000000..1f90ef2c --- /dev/null +++ b/src/tcl/memory.tcl @@ -0,0 +1,108 @@ +# MEMORY +# +# All Memory regions have two components. +# (1) A count of regions, in the form N_NAME +# (2) An array within info about each region. +# +# The ARRAY +# +# ( RegionNumber , ATTRIBUTE ) +# +# Where is one of: +# +# N_FLASH & FLASH (internal memory) +# N_RAM & RAM (internal memory) +# N_MMREGS & MMREGS (for memory mapped registers) +# N_XMEM & XMEM (off chip memory, ie: flash on cs0, sdram on cs2) +# or N_UNKNOWN & UNKNOWN for things that do not exist. +# +# We have 1 unknown region. +set N_UNKNOWN 1 +# All MEMORY regions must have these attributes +# CS - chip select (if internal, use -1) +set UNKNOWN(0,CHIPSELECT) -1 +# BASE - base address in memory +set UNKNOWN(0,BASE) 0 +# LEN - length in bytes +set UNKNOWN(0,LEN) $CPU_MAX_ADDRESS +# HUMAN - human name of the region +set UNKNOWN(0,HUMAN) "unknown" +# TYPE - one of: +# flash, ram, mmr, unknown +# For harvard arch: +# iflash, dflash, iram, dram +set UNKNOWN(0,TYPE) "unknown" +# RWX - access ablity +# unix style chmod bits +# 0 - no access +# 1 - execute +# 2 - write +# 4 - read +# hence: 7 - readwrite execute +set RWX_NO_ACCESS 0 +set RWX_X_ONLY $BIT0 +set RWX_W_ONLY $BIT1 +set RWX_R_ONLY $BIT2 +set RWX_RW [expr $RWX_R_ONLY + $RWX_W_ONLY] +set RWX_R_X [expr $RWX_R_ONLY + $RWX_X_ONLY] +set RWX_RWX [expr $RWX_R_ONLY + $RWX_W_ONLY + $RWX_X_ONLY] +set UNKNOWN(0,RWX) $RWX_NO_ACCESS + +# WIDTH - access width +# 8,16,32 [0 means ANY] +set ACCESS_WIDTH_NONE 0 +set ACCESS_WIDTH_8 $BIT0 +set ACCESS_WIDTH_16 $BIT1 +set ACCESS_WIDTH_32 $BIT2 +set ACCESS_WIDTH_ANY [expr $ACCESS_WIDTH_8 + $ACCESS_WIDTH_16 + $ACCESS_WIDTH_32] +set UNKNOWN(0,ACCESS_WIDTH) $ACCESS_WIDTH_NONE + +proc iswithin { ADDRESS BASE LEN } { + return [expr ((($ADDRESS - $BASE) > 0) && (($ADDRESS - $BASE + $LEN) > 0))] +} + +proc address_info { ADDRESS } { + + foreach WHERE { FLASH RAM MMREGS XMEM UNKNOWN } { + if { info exists $WHERE } { + set lmt [set N_[set WHERE]] + for { set region 0 } { $region < $lmt } { incr region } { + if { iswithin $ADDRESS $WHERE($region,BASE) $WHERE($region,LEN) } { + return "$WHERE $region"; + } + } + } + } + + # Return the 'unknown' + return "UNKNOWN 0" +} + +proc memread32 {ADDR } { + set foo(0) 0 + if ![ catch { mem2array foo 32 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memead32: $msg" + } +} + +proc memread16 {ADDR } { + set foo(0) 0 + if ![ catch { mem2array foo 16 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memead16: $msg" + } +} + +proc memread82 {ADDR } { + set foo(0) 0 + if ![ catch { mem2array foo 8 $ADDR 1 } msg ] { + return $foo(0) + } else { + error "memead8: $msg" + } +} + + diff --git a/src/tcl/mmr_helpers.tcl b/src/tcl/mmr_helpers.tcl new file mode 100644 index 00000000..5dac48a8 --- /dev/null +++ b/src/tcl/mmr_helpers.tcl @@ -0,0 +1,59 @@ + +proc proc_exists { NAME } { + set n [info commands $NAME] + set l [string length $n] + return [expr $l != 0] +} + +# Give: REGISTER name - must be a global variable. +proc show_mmr32_reg { NAME } { + + global $NAME + # we want $($NAME) + set a [set [set NAME]] + + if ![catch { set v [memread32 $a] } msg ] { + puts [format "%10s: (0x%08x): 0x%08x" $NAME $a $v] + + # Was a helper defined? + set fn show_${NAME}_helper + if [ proc_exists $fn ] { + # Then call it + $fn $NAME $a $v + } + return $v; + } else { + error [format "%s (%s)" $msg $NAME ] + } +} + + +# Give: NAMES - an array of names accessable +# in the callers symbol-scope. +# VAL - the bits to display. + +proc show_mmr32_bits { NAMES VAL } { + + upvar $NAMES MYNAMES + + set w 0 + foreach {IDX N} $MYNAMES { + set l [string length $N] + if { $l > $w } { set w $l } + } + + for { set x 24 } { $x >= 0 } { incr x -8 } { + puts -nonewline " " + for { set y 7 } { $y >= 0 } { incr y -1 } { + set s $MYNAMES([expr $x + $y]) + puts -nonewline [format "%2d: %-*s | " [expr $x + $y] $w $s ] + } + puts "" + + puts -nonewline " " + for { set y 7 } { $y >= 0 } { incr y -1 } { + puts -nonewline [format " %d%*s | " [expr !!($VAL & (1 << ($x + $y)))] [expr $w -1] ""] + } + puts "" + } +} diff --git a/src/tcl/readable.tcl b/src/tcl/readable.tcl new file mode 100644 index 00000000..39f43caa --- /dev/null +++ b/src/tcl/readable.tcl @@ -0,0 +1,25 @@ +proc iswithin { ADDRESS BASE LEN } { + return [expr ((($ADDRESS - $BASE) > 0) && (($ADDRESS - $BASE + $LEN) > 0))] +} + +proc memorytype { ADDRESS } { + for { set chip 0 } { $chip < $N_CHIP } { incr chip } { + if { iswithin $ADDRESS $FLASH($chip,BASE) $FLASH($chip,LEN) } { + return "flash" + } + } + + for { set chip 0 } { $chip < $N_RAM } { incr chip } { + if { iswithin $ADDRESS $RAM($chip,BASE) $RAM($chip,LEN) } { + return "ram" + } + } +} + +# default to 32bit reads. +proc isreadable { ADDRESS } { + return isreadable32 $ADDRESS +} + +proc isreadable32 { ADDRESS } { + \ No newline at end of file -- cgit v1.2.3