RTL8710 Flasher

https://bitbucket.org/rebane/rtl8710_openocd/

rtl8710_openocd / script / rtl8710.ocd

#
# OpenOCD script for RTL8710
# Copyright (C) 2016 Rebane, rebane@alkohol.ee
#

source [find target/swj-dp.tcl]

if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
} else {
    set _CHIPNAME rtl8710
}

if { [info exists ENDIAN] } {
    set _ENDIAN $ENDIAN
} else {
    set _ENDIAN little
}

if { [info exists WORKAREASIZE] } {
    set _WORKAREASIZE $WORKAREASIZE
} else {
    set _WORKAREASIZE 0x800
}

if { [info exists CPUTAPID] } {
    set _CPUTAPID $CPUTAPID
} else {
    set _CPUTAPID 0x2ba01477
}

swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME

$_TARGETNAME configure -work-area-phys 0x10001000 -work-area-size $_WORKAREASIZE -work-area-backup 0

adapter_khz 500
adapter_nsrst_delay 100

if {![using_hla]} {
    cortex_m reset_config sysresetreq
}

set rtl8710_flasher_firmware_ptr 0x10001000
set rtl8710_flasher_buffer 0x10008000
set rtl8710_flasher_buffer_size 262144
set rtl8710_flasher_sector_size 4096

array set rtl8710_flasher_code {
    0 0xB671B57F 1 0x25FF4B58 2 0x6B196B1A 3 0x7040F042 4 0x69D96318 5 0xF4414E55
    6 0x69D97480 7 0xF8D361DC 8 0xF8C32120 9 0xF8D35120 10 0xF8C31124 11 0x47B05124
    12 0x47B04E4F 13 0x47984B4F 14 0x60104A4F 15 0x484F47B0 16 0x60012100 17 0x2C006804
    18 0x4D4DD0FC 19 0xB93E682E 20 0x60264C49 21 0x47B04E46 22 0x47984B46 23 0xE7ED6020
    24 0x2B01682B 25 0x4E42D109 26 0x4C4647B0 27 0x47A02006 28 0x47904A45 29 0x47A020C7
    30 0x682AE00D 31 0xD10E2A02 32 0x47B04E3B 33 0x20064C3F 34 0x483F47A0 35 0x493F4780
    36 0x68084D3F 37 0x47B047A8 38 0x47A02004 39 0x6828E7CE 40 0xD1132803 41 0x47A04C32
    42 0x24004838 43 0x4E396805 44 0x68311960 45 0xD206428C 46 0x4B384A37 47 0x221018A1
    48 0x34104798 49 0x4D2AE7F3 50 0xE7B847A8 51 0x29046829 52 0x2400D11B 53 0x6806482F
    54 0xD2B042B4 55 0x47A84D24 56 0x20064E28 57 0x4B2847B0 58 0x49284798 59 0x680A4B2A
    60 0x18A018E1 61 0xF44F4B2A 62 0x47987280 63 0x200447A8 64 0xF50447B0 65 0x47A87480
    66 0x682CE7E4 67 0xD1232C05 68 0x47984B17 69 0x4D1F2400 70 0x4294682A 71 0x481BD28F
    72 0x68012210 73 0x18604E1D 74 0x47B04669 75 0x1B19682B 76 0xBF282910 77 0x23002110
    78 0xD011428B 79 0xF81D4A16 80 0x18A05003 81 0x42B55CC6 82 0x3301D101 83 0x4A15E7F4
    84 0x60112101 85 0xE7726054 86 0x25014E12 87 0xE76E6035 88 0x47A84D03 89 0xE7D63410
    90 0x40000200 91 0x100011BD 92 0x100013DD 93 0x10001289 94 0x1000800C 95 0x10008000
    96 0x10008004 97 0x1000130D 98 0x100013ED 99 0x10008010 100 0x10001335 101 0x10008014
    102 0x10008020 103 0x10001221 104 0x10001375 105 0x10008008 106 0x6A5A4B03 107 0xD0FB0512
    108 0x0060F893 109 0xBF004770 110 0x40006000 111 0x6B194B17 112 0xF4416B1A 113 0x63187040
    114 0x69186919 115 0x0110F041 116 0xF8D36119 117 0x220000C0 118 0x0106F020 119 0x00C0F8D3
    120 0x10C0F8C3 121 0x00C0F8D3 122 0x0101F040 123 0x00C0F8D3 124 0x10C0F8C3 125 0x43BCF503
    126 0x609A6899 127 0x20016AD9 128 0x691962DA 129 0x69596118 130 0x61592102 131 0x619A6999
    132 0x61DA69D9 133 0x64DA6CD9 134 0xBF004770 135 0x40000200 136 0x460EB570 137 0xB34A4614
    138 0xF3C04B15 139 0x681A4507 140 0x7240F44F 141 0x685A601A 142 0xF3C02103 143 0x2C102207
    144 0x2410BF28 145 0x605CB2C0 146 0x1060F883 147 0x5060F883 148 0xF8832101 149 0xF8832060
    150 0x689A0060 151 0x60992500 152 0x47984B08 153 0x35015570 154 0x42A2B2AA 155 0x4804D3F8
    156 0xF0116A81 157 0xD1FA0301 158 0x60836881 159 0xBD704620 160 0x40006000 161 0x100011A9
    162 0x4C10B5F8 163 0x68232003 164 0x7340F44F 165 0x68636023 166 0x60602101 167 0x68A3229F
    168 0x60A14D0B 169 0x2060F884 170 0x460647A8 171 0x460747A8 172 0x040347A8 173 0x2707EA43
    174 0x0006EA47 175 0x4B036AA1 176 0x0201F011 177 0x6899D1FA 178 0xBDF8609A 179 0x40006000
    180 0x100011A9 181 0x4C0BB510 182 0x68232001 183 0x7340F44F 184 0x68636023 185 0x60602105
    186 0x60A068A2 187 0xF8844A06 188 0x47901060 189 0x4B036AA1 190 0x0201F011 191 0x6899D1FA
    192 0xBD10609A 193 0x40006000 194 0x100011A9 195 0x21014B08 196 0xF44F681A 197 0x601A7280
    198 0x6099689A 199 0x0060F883 200 0x48036A9A 201 0x0101F012 202 0x6883D1FA 203 0x47706081
    204 0x40006000 205 0x21014B0E 206 0xF44F681A 207 0x601A7280 208 0x2220689A 209 0xF8836099
    210 0xF3C02060 211 0xF3C04107 212 0xB2C02207 213 0x1060F883 214 0x2060F883 215 0x0060F883
    216 0x4A036A99 217 0x0001F011 218 0x6893D1FA 219 0x47706090 220 0x40006000 221 0xB36AB530
    222 0x25014B17 223 0xF44F681C 224 0x601C7480 225 0x2402689C 226 0xF883609D 227 0xF3C04060
    228 0xF3C04507 229 0xB2C02407 230 0x5060F883 231 0x7F80F5B2 232 0xF44FBF28 233 0xF8837280
    234 0xF8834060 235 0x20000060 236 0x4C095C0D 237 0xF8843001 238 0xB2855060 239 0xD3F74295
    240 0x07496A99 241 0x6AA0D5FC 242 0xF0104B03 243 0xD1FA0101 244 0x60996898 245 0xBD304610
    246 0x40006000 247 0x4B02B508 248 0x07C04798 249 0xBD08D4FB 250 0x100012D5 251 0x4B04B508
    252 0xF0004798 253 0xB2C10002 254 0xD0F82900 255 0xBF00BD08 256 0x100012D5
}

set rtl8710_flasher_command_read_id      0
set rtl8710_flasher_command_mass_erase   1
set rtl8710_flasher_command_sector_erase 2
set rtl8710_flasher_command_read         3
set rtl8710_flasher_command_write        4
set rtl8710_flasher_command_verify       5

set rtl8710_flasher_mac_address_offset   0xA088

set rtl8710_flasher_ready                0
set rtl8710_flasher_capacity             0
set rtl8710_flasher_auto_erase           0
set rtl8710_flasher_auto_verify          0
set rtl8710_flasher_auto_erase_sector    0xFFFFFFFF

proc rtl8710_flasher_init {} {
    global rtl8710_flasher_firmware_ptr
    global rtl8710_flasher_buffer
    global rtl8710_flasher_capacity
    global rtl8710_flasher_ready
    global rtl8710_flasher_code

    if {[expr {$rtl8710_flasher_ready == 0}]} {
        echo "initializing RTL8710 flasher"
        halt
        mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
        mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
        array2mem rtl8710_flasher_code 32 $rtl8710_flasher_firmware_ptr [array size rtl8710_flasher_code]
        reg faultmask 0x01
        reg sp 0x20000000
        reg pc $rtl8710_flasher_firmware_ptr
        resume
        rtl8710_flasher_wait
        set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
        set rtl8710_flasher_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}]
        set rtl8710_flasher_ready 1
        echo "RTL8710 flasher initialized"
    }
    return ""
}

proc rtl8710_flasher_mrw {reg} {
    set value ""
    mem2array value 32 $reg 1
    return $value(0)
}

proc rtl8710_flasher_wait {} {
    global rtl8710_flasher_buffer
    while {[rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x00}]]} { }
}

proc rtl8710_flasher_load_block {local_filename offset len} {
    global rtl8710_flasher_buffer
    load_image $local_filename [expr {$rtl8710_flasher_buffer + 0x20 - $offset}] bin [expr {$rtl8710_flasher_buffer + 0x20}] $len
}

proc rtl8710_flasher_read_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_read
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        error "read error, offset $offset"
    }
}

proc rtl8710_flasher_write_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_write
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_write
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        error "write error, offset $offset"
    }
}

proc rtl8710_flasher_verify_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_verify
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_verify
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
        set status [expr {$status + $offset}]
        error "verify error, offset $status"
    }
}

proc rtl8710_flash_read_id {} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_capacity
    global rtl8710_flasher_command_read_id
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read_id
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
    set manufacturer_id [format "0x%02X" [expr {$id & 0xFF}]]
    set memory_type [format "0x%02X" [expr {($id >> 8) & 0xFF}]]
    set memory_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}]
    echo "manufacturer ID: $manufacturer_id, memory type: $memory_type, memory capacity: $memory_capacity bytes"
}

proc rtl8710_flash_mass_erase {} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_mass_erase
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_mass_erase
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
}

proc rtl8710_flash_sector_erase {offset} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_sector_erase
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_sector_erase
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
}

proc rtl8710_flash_read {local_filename loc size} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_buffer_size
    rtl8710_flasher_init
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "read offset $flash_offset"
        rtl8710_flasher_read_block $flash_offset $len
        dump_image /tmp/_rtl8710_flasher.bin [expr {$rtl8710_flasher_buffer + 0x20}] $len
        exec dd conv=notrunc if=/tmp/_rtl8710_flasher.bin "of=$local_filename" bs=1 "seek=$offset"
        echo "read $len bytes"
    }
}

proc rtl8710_flash_write {local_filename loc} {
    global rtl8710_flasher_buffer_size
    global rtl8710_flasher_sector_size
    global rtl8710_flasher_auto_erase
    global rtl8710_flasher_auto_verify
    global rtl8710_flasher_auto_erase_sector
    rtl8710_flasher_init
    set sector 0
    set size [file size $local_filename]
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "write offset $flash_offset"
        rtl8710_flasher_load_block $local_filename $offset $len
        if {[expr {$rtl8710_flasher_auto_erase != 0}]} {
            for {set i $flash_offset} {$i < [expr {$flash_offset + $len}]} {incr i} {
                set sector [expr {$i / $rtl8710_flasher_sector_size}]
                if {[expr {$rtl8710_flasher_auto_erase_sector != $sector}]} {
                    echo "erase sector $sector"
                    rtl8710_flash_sector_erase [expr {$sector * $rtl8710_flasher_sector_size}]
                    set rtl8710_flasher_auto_erase_sector $sector
                }
            }
        }
        rtl8710_flasher_write_block $flash_offset $len
        echo "wrote $len bytes"
        if {[expr {$rtl8710_flasher_auto_verify != 0}]} {
            echo "verify offset $flash_offset"
            rtl8710_flasher_verify_block $flash_offset $len
        }
    }
}

proc rtl8710_flash_verify {local_filename loc} {
    global rtl8710_flasher_buffer_size
    rtl8710_flasher_init
    set size [file size $local_filename]
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "read offset $flash_offset"
        rtl8710_flasher_load_block $local_filename $offset $len
        echo "verify offset $flash_offset"
        rtl8710_flasher_verify_block $flash_offset $len
    }
}

proc rtl8710_flash_read_mac {} {
    global rtl8710_flasher_mac_address_offset
    global rtl8710_flasher_buffer
    rtl8710_flasher_init
    rtl8710_flasher_read_block $rtl8710_flasher_mac_address_offset 6
    set mac ""
    mem2array mac 8 [expr {$rtl8710_flasher_buffer + 0x20}] 6
    set res "MAC address: "
    append res [format %02X $mac(0)]
    append res ":" [format %02X $mac(1)]
    append res ":" [format %02X $mac(2)]
    append res ":" [format %02X $mac(3)]
    append res ":" [format %02X $mac(4)]
    append res ":" [format %02X $mac(5)]
    echo $res
}

proc rtl8710_flash_auto_erase {on} {
    global rtl8710_flasher_auto_erase
    if {[expr {$on != 0}]} {
        set rtl8710_flasher_auto_erase 1
        echo "auto erase on"
    } else {
        set rtl8710_flasher_auto_erase 0
        echo "auto erase off"
    }
}

proc rtl8710_flash_auto_verify {on} {
    global rtl8710_flasher_auto_verify
    if {[expr {$on != 0}]} {
        set rtl8710_flasher_auto_verify 1
        echo "auto verify on"
    } else {
        set rtl8710_flasher_auto_verify 0
        echo "auto verify off"
    }
}

proc rtl8710_reboot {} {
    mww 0xE000ED0C 0x05FA0007
}

rtl8710_openocd / rtl8710_flasher.tcl

set rtl8710_flasher_command_read_id      0
set rtl8710_flasher_command_mass_erase   1
set rtl8710_flasher_command_sector_erase 2
set rtl8710_flasher_command_read         3
set rtl8710_flasher_command_write        4
set rtl8710_flasher_command_verify       5

set rtl8710_flasher_mac_address_offset   0xA088

set rtl8710_flasher_ready                0
set rtl8710_flasher_capacity             0
set rtl8710_flasher_auto_erase           0
set rtl8710_flasher_auto_verify          0
set rtl8710_flasher_auto_erase_sector    0xFFFFFFFF

proc rtl8710_flasher_init {} {
    global rtl8710_flasher_firmware_ptr
    global rtl8710_flasher_buffer
    global rtl8710_flasher_capacity
    global rtl8710_flasher_ready
    global rtl8710_flasher_code

    if {[expr {$rtl8710_flasher_ready == 0}]} {
        echo "initializing RTL8710 flasher"
        halt
        mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
        mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
        array2mem rtl8710_flasher_code 32 $rtl8710_flasher_firmware_ptr [array size rtl8710_flasher_code]
        reg faultmask 0x01
        reg sp 0x20000000
        reg pc $rtl8710_flasher_firmware_ptr
        resume
        rtl8710_flasher_wait
        set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
        set rtl8710_flasher_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}]
        set rtl8710_flasher_ready 1
        echo "RTL8710 flasher initialized"
    }
    return ""
}

proc rtl8710_flasher_mrw {reg} {
    set value ""
    mem2array value 32 $reg 1
    return $value(0)
}

proc rtl8710_flasher_wait {} {
    global rtl8710_flasher_buffer
    while {[rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x00}]]} { }
}

proc rtl8710_flasher_load_block {local_filename offset len} {
    global rtl8710_flasher_buffer
    load_image $local_filename [expr {$rtl8710_flasher_buffer + 0x20 - $offset}] bin [expr {$rtl8710_flasher_buffer + 0x20}] $len
}

proc rtl8710_flasher_read_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_read
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        error "read error, offset $offset"
    }
}

proc rtl8710_flasher_write_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_write
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_write
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        error "write error, offset $offset"
    }
}

proc rtl8710_flasher_verify_block {offset len} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_verify
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_verify
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x14}] $len
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]]
    if {[expr {$status > 0}]} {
        set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
        set status [expr {$status + $offset}]
        error "verify error, offset $status"
    }
}

proc rtl8710_flash_read_id {} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_capacity
    global rtl8710_flasher_command_read_id
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read_id
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
    set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]]
    set manufacturer_id [format "0x%02X" [expr {$id & 0xFF}]]
    set memory_type [format "0x%02X" [expr {($id >> 8) & 0xFF}]]
    set memory_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}]
    echo "manufacturer ID: $manufacturer_id, memory type: $memory_type, memory capacity: $memory_capacity bytes"
}

proc rtl8710_flash_mass_erase {} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_mass_erase
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_mass_erase
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
}

proc rtl8710_flash_sector_erase {offset} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_command_sector_erase
    rtl8710_flasher_init
    mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_sector_erase
    mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000
    mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset
    mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001
    rtl8710_flasher_wait
}

proc rtl8710_flash_read {local_filename loc size} {
    global rtl8710_flasher_buffer
    global rtl8710_flasher_buffer_size
    rtl8710_flasher_init
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "read offset $flash_offset"
        rtl8710_flasher_read_block $flash_offset $len
        dump_image /tmp/_rtl8710_flasher.bin [expr {$rtl8710_flasher_buffer + 0x20}] $len
        exec dd conv=notrunc if=/tmp/_rtl8710_flasher.bin "of=$local_filename" bs=1 "seek=$offset"
        echo "read $len bytes"
    }
}

proc rtl8710_flash_write {local_filename loc} {
    global rtl8710_flasher_buffer_size
    global rtl8710_flasher_sector_size
    global rtl8710_flasher_auto_erase
    global rtl8710_flasher_auto_verify
    global rtl8710_flasher_auto_erase_sector
    rtl8710_flasher_init
    set sector 0
    set size [file size $local_filename]
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "write offset $flash_offset"
        rtl8710_flasher_load_block $local_filename $offset $len
        if {[expr {$rtl8710_flasher_auto_erase != 0}]} {
            for {set i $flash_offset} {$i < [expr {$flash_offset + $len}]} {incr i} {
                set sector [expr {$i / $rtl8710_flasher_sector_size}]
                if {[expr {$rtl8710_flasher_auto_erase_sector != $sector}]} {
                    echo "erase sector $sector"
                    rtl8710_flash_sector_erase [expr {$sector * $rtl8710_flasher_sector_size}]
                    set rtl8710_flasher_auto_erase_sector $sector
                }
            }
        }
        rtl8710_flasher_write_block $flash_offset $len
        echo "wrote $len bytes"
        if {[expr {$rtl8710_flasher_auto_verify != 0}]} {
            echo "verify offset $flash_offset"
            rtl8710_flasher_verify_block $flash_offset $len
        }
    }
}

proc rtl8710_flash_verify {local_filename loc} {
    global rtl8710_flasher_buffer_size
    rtl8710_flasher_init
    set size [file size $local_filename]
    for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} {
        set len [expr {$size - $offset}]
        if {[expr {$len > $rtl8710_flasher_buffer_size}]} {
            set len $rtl8710_flasher_buffer_size
        }
        set flash_offset [expr {$loc + $offset}]
        echo "read offset $flash_offset"
        rtl8710_flasher_load_block $local_filename $offset $len
        echo "verify offset $flash_offset"
        rtl8710_flasher_verify_block $flash_offset $len
    }
}

proc rtl8710_flash_read_mac {} {
    global rtl8710_flasher_mac_address_offset
    global rtl8710_flasher_buffer
    rtl8710_flasher_init
    rtl8710_flasher_read_block $rtl8710_flasher_mac_address_offset 6
    set mac ""
    mem2array mac 8 [expr {$rtl8710_flasher_buffer + 0x20}] 6
    set res "MAC address: "
    append res [format %02X $mac(0)]
    append res ":" [format %02X $mac(1)]
    append res ":" [format %02X $mac(2)]
    append res ":" [format %02X $mac(3)]
    append res ":" [format %02X $mac(4)]
    append res ":" [format %02X $mac(5)]
    echo $res
}

proc rtl8710_flash_auto_erase {on} {
    global rtl8710_flasher_auto_erase
    if {[expr {$on != 0}]} {
        set rtl8710_flasher_auto_erase 1
        echo "auto erase on"
    } else {
        set rtl8710_flasher_auto_erase 0
        echo "auto erase off"
    }
}

proc rtl8710_flash_auto_verify {on} {
    global rtl8710_flasher_auto_verify
    if {[expr {$on != 0}]} {
        set rtl8710_flasher_auto_verify 1
        echo "auto verify on"
    } else {
        set rtl8710_flasher_auto_verify 0
        echo "auto verify off"
    }
}

proc rtl8710_reboot {} {
    mww 0xE000ED0C 0x05FA0007
}

tl8710_openocd / rtl8710_flasher.c

/*
 *
 * Copyright (C) 2016 Rebane, rebane@alkohol.ee
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "rtl8710.h"
#include <stdio.h>
#include "spi_flash.h"

#define MEM_START            (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x00))
#define MEM_COMMAND          (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x04))
#define MEM_STATUS           (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x08))
#define MEM_PARAM            (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x0C))
#define MEM_OFFSET           (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x10))
#define MEM_LEN              (*(volatile uint32_t *)(BUFFER_ADDRESS + 0x14))
#define MEM_DATA             ((volatile uint8_t *)(BUFFER_ADDRESS + 0x20))

#define COMMAND_READ_ID      0
#define COMMAND_MASS_ERASE   1
#define COMMAND_SECTOR_ERASE 2
#define COMMAND_READ         3
#define COMMAND_WRITE        4
#define COMMAND_VERIFY       5

int __attribute__((section(".vectors"))) main(){
    uint32_t p, i, l;
    uint8_t read_buffer[16];

    __asm__("cpsid f");

    PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_GPIO_EN | PERI_ON_CLK_CTRL_SLPCK_GPIO_EN; // enable gpio peripheral clock
    PERI_ON->SOC_PERI_FUNC1_EN |= PERI_ON_SOC_PERI_FUNC1_EN_GPIO; // enable gpio peripheral

    PERI_ON->GPIO_SHTDN_CTRL = 0xFF;
    PERI_ON->GPIO_DRIVING_CTRL = 0xFF;

    spi_flash_init();

    // read jedec info
    spi_flash_wait_busy();
    MEM_PARAM = spi_flash_jedec_id();
    spi_flash_wait_busy();

    while(1){
        MEM_START = 0x00000000;
        while(MEM_START == 0x00000000);
        if(MEM_COMMAND == COMMAND_READ_ID){
            MEM_PARAM = 0x00000000;
            spi_flash_wait_busy();
            MEM_PARAM = spi_flash_jedec_id();
            spi_flash_wait_busy();
        }else if(MEM_COMMAND == COMMAND_MASS_ERASE){
            spi_flash_wait_busy();
            spi_flash_cmd(0x06);
            spi_flash_wait_wel();
            spi_flash_cmd(0xC7);
            spi_flash_wait_busy();
            spi_flash_cmd(0x04);
            spi_flash_wait_busy();
        }else if(MEM_COMMAND == COMMAND_SECTOR_ERASE){
            spi_flash_wait_busy();
            spi_flash_cmd(0x06);
            spi_flash_wait_wel();
            spi_flash_sector_erase(MEM_OFFSET);
            spi_flash_wait_busy();
            spi_flash_cmd(0x04);
            spi_flash_wait_busy();
        }else if(MEM_COMMAND == COMMAND_READ){
            spi_flash_wait_busy();
            p = MEM_OFFSET;
            for(i = 0; i < MEM_LEN; i += 16, p += 16){
                spi_flash_read(p, (void *)&MEM_DATA[i], 16);
            }
            spi_flash_wait_busy();
        }else if(MEM_COMMAND == COMMAND_WRITE){
            for(p = 0; p < MEM_LEN; p += 256){
                spi_flash_wait_busy();
                spi_flash_cmd(0x06);
                spi_flash_wait_wel();
                spi_flash_write((MEM_OFFSET + p), (void *)&MEM_DATA[p], 256);
                spi_flash_wait_busy();
                spi_flash_cmd(0x04);
                spi_flash_wait_busy();
            }
        }else if(MEM_COMMAND == COMMAND_VERIFY){
            spi_flash_wait_busy();
            for(p = 0; p < MEM_LEN; p += 16){
                spi_flash_read((MEM_OFFSET + p), read_buffer, 16);
                l = MEM_LEN - p;
                if(l > 16)l = 16;
                for(i = 0; i < l; i++){
                    if(read_buffer[i] != MEM_DATA[p + i]){
                        break;
                    }
                }
                if(i < l){
                    MEM_STATUS = 0x00000001;
                    MEM_PARAM = p;
                    break;
                }
                spi_flash_wait_busy();
            }
        }else{
            MEM_STATUS = 0x00000001;
        }
    }
}

 

rtl8710_openocd / spi_flash.h

/*
 *
 * Copyright (C) 2016 Rebane, rebane@alkohol.ee
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef _SPI_FLASH_H_
#define _SPI_FLASH_H_

#include <stdint.h>

void spi_flash_init();
uint16_t spi_flash_read(uint32_t address, void *buf, uint16_t count);
uint16_t spi_flash_write(uint32_t address, const void *buf, uint16_t count);
uint32_t spi_flash_jedec_id();
uint8_t spi_flash_status();
void spi_flash_cmd(uint8_t cmd);
void spi_flash_sector_erase(uint32_t address);
void spi_flash_wait_busy();
void spi_flash_wait_wel();

#endif

 

rtl8710_openocd / spi_flash.c

/*
 *
 * Copyright (C) 2016 Rebane, rebane@alkohol.ee
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
 * Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "spi_flash.h"
#include "rtl8710.h"
#include "mask.h"

static void spi_flash_send(uint8_t byte){
    // while(!(SPI_FLASH->SR & SPI_SR_TFNF));
    SPI_FLASH->DR = byte;
}

static uint8_t spi_flash_recv(){
    while(!(SPI_FLASH->RXFLR & 0x0FFF));
    return(SPI_FLASH->DR);
}

void spi_flash_init(){
    PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_FLASH_EN | PERI_ON_CLK_CTRL_SLPCK_FLASH_EN; // enable spi flash peripheral clock
    PERI_ON->SOC_FUNC_EN |= PERI_ON_SOC_FUNC_EN_FLASH; // enable spi flash peripheral
    mask32_set(PERI_ON->CPU_PERIPHERAL_CTRL, PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_SEL, 0); // select spi flash pinout (0 - internal)
    PERI_ON->CPU_PERIPHERAL_CTRL |= PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_EN; // enable spi flash pins

    SPI_FLASH->SSIENR = 0; // disable SPI FLASH operation
    SPI_FLASH->IMR = 0; // disable all interrupts
    SPI_FLASH->SER = SPI_SER_SS0; // use first "slave select" pin
    SPI_FLASH->BAUDR = 2; // baud rate, default value
    SPI_FLASH->TXFTLR = 0; // tx fifo threshold
    SPI_FLASH->RXFTLR = 0; // rx fifo threshold
    SPI_FLASH->DMACR = 0; // disable DMA
}

uint16_t spi_flash_read(uint32_t address, void *buf, uint16_t count){
    uint16_t i;
    if(!count)return(0);
    if(count > 16)count = 16;
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
    SPI_FLASH->CTRLR1 = count;

    spi_flash_send(0x03); // flash command "read"
    spi_flash_send((address >> 16) & 0xFF); // address * 3
    spi_flash_send((address >> 8) & 0xFF);
    spi_flash_send((address >> 0) & 0xFF);

    SPI_FLASH->SSIENR = 1;

    for(i = 0; i < count; i++){
        ((uint8_t *)buf)[i] = spi_flash_recv();
    }
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
    return(count);
}

uint32_t spi_flash_jedec_id(){
    uint32_t id;
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
    SPI_FLASH->CTRLR1 = 3;

    SPI_FLASH->SSIENR = 1;
    spi_flash_send(0x9F); // jedec id
    id = spi_flash_recv();
    id |= ((uint32_t)spi_flash_recv() << 8);
    id |= ((uint32_t)spi_flash_recv() << 16);
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
    return(id);
}

uint8_t spi_flash_status(){
    uint8_t status;
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);
    SPI_FLASH->CTRLR1 = 1;

    SPI_FLASH->SSIENR = 1;
    spi_flash_send(0x05); // read status
    status = spi_flash_recv();
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
    return(status);
}

void spi_flash_cmd(uint8_t cmd){
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);

    SPI_FLASH->SSIENR = 1;
    spi_flash_send(cmd);
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
}

void spi_flash_sector_erase(uint32_t address){
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);

    SPI_FLASH->SSIENR = 1;
    spi_flash_send(0x20); // sector erase
    spi_flash_send((address >> 16) & 0xFF);
    spi_flash_send((address >> 8) & 0xFF);
    spi_flash_send((address >> 0) & 0xFF);
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
}

uint16_t spi_flash_write(uint32_t address, const void *buf, uint16_t count){
    uint16_t i;
    if(!count)return(0);
    if(count > 256)count = 256;
    SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0);

    SPI_FLASH->SSIENR = 1;
    spi_flash_send(0x02); // write
    spi_flash_send((address >> 16) & 0xFF);
    spi_flash_send((address >> 8) & 0xFF);
    spi_flash_send((address >> 0) & 0xFF);
    for(i = 0; i < count; i++){
        spi_flash_send(((uint8_t *)buf)[i]);
    }
    while(!(SPI_FLASH->SR & SPI_SR_TFE));
    while(SPI_FLASH->SR & SPI_SR_SSI);
    SPI_FLASH->SSIENR = 0;
    return(count);
}

void spi_flash_wait_busy(){
    while(spi_flash_status() & 0x01);
}

void spi_flash_wait_wel(){
    while(!(spi_flash_status() & 0x02));
}

rtl8710_openocd / make_array.c

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>

int main(){
    ssize_t i, l;
    uint32_t value, index;
    uint8_t buffer[24];
    index = 0;
    while(1){
        l = read(0, buffer, 24);
        if(l < 1)break;
        printf("\t");
        for(i = 0; i < l; i += 4){
            value = ((uint32_t)buffer[i + 0] << 0) | ((uint32_t)buffer[i + 1] << 8) | ((uint32_t)buffer[i + 2] << 16) | ((uint32_t)buffer[i + 3] << 24);
            if(i)printf(" ");
            printf("%d 0x%08X", index++, (unsigned int)value);
        }
        printf("\n");
    }
}

 

RTL-8710 openocd support

OpenOCD support for RTL8710 and integrated flash.

pins:

SWD

  • SWDIO: GE3
  • SWCLK: GE4

JTAG

  • TRST: GE0
  • TDI: GE1
  • TDO: GE2
  • TMS: GE3
  • TCK: GE4

building:

make

available OpenOCD commands:

rtl8710_flash_read_id

read and parse the jedec id bytes from flash

rtl8710_flash_read_mac

read MAC address from flash memory at 0xA088

rtl8710_flash_mass_erase

erase whole flash

rtl8710_flash_read [filename] [offset] [size]

dump (size) bytes from flash offset (offset) to file (filename)

rtl8710_flash_write [filename] [offset]

write file (filename) to flash offset (offset)

rtl8710_flash_verify [filename] [offset]

compare file (filename) with flash offset (offset)

rtl8710_flash_auto_erase [1/0]

set auto_erase option on/off. flash sectors will be autoerased when writing

rtl8710_flash_auto_verify [1/0]

set auto_verify option on/off. each block of data will be auto verified when writing

examples:

openocd -f interface/stlink-v2-1.cfg -f rtl8710.ocd -c "init" -c "reset halt" -c "rtl8710_flash_read_id" -c "rtl8710_flash_read dump.bin 0 1048576" -c "shutdown"
openocd -f interface/stlink-v2-1.cfg -f rtl8710.ocd -c "init" -c "reset halt" -c "rtl8710_flash_auto_erase 1" -c "rtl8710_flash_auto_verify 1" -c "rtl8710_flash_write dump.bin 0" -c "shutdown"

About

RTL8710 OpenOCD support is created by Rebane (rebane@alkohol.ee)

This document and the attached source code is released under GPLv2.

 

posted @ 2016-10-26 23:45 carprog 阅读(...) 评论(...) 编辑 收藏