我正在尝试更改 sam-ba (sam bootloader assistant) 正在使用的链接器脚本。班轮脚本由 Atmel Corporation(tcl_lib 和 applet)为 samd21j18a 编写。根据数据表,samd21e16b Sram 为 8 kB,闪存为 64 kB。根据文档,我需要更改
- appletAddr 和 appletMailboxAddr 相应地在 tcl_lib 中,基于选择的设备和 SAM-BA 引导加载程序占用的 SRAM。
- 为 SAMD21E16B 和最新的 ASF 定制 ASF SAM-BA Applet 链接器脚本。我需要更新基于所选设备的部分,以及 SAM-BA 引导加载程序占用的 SRAM 大小。
您是否有任何资源有助于理解用于定制芯片 (samd21e16b) 的链接器脚本中的这些信息?
什么是 appletAddr 和 appletMailboxAddr?
他们如何写 sram 大小:
sram (W!RX) : ORIGIN = 0x20002000, LENGTH = 0x00002000 /* sram, 4K - sizeof(romcodesram) */
tcl_lib:
set cidr_addr 0x41002018
# *****************************************************************************
# CHIP NAME CHIPID_CIDR
# *****************************************************************************
array set devicesList { samd21j18a 0x10010000
samd21j17a 0x10010001
samd21j16a 0x10010002
samd21j15a 0x10010003
samd21g18a 0x10010005
samd21g17a 0x10010006
samd21g16a 0x10010007
samd21g15a 0x10010008
samd21e18a 0x1001000A
samd21e17a 0x1001000B
samd21e16a 0x1001000C
samd21e15a 0x1001000D
}
global target
global commandLineMode
set isValidChipOfBoard 0
set version_mask 0xFFBF00FF
set chipname_list [array names ::devicesList]
set chip_id [format "0x%08x" [TCL_Read_Int $target(handle) $cidr_addr err_code]]
puts "Read device Chip ID at $cidr_addr --- get $chip_id"
set proc_id_masked [format "0x%08x" [expr $chip_id & $version_mask]]
foreach {key value} [array get devicesList] {
set masked_chipId_Cidr [format "0x%08x" [expr $value & $version_mask]]
if {[regexp $proc_id_masked $masked_chipId_Cidr] != 0} {
puts "-I- Found chip : $key (Chip ID : $chip_id)"
set isValidChipOfBoard 1
break
}
}
if { $isValidChipOfBoard == 0 } {
if { $commandLineMode == 1 } {
puts "-E- Invalid device or board!"
} else {
tk_messageBox -title "Invalid chip ID" -message "Can't connect $target(board)\n" -icon error -type ok
}
TCL_Close $target(handle)
exit
}
namespace eval BOARD {
variable sramSize 0x00008000
variable maxBootSize 0
# Vdd Memory 1.8V = 0 / Vdd Memory 3.3V = 1
variable extRamVdd 1
# External SDRAM = 0 / External DDR = 1 External PSRAM = 2 (not used)
variable extRamType 0
# Set bus width (16 or 32)
variable extRamDataBusWidth 16
# DDRAM Model (not used)
variable extDDRamModel 0
}
# Standard applet commands + some SAMD21 specific commands
array set appletCmdSamd21 {
init 0x00
fullErase 0x01
write 0x02
read 0x03
lock 0x04
unlock 0x05
gpnvm 0x06
security 0x07
erasebuffer 0x08
binarypage 0x09
otpRead 0x0a
otpWrite 0x0b
listbadblocks 0x10
tagBlock 0x11
readUniqueID 0x12
eraseBlocks 0x13
batchErase 0x14
pmeccParam 0x15
pmeccBoot 0x16
switchEccMode 0x17
trimffsMode 0x18
eraseRow 0x40
readDeviceID 0x41
readLocks 0x42
readFuses 0x43
eraseApp 0x44
}
set target(board) "samd21_xplained_pro"
################################################################################
## PROCEDURES FOR COMPATIBILITY WITH OLDER SAM-BA VERSIONS AND USER DEFINED
################################################################################
if { [ catch { source "$libPath(extLib)/common/functions.tcl"} errMsg] } {
if {$commandLineMode == 0} {
tk_messageBox -title "File not found" -message "Function file not found:\n$errMsg" -type ok -icon error
} else {
puts "-E- Function file not found:\n$errMsg"
puts "-E- Connection abort"
}
exit
}
array set memoryAlgo {
"SRAM" "::atsamd21_sram"
"Flash" "::atsamd21_flash"
"Peripheral" "::atsamd21_peripheral"
}
################################################################################
## Low Level Initialization
################################################################################
################################################################################
## SRAM : 32k
################################################################################
array set atsamd21_sram {
dftDisplay 0
dftDefault 0
dftAddress 0x20000000
dftSize 0x8000
dftSend "RAM::sendFile"
dftReceive "RAM::receiveFile"
dftScripts ""
}
################################################################################
## FLASH : 256k
################################################################################
array set atsamd21_flash {
dftDisplay 1
dftDefault 1
dftAddress 0x00000
dftSize 0x40000
dftSend "FLASH::SendFileNoLock"
dftReceive "FLASH::ReceiveFile"
dftScripts "::atsamd21_flash_scripts"
}
array set atsamd21_flash_scripts {
"Read Device ID" "FLASH::ReadDeviceID"
"Read Lock Fuses" "FLASH::ReadLocks"
"Unlock All" "FLASH::UnlockAll"
"Set Lock Bit 00" "FLASH::SetLock 0"
"Set Lock Bit 01" "FLASH::SetLock 1"
"Set Lock Bit 02" "FLASH::SetLock 2"
"Set Lock Bit 03" "FLASH::SetLock 3"
"Set Lock Bit 04" "FLASH::SetLock 4"
"Set Lock Bit 05" "FLASH::SetLock 5"
"Set Lock Bit 06" "FLASH::SetLock 6"
"Set Lock Bit 07" "FLASH::SetLock 7"
"Set Lock Bit 08" "FLASH::SetLock 8"
"Set Lock Bit 09" "FLASH::SetLock 9"
"Set Lock Bit 10" "FLASH::SetLock 10"
"Set Lock Bit 11" "FLASH::SetLock 11"
"Set Lock Bit 12" "FLASH::SetLock 12"
"Set Lock Bit 13" "FLASH::SetLock 13"
"Set Lock Bit 14" "FLASH::SetLock 14"
"Set Lock Bit 15" "FLASH::SetLock 15"
"Invalidate application" "FLASH::EraseRow 32"
"Erase application area" "FLASH::EraseApp"
"Read Fuses" "FLASH::ReadFuses"
"Set Security Bit" "FLASH::SetSecurity"
}
set FLASH::appletAddr 0x20002000
set FLASH::appletMailboxAddr 0x20002040
set FLASH::appletFileName "$libPath(extLib)/$target(board)/applet-flash-samd21j18a.bin"
# Initialize FLASH
if {[catch {FLASH::Init} dummy_err]} {
if {$commandLineMode == 0} {
tk_messageBox -title "FLASH init" -message "Failed to initialize FLASH access" -icon error -type ok
} else {
puts "-E- Error during FLASH initialization"
puts "-E- Connection abort"
}
# Close link
TCL_Close $target(handle)
exit
} else {
#retrieve additionnal parameters from the Init function
set appletAddrArgvps [expr $FLASH::appletMailboxAddr + 0x18]
set appletAddrArgvnp [expr $FLASH::appletMailboxAddr + 0x1c]
set appletAddrArgvasp [expr $FLASH::appletMailboxAddr + 0x20]
set flashPageSize [TCL_Read_Int $target(handle) $appletAddrArgvps]
set flashNbPage [TCL_Read_Int $target(handle) $appletAddrArgvnp]
set flashAppStartPage [TCL_Read_Int $target(handle) $appletAddrArgvasp]
puts "flashPageSize [format "0x%08x" $flashPageSize]"
puts "flashNbPage [format "%d" $flashNbPage]"
puts "flashAppStartPage [format "%d" $flashAppStartPage]"
puts "-I- FLASH initialized"
}
################################################################################
array set atsamd21_peripheral {
dftDisplay 0
dftDefault 0
dftAddress 0x40000000
dftSize 0x10000000
dftSend ""
dftReceive ""
dftScripts ""
}
#===============================================================================
# proc FLASH::ReadDeviceID
#===============================================================================
proc FLASH::ReadDeviceID { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArgv0 [expr $appletMailboxAddr + 0x08]
set appletAddrArgv1 [expr $appletMailboxAddr + 0x0c]
set appletAddrArgv2 [expr $appletMailboxAddr + 0x10]
set appletAddrArgv3 [expr $appletMailboxAddr + 0x14]
# Init the ping pong algorithm: the buffer is active
set bufferAddress $GENERIC::appletBufferAddress
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(readDeviceID) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write the buffer address in the argument area
if {[catch {TCL_Write_Int $target(handle) $bufferAddress $appletAddrArgv0} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(readDeviceID)]} dummy_err]} {
error "Applet readDeviceID command has not been launched ($dummy_err)"
}
puts "buffer address [format "0x%08x" $bufferAddress]"
puts "Device ID :"
set addr [expr $bufferAddress]
# Return the error code returned by the applet
if {[catch {set data [TCL_Read_Int $target(handle) $addr]} dummy_err] } {
error "Error reading the buffer containing Device ID"
}
puts [format "0x%08x" $data]
}
#===============================================================================
# proc FLASH::ReadFuses
#===============================================================================
proc FLASH::ReadFuses { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArgv0 [expr $appletMailboxAddr + 0x08]
set appletAddrArgv1 [expr $appletMailboxAddr + 0x0c]
# Init the ping pong algorithm: the buffer is active
set bufferAddress $GENERIC::appletBufferAddress
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(readFuses) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write the buffer address in the argument area
if {[catch {TCL_Write_Int $target(handle) $bufferAddress $appletAddrArgv0} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(readFuses)]} dummy_err]} {
error "Applet readDeviceID command has not been launched ($dummy_err)"
}
puts "buffer address [format "0x%08x" $bufferAddress]"
puts "Fuses :"
set i 0
set addr [expr $bufferAddress]
while {$i < [expr 2]} {
# Return the error code returned by the applet
if {[catch {set data [TCL_Read_Int $target(handle) $addr]} dummy_err] } {
error "Error reading the buffer containing Device ID"
}
incr addr +4
incr i +1
puts [format "0x%08x" $data]
}
}
#===============================================================================
# proc FLASH::ReadLocks
#===============================================================================
proc FLASH::ReadLocks { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArgv0 [expr $appletMailboxAddr + 0x08]
set appletAddrArgv1 [expr $appletMailboxAddr + 0x0c]
set appletAddrArgv2 [expr $appletMailboxAddr + 0x10]
set appletAddrArgv3 [expr $appletMailboxAddr + 0x14]
# Init the ping pong algorithm: the buffer is active
set bufferAddress $GENERIC::appletBufferAddress
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(readLocks) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write the buffer address in the argument area
if {[catch {TCL_Write_Int $target(handle) $bufferAddress $appletAddrArgv0} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(readLocks)]} dummy_err]} {
error "Applet readDeviceID command has not been launched ($dummy_err)"
}
puts "buffer address [format "0x%08x" $bufferAddress]"
puts "Lock status :"
set addr [expr $bufferAddress]
# Return the error code returned by the applet
if {[catch {set data [TCL_Read_Short $target(handle) $addr]} dummy_err] } {
error "Error reading the buffer containing Device ID"
}
puts [format "0x%4x" $data]
}
#===============================================================================
# proc FLASH::SetLock
#===============================================================================
proc FLASH::SetLock { lockbit } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArg_value [expr $appletMailboxAddr + 0x08]
if {$lockbit > [expr 16]} {
error "Wrong lock bit number"
}
set writemask [expr 1 << $lockbit ]
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(lock) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write value in the argument area
if {[catch {TCL_Write_Int $target(handle) [expr $lockbit] $appletAddrArg_value} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(lock)]} dummy_err]} {
error "Applet lock command has not been launched ($dummy_err)"
}
puts "Region locked"
}
#===============================================================================
# proc FLASH::UnlockAll
#===============================================================================
proc FLASH::UnlockAll { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArg_value [expr $appletMailboxAddr + 0x08]
set lockbit 0
while { $lockbit < [expr 16]} {
set writemask [expr 1 << $lockbit ]
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(unlock) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write value in the argument area
if {[catch {TCL_Write_Int $target(handle) [expr $lockbit] $appletAddrArg_value} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(unlock)]} dummy_err]} {
error "Applet lock command has not been launched ($dummy_err)"
}
puts "Region ($lockbit) unlocked"
incr lockbit +1
}
}
#===============================================================================
# proc FLASH::SetSecurity
#===============================================================================
proc FLASH::SetSecurity { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArg_param [expr $appletMailboxAddr + 0x08]
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(security) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write the param value in the argument area
if {[catch {TCL_Write_Int $target(handle) 1 $appletAddrArg_param} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
puts "About to launch set security bit procedure ..."
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(security)]} dummy_err]} {
error "Applet security command has not been launched ($dummy_err)"
} else {
puts "Part is secured"
}
}
#===============================================================================
# proc FLASH::SendFileNoLock
#===============================================================================
proc FLASH::SendFileNoLock { name addr } {
variable flashSize
variable flashLockRegionSize
variable flashNumbersLockBits
variable appletBufferAddress
global commandLineMode
if { [catch {set f [open $name r]}] } {
puts "-E- Can't open file $name"
return -1
}
fconfigure $f -translation binary
#First Step check the locked sector
set dummy_err 0
set rewrite 0
set size [file size $name]
set dest [expr $addr & [expr $flashSize - 1]]
set first_page [expr $dest / $::flashPageSize]
puts "File size : $size"
puts "Flash size : $flashSize Flash page size : $::flashPageSize First page : $first_page"
puts "Dest : $dest"
if { $first_page < $::flashAppStartPage } {
if {$commandLineMode == 0} {
set answer [tk_messageBox -title "Attempt to write monitor area"\
-message " Writing to the monitor area is forbidden, write operation aborted "\
-icon error \
-type ok]
}
return -1
}
if {[catch {GENERIC::Write $dest $size $f 0} dummy_err] } {
puts "-E- Generic::Write returned error ($dummy_err)"
close $f
return -1
}
close $f
}
#===============================================================================
# proc FLASH::EraseRow
#===============================================================================
proc FLASH::EraseRow { flashrow } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArg_param [expr $appletMailboxAddr + 0x08]
if {$flashrow > [expr 1024]} {
error "Wrong flash region number"
}
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(eraseRow) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
# Write the param value in the argument area
if {[catch {TCL_Write_Int $target(handle) [expr $flashrow] $appletAddrArg_param} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(eraseRow)]} dummy_err]} {
error "Applet eraseRow command has not been launched ($dummy_err)"
}
puts "Flash memory row erased."
}
#===============================================================================
# proc FLASH::EraseApp
#===============================================================================
proc FLASH::EraseApp { } {
global target
variable appletMailboxAddr
set dummy_err 0
# Mailbox is 32 word long (add variable here if you need read/write more data)
set appletAddrCmd [expr $appletMailboxAddr]
set appletAddrStatus [expr $appletMailboxAddr + 0x04]
set appletAddrArg_start_row [expr $appletMailboxAddr + 0x08]
set appletAddrArg_end_row [expr $appletMailboxAddr + 0x0c]
# Write the Cmd op code in the argument area
if {[catch {TCL_Write_Int $target(handle) $::appletCmdSamd21(eraseApp) $appletAddrCmd} dummy_err] } {
error "Error Writing Applet command ($dummy_err)"
}
set start [expr $::flashAppStartPage/4]
set end [expr $::flashNbPage/4]
# Write the starting row number in the argument area
if {[catch {TCL_Write_Int $target(handle) [expr $start] $appletAddrArg_start_row} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
# Write the ending row number in the argument area
if {[catch {TCL_Write_Int $target(handle) [expr $end] $appletAddrArg_end_row} dummy_err] } {
error "[format "0x%08x" $dummy_err]"
}
puts "Start row: [format "0x%08x" $start]"
puts "End row: [format "0x%08x" $end]"
# Launch the applet Jumping to the appletAddr
if {[catch {set result [GENERIC::Run $::appletCmdSamd21(eraseApp)]} dummy_err]} {
error "Applet eraseApp command has not been launched ($dummy_err)"
}
puts "Application area erased"
}
小程序:
/*------------------------------------------------------------------------------
* Linker script for running in internal SRAM on the SAMD21J18
*----------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
/* Memory Spaces Definitions */
MEMORY
{
romcodesram (W!RX) : ORIGIN = 0x20000000, LENGTH = 0x2000
sram (W!RX) : ORIGIN = 0x20002000, LENGTH = 0x00002000 /* sram, 4K - sizeof(romcodesram) */
}
SECTIONS
{
/* startup code in the .isr_vector */
.text :
{
. = ALIGN(4);
_stext = .;
KEEP(*(.isr_vector .isr_vector.*))
*(.mailbox)
*(.text .text.*)
*(.rodata .rodata.*)
*(.ramfunc .ramfunc.*)
*(.glue_7)
*(.glue_7t)
*(.gcc_except_table)
*(.rodata .rodata*)
*(.gnu.linkonce.r.*)
. = ALIGN(4);
_etext = .;
} > sram
/* data */
.data :
{
. = ALIGN(4);
_sidata = .;
_sdata = .;
*(.data)
*(.data.*)
. = ALIGN(4);
_edata = .;
} > sram
.bss (NOLOAD) : {
_szero = .;
*(.bss)
. = ALIGN(4);
_ezero = .;
} >sram
/* Stack in SRAM */
_sstack = 0x20003FF0;
/DISCARD/ : { *(.note.gnu.*) }
}
. = ALIGN(4);
end = .;