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
This commit is contained in:
oharboe
2008-07-06 19:17:43 +00:00
parent 71460ba9a5
commit dc796a2091
27 changed files with 2004 additions and 157 deletions

View File

@@ -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/<NAME>.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_<name>
(2) NAME( array )
And the array must have some specific names:
( <idx>, 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...

63
src/tcl/bitsbytes.tcl Normal file
View File

@@ -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
}

View File

@@ -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
}
}
}

View File

@@ -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]

View File

@@ -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]

View File

@@ -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

View File

@@ -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
}

View File

@@ -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 }

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

108
src/tcl/memory.tcl Normal file
View File

@@ -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
#
# <NAME>( RegionNumber , ATTRIBUTE )
#
# Where <NAME> 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"
}
}

59
src/tcl/mmr_helpers.tcl Normal file
View File

@@ -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 ""
}
}

25
src/tcl/readable.tcl Normal file
View File

@@ -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 } {