├── .gitignore ├── .gitmodules ├── .travis.yml ├── COPYING ├── HACKING ├── Makefile ├── README.md ├── driver ├── blackmagic.inf └── blackmagic_upgrade.inf ├── scripts ├── README ├── bootprog.py ├── dfu-convert.py ├── dfu.py ├── gdb.py ├── get_openocd_nrf51_ids.py ├── hexprog.py ├── stm32_mem.py └── stubs │ ├── Makefile │ ├── stm32_opterase.S │ └── stm32_optprog.S ├── src ├── Makefile ├── command.c ├── crc32.c ├── exception.c ├── gdb_hostio.c ├── gdb_hostio.h ├── gdb_main.c ├── gdb_packet.c ├── hex_utils.c ├── include │ ├── command.h │ ├── crc32.h │ ├── exception.h │ ├── gdb_if.h │ ├── gdb_main.h │ ├── gdb_packet.h │ ├── general.h │ ├── hex_utils.h │ ├── jtagtap.h │ ├── morse.h │ ├── platform_support.h │ ├── swdptap.h │ └── target.h ├── main.c ├── morse.c ├── platforms │ ├── common │ │ ├── cdcacm.c │ │ ├── cdcacm.h │ │ ├── serialno.h │ │ ├── swdptap.c │ │ ├── timing.c │ │ ├── timing.h │ │ ├── traceswo.h │ │ └── usbuart.h │ ├── f4discovery │ │ ├── Makefile.inc │ │ ├── Readme │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ ├── hydrabus │ │ ├── Makefile.inc │ │ ├── Readme.md │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ ├── launchpad-icdi │ │ ├── Makefile.inc │ │ ├── platform.c │ │ └── platform.h │ ├── libftdi │ │ ├── Makefile.inc │ │ ├── gdb_if.c │ │ ├── jtagtap.c │ │ ├── platform.c │ │ ├── platform.h │ │ └── swdptap.c │ ├── native │ │ ├── Makefile.inc │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ ├── stlink-bootloader │ │ ├── Connector │ │ ├── Makefile.inc │ │ ├── Readme │ │ ├── dfu_upgrade.c │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ ├── stlink │ │ ├── Connector │ │ ├── Makefile.inc │ │ ├── Readme │ │ ├── dfu_upgrade.c │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ ├── stm32 │ │ ├── blackmagic.ld │ │ ├── dfu_f1.c │ │ ├── dfu_f4.c │ │ ├── dfucore.c │ │ ├── f4discovery.ld │ │ ├── gdb_if.c │ │ ├── gpio.h │ │ ├── jtagtap.c │ │ ├── serialno.c │ │ ├── stlink-bootloader.ld │ │ ├── stlink.ld │ │ ├── stm32_can.ld │ │ ├── timing_stm32.c │ │ ├── timing_stm32.h │ │ ├── traceswo.c │ │ ├── usbdfu.h │ │ └── usbuart.c │ ├── swlink │ │ ├── Connectors │ │ ├── Makefile.inc │ │ ├── Readme │ │ ├── platform.c │ │ ├── platform.h │ │ └── usbdfu.c │ └── tm4c │ │ ├── gdb_if.c │ │ ├── jtagtap.c │ │ ├── tm4c.ld │ │ ├── traceswo.c │ │ └── usbuart.c └── target │ ├── adiv5.c │ ├── adiv5.h │ ├── adiv5_jtagdp.c │ ├── adiv5_swdp.c │ ├── cortexa.c │ ├── cortexm.c │ ├── cortexm.h │ ├── efm32.c │ ├── flashstub │ ├── Makefile │ ├── README.md │ ├── efm32.c │ ├── efm32.stub │ ├── lmi.c │ ├── lmi.stub │ ├── nrf51.s │ ├── nrf51.stub │ ├── stm32f1.c │ ├── stm32f1.stub │ ├── stm32f4.c │ ├── stm32f4.stub │ ├── stm32l4.c │ ├── stm32l4.stub │ └── stub.h │ ├── jtag_scan.c │ ├── jtag_scan.h │ ├── jtagtap_generic.c │ ├── kinetis.c │ ├── lmi.c │ ├── lpc11xx.c │ ├── lpc15xx.c │ ├── lpc43xx.c │ ├── lpc_common.c │ ├── lpc_common.h │ ├── nrf51.c │ ├── sam3x.c │ ├── sam4l.c │ ├── samd.c │ ├── stm32f1.c │ ├── stm32f4.c │ ├── stm32l0.c │ ├── stm32l4.c │ ├── swdptap_generic.c │ ├── target.c │ └── target_internal.h └── upgrade ├── Makefile ├── bindata.S ├── bindata.h ├── dfu.c ├── dfu.h ├── main.c ├── stm32mem.c └── stm32mem.h /.gitignore: -------------------------------------------------------------------------------- 1 | src/include/version.h 2 | blackmagic 3 | *.bin 4 | *.hex 5 | blackmagic_dfu 6 | dfu_upgrade 7 | mapfile 8 | *.o 9 | *.d 10 | .*.swp 11 | *~ 12 | *.pyc 13 | tags 14 | .gdbinit 15 | *.s#* 16 | *.b#* 17 | blackmagic_upgrade 18 | *.exe 19 | 20 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/libopencm3/libopencm3.git 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | before_install: 4 | - sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa 5 | - sudo apt-get update -qq 6 | - sudo apt-get install -y build-essential libftdi-dev gcc-arm-embedded 7 | - sudo pip install intelhex 8 | 9 | install: true 10 | 11 | script: 12 | - make -C libopencm3 lib 13 | - make -C src all_platforms 14 | 15 | deploy: 16 | provider: s3 17 | access_key_id: AKIAIDXRMRPEG5OCN5AQ 18 | secret_access_key: 19 | secure: AKGtHD71s7FEfmzSWkrEgW8DT3exDzKPROn4hI4kwuMcI6gYoOHqloEhzqZVi9ok8ynEkGfzzaAAcPYCNjlxOu2zmMJFgCiGegIUacrpJuzo9eknqW281pEpIlSXonrlttW9Hm0gJhl3yLKdMQYKoXvCfR7HgUkcN7QSAZxLgv297u/azMLq2z6rZdTCgZYpD2EIB3BlqChZkoepyczBYEtGOj0tMW4WF79qufIfVnUnQqWr8Lef2tQ9X9MEn7LIsHbBgGJ08TGb2yIiPTF+NyE+2ev3KmVmBdzDLdfAAV3koPtiTsTBdcstNAT51vvPsQhuIXB7gIr91xhquCel84DV285aZn2wOwgQ0KHhbFLVFXb2wv+r1saF1b4/rJTiobavDbIXIDVm/UfAs41AyM/zoclTeixAgyA8BpuhDEP+2dDYk3rehZ1Uhbaf8U9OKyQ6kYg1aFOQU5jYFjIbJmgSTlkJwntk9w3EX7lI8LSInNgdPhM8Ak6IjTCKg8NSKvtDH27X++UNVn1r2vX0eMjcusUNSPktjvilWIFMIvPw8bO2yLgj6bLDQ73WsEUC0LiiqL45r3A5KOMkMO8z1xp0TOz2f3Pxdyr1l2gXC0n/hxutoue7HaaPE2zA08giYdSCwZBxSedcoxxKA8V+E4vwfm0D/sWZS+U7vXm15LE= 20 | bucket: builds.blacksphere.co.nz 21 | region: us-west-2 22 | local-dir: src/artifacts 23 | upload-dir: blackmagic 24 | acl: public_read 25 | skip_cleanup: true 26 | on: 27 | repo: blacksphere/blackmagic 28 | branch: master 29 | -------------------------------------------------------------------------------- /HACKING: -------------------------------------------------------------------------------- 1 | See https://github.com/blacksphere/blackmagic/wiki/Hacking 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifneq ($(V), 1) 2 | MFLAGS += --no-print-dir 3 | Q := @ 4 | endif 5 | 6 | all: 7 | $(Q)if [ ! -f libopencm3/Makefile ]; then \ 8 | echo "Initialising git submodules..." ;\ 9 | git submodule init ;\ 10 | git submodule update ;\ 11 | fi 12 | $(Q)$(MAKE) $(MFLAGS) -C libopencm3 lib 13 | $(Q)$(MAKE) $(MFLAGS) -C src 14 | 15 | clean: 16 | $(Q)$(MAKE) $(MFLAGS) -C libopencm3 $@ 17 | $(Q)$(MAKE) $(MFLAGS) -C src $@ 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Black Magic Probe 2 | ================= 3 | 4 | [![Build Status](https://travis-ci.org/blacksphere/blackmagic.svg?branch=master)](https://travis-ci.org/blacksphere/blackmagic) 5 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/blacksphere/blackmagic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) 6 | [![Donate](https://img.shields.io/badge/paypal-donate-blue.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=N84QYNAM2JJQG) 7 | [![Kickstarter](https://img.shields.io/badge/kickstarter-back%20us-14e16e.svg)](https://www.kickstarter.com/projects/esden/1bitsy-and-black-magic-probe-demystifying-arm-prog) 8 | 9 | Firmware for the Black Magic Debug Probe. 10 | 11 | The Black Magic Probe is a modern, in-application debugging tool for 12 | embedded microprocessors. It allows you see what is going on 'inside' an 13 | application running on an embedded microprocessor while it executes. It is 14 | able to control and examine the state of the target microprocessor using a 15 | JTAG or Serial Wire Debugging (SWD) port and on-chip debug logic provided 16 | by the microprocessor. The probe connects to a host computer using a 17 | standard USB interface. The user is able to control exactly what happens 18 | using the GNU source level debugging software, GDB. 19 | 20 | See online documentation at https://github.com/blacksphere/blackmagic/wiki 21 | 22 | Binaries from the latest automated build are at http://builds.blacksphere.co.nz/blackmagic 23 | -------------------------------------------------------------------------------- /driver/blackmagic.inf: -------------------------------------------------------------------------------- 1 | ; Windows USB CDC ACM driver setup file. 2 | 3 | ; Copyright (C) 2004 Al Borchers (alborchers@steinerpoint.com) 4 | ; Taken from Linux documentation, modified for Black Magic debug probe 5 | ; by Gareth McMullin 6 | 7 | ; This provides the driver information for the GDB and UART interfaces to 8 | ; be presented as virtual serial ports in Windows. 9 | 10 | ; Common to Windows 32- and 64-bit systems 11 | 12 | [Version] 13 | Signature="$Windows NT$" 14 | Class=Ports 15 | ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} 16 | Provider=%BLACKSPHERE% 17 | DriverVer=28/12/2011,0.0.1.1 18 | 19 | [Manufacturer] 20 | %VendorName%=DeviceList, NTamd64 21 | 22 | [Strings] 23 | VendorName = "Black Sphere Technologies" 24 | BLACKMAGICGDB = "Black Magic GDB Server" 25 | BLACKMAGICUART = "Black Magic UART Port" 26 | BLACKSPHERE_DISPLAY_NAME = "Black Magic Probe Driver" 27 | 28 | [DeviceList] 29 | %BLACKMAGICGDB%=DriverInstall, USB\VID_1d50&PID_6018&Rev_0100&MI_00 30 | %BLACKMAGICUART%=DriverInstall, USB\VID_1d50&PID_6018&Rev_0100&MI_02 31 | 32 | [DeviceList.NTamd64] 33 | %BLACKMAGICGDB%=DriverInstall, USB\VID_1d50&PID_6018&Rev_0100&MI_00 34 | %BLACKMAGICUART%=DriverInstall, USB\VID_1d50&PID_6018&Rev_0100&MI_02 35 | 36 | [DestinationDirs] 37 | DefaultDestDir=10,System32\Drivers 38 | 39 | ; Windows 32-bit sections 40 | ;~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 42 | [DriverInstall.nt] 43 | CopyFiles=DriverCopyFiles.nt 44 | AddReg=DriverInstall.nt.AddReg 45 | 46 | [DriverCopyFiles.nt] 47 | usbser.sys,,,0x20 48 | 49 | [DriverInstall.nt.AddReg] 50 | HKR,,DevLoader,,*ntkern 51 | HKR,,NTMPDriver,,usbser.sys 52 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 53 | 54 | [DriverInstall.nt.Services] 55 | AddService = usbser,0x0002,DriverService.nt 56 | 57 | [DriverService.nt] 58 | DisplayName = %BLACKSPHERE_DISPLAY_NAME% 59 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 60 | StartType = 3 ; SERVICE_DEMAND_START 61 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 62 | ServiceBinary = %10%\System32\Drivers\usbser.sys 63 | LoadOrderGroup = Base 64 | 65 | ; Windows 64-bit sections 66 | ;~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | [DriverInstall.NTamd64] 68 | CopyFiles=DriverCopyFiles.NTamd64 69 | AddReg=DriverInstall.NTamd64.AddReg 70 | 71 | [DriverCopyFiles.NTamd64] 72 | usbser.sys,,,0x20 73 | 74 | [DriverInstall.NTamd64.AddReg] 75 | HKR,,DevLoader,,*ntkern 76 | HKR,,NTMPDriver,,usbser.sys 77 | HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" 78 | 79 | [DriverInstall.NTamd64.Services] 80 | AddService = usbser,0x0002,DriverService.NTamd64 81 | 82 | [DriverService.NTamd64] 83 | DisplayName = %BLACKSPHERE_DISPLAY_NAME% 84 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 85 | StartType = 3 ; SERVICE_DEMAND_START 86 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 87 | ServiceBinary = %10%\System32\Drivers\usbser.sys 88 | LoadOrderGroup = Base 89 | 90 | -------------------------------------------------------------------------------- /scripts/README: -------------------------------------------------------------------------------- 1 | This directory contains some useful scripts for working 2 | on the Black Magic Debug project. 3 | 4 | bootprog.py - Production programmer using the STM32 SystemMemory bootloader. 5 | hexprog.py - Write an Intel hex file to a target using the GDB protocol. 6 | stm32_mem.py - Access STM32 Flash memory using USB DFU class interface. 7 | 8 | stubs/ - Source code for the microcode strings included in hexprog.py. 9 | 10 | -------------------------------------------------------------------------------- /scripts/get_openocd_nrf51_ids.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """Pulls nRF51 IDs from openocd's nrf51.c in a form suitable for 4 | pasting into blackmagic's nrf51.c 5 | 6 | """ 7 | 8 | import subprocess,re 9 | 10 | cmd = 'git archive --remote=git://git.code.sf.net/p/openocd/code HEAD src/flash/nor/nrf51.c | tar -xO' 11 | 12 | class Spec(): 13 | def __repr__(self): 14 | return "0x%04X: /* %s %s %s */"%(self.hwid,self.comment, self.variant,self.build_code) 15 | 16 | fd = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE).stdout 17 | 18 | specdict={} 19 | specs=[] 20 | spec=Spec() 21 | for line in fd.read().split('\n'): 22 | m=re.search('/\*(.*)\*/',line) 23 | if m: 24 | lastcomment=m.group(1) 25 | 26 | m=re.search('.hwid.*=\s*(0x[0-9A-F]*),',line) 27 | if m: 28 | spec.hwid=int(m.group(1),base=0) 29 | m=re.search('.variant.*=\s*"(.*)",',line) 30 | if m: 31 | spec.variant=m.group(1) 32 | m=re.search('.build_code.*=\s*"(.*)",',line) 33 | if m: 34 | spec.build_code=m.group(1) 35 | m=re.search('.flash_size_kb.*=\s*([0-9]*),',line) 36 | if m: 37 | spec.flash_size_kb=int(m.group(1),base=0) 38 | ram,flash = {'AA':(16,256), 39 | 'AB':(16,128), 40 | 'AC':(32,256)}[spec.variant[-2:]] 41 | assert flash==spec.flash_size_kb 42 | spec.ram_size_kb = ram 43 | nicecomment =lastcomment.strip().replace('IC ','').replace('Devices ','').replace('.','') 44 | spec.comment=nicecomment 45 | 46 | specdict.setdefault((ram,flash),[]).append(spec) 47 | specs.append(spec) 48 | spec=Spec() 49 | 50 | for (ram,flash),specs in specdict.iteritems(): 51 | specs.sort(key=lambda x:x.hwid) 52 | for spec in specs: 53 | print "\tcase",spec 54 | print '\t\tt->driver = "Nordic nRF51";' 55 | print '\t\ttarget_add_ram(t, 0x20000000, 0x%X);'%(1024*ram) 56 | print '\t\tnrf51_add_flash(t, 0x00000000, 0x%X, NRF51_PAGE_SIZE);'%(1024*flash) 57 | print '\t\tnrf51_add_flash(t, NRF51_UICR, 0x100, 0x100);' 58 | print '\t\ttarget_add_commands(t, nrf51_cmd_list, "nRF51");' 59 | print '\t\treturn true;' 60 | 61 | -------------------------------------------------------------------------------- /scripts/stm32_mem.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # stm32_mem.py: STM32 memory access using USB DFU class 4 | # Copyright (C) 2011 Black Sphere Technologies 5 | # Written by Gareth McMullin 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | 20 | from time import sleep 21 | import struct 22 | from sys import stdout, argv 23 | 24 | import argparse 25 | import usb 26 | import dfu 27 | 28 | CMD_GETCOMMANDS = 0x00 29 | CMD_SETADDRESSPOINTER = 0x21 30 | CMD_ERASE = 0x41 31 | 32 | def stm32_erase(dev, addr): 33 | erase_cmd = struct.pack("" 67 | print 68 | 69 | parser = argparse.ArgumentParser() 70 | parser.add_argument("progfile", help="Binary file to program") 71 | parser.add_argument("-s", "--serial_target", help="Match Serial Number") 72 | args = parser.parse_args() 73 | devs = dfu.finddevs() 74 | if not devs: 75 | print "No devices found!" 76 | exit(-1) 77 | 78 | for dev in devs: 79 | dfudev = dfu.dfu_device(*dev) 80 | man = dfudev.handle.getString(dfudev.dev.iManufacturer, 30) 81 | product = dfudev.handle.getString(dfudev.dev.iProduct, 64) 82 | serial_no = dfudev.handle.getString(dfudev.dev.iSerialNumber, 30) 83 | if args.serial_target: 84 | if man == "Black Sphere Technologies" and serial_no == args.serial_target: break 85 | if man == "STMicroelectronics" and serial_no == args.serial_target: break 86 | else: 87 | if man == "Black Sphere Technologies": break 88 | if man == "STMicroelectronics": break 89 | 90 | print "Device %s: ID %04x:%04x %s - %s\n\tSerial %s" % ( 91 | dfudev.dev.filename, dfudev.dev.idVendor, 92 | dfudev.dev.idProduct, man, product, serial_no) 93 | 94 | if args.serial_target and serial_no != args.serial_target: 95 | print "Serial number doesn't match!\n" 96 | exit(-2) 97 | try: 98 | state = dfudev.get_state() 99 | except: 100 | print "Failed to read device state! Assuming APP_IDLE" 101 | state = dfu.STATE_APP_IDLE 102 | if state == dfu.STATE_APP_IDLE: 103 | dfudev.detach() 104 | print "Run again to upgrade firmware." 105 | exit(0) 106 | 107 | dfudev.make_idle() 108 | 109 | bin = open(args.progfile, "rb").read() 110 | 111 | if "F4" in product: 112 | addr = 0x8004000 113 | else: 114 | addr = 0x8002000 115 | while bin: 116 | print ("Programming memory at 0x%08X\r" % addr), 117 | stdout.flush() 118 | try: 119 | stm32_erase(dfudev, addr) 120 | except: 121 | print "\nErase Timed out\n" 122 | break 123 | stm32_write(dfudev, bin[:1024]) 124 | 125 | bin = bin[1024:] 126 | addr += 1024 127 | 128 | stm32_manifest(dfudev) 129 | 130 | print "\nAll operations complete!\n" 131 | -------------------------------------------------------------------------------- /scripts/stubs/Makefile: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE = stm32- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | all: stm32_opterase.bin stm32_optprog.bin 6 | 7 | %.bin: %.S 8 | $(CC) -nostdlib -Wl,-Ttext,0x20000000 $< 9 | $(OBJCOPY) -O binary a.out $@ 10 | 11 | clean: 12 | -rm *.bin 13 | -------------------------------------------------------------------------------- /scripts/stubs/stm32_opterase.S: -------------------------------------------------------------------------------- 1 | @; Assembler sequence to erase option bytes on STM32 2 | @; Takes no parameters, ends with BKPT instruction 3 | .global _start 4 | 5 | .equ FLASHBASE, 0x40022000 6 | 7 | .equ KEY1, 0x45670123 8 | .equ KEY2, 0xCDEF89AB 9 | 10 | .equ FLASH_KEY, 0x04 11 | .equ FLASH_OPTKEY, 0x08 12 | .equ FLASH_CR, 0x10 13 | .equ FLASH_SR, 0x0C 14 | 15 | .equ OPTER, 0x20 16 | .equ STRT, 0x40 17 | 18 | .equ BSY, 0x01 19 | 20 | .syntax unified 21 | 22 | _start: 23 | @; Load FLASH controller base address 24 | ldr r0, =FLASHBASE 25 | 26 | @; Do unlocking sequence 27 | ldr r1, =KEY1 28 | str r1, [r0, #FLASH_KEY] 29 | ldr r1, =KEY2 30 | str r1, [r0, #FLASH_KEY] 31 | 32 | @; Same for option bytes 33 | ldr r1, =KEY1 34 | str r1, [r0, #FLASH_OPTKEY] 35 | ldr r1, =KEY2 36 | str r1, [r0, #FLASH_OPTKEY] 37 | 38 | @; Set OPTER bit in FLASH_CR 39 | ldr r1, [r0, #FLASH_CR] 40 | orr r1, r1, #OPTER 41 | str r1, [r0, #FLASH_CR] 42 | @; Set STRT bit in FLASH_CR 43 | orr r1, r1, #STRT 44 | str r1, [r0, #FLASH_CR] 45 | 46 | _wait: @; Wait for BSY bit to clear 47 | ldr r4, [r0, #FLASH_SR] 48 | mov r6, #BSY 49 | tst r4, r6 50 | bne _wait 51 | 52 | bkpt 53 | 54 | -------------------------------------------------------------------------------- /scripts/stubs/stm32_optprog.S: -------------------------------------------------------------------------------- 1 | @; Assembler sequence to program option bytes on STM32 2 | @; Takes option address in r0 and value in r1. 3 | @; Ends with BKPT instruction 4 | .global _start 5 | 6 | .equ FLASHBASE, 0x40022000 7 | 8 | .equ KEY1, 0x45670123 9 | .equ KEY2, 0xCDEF89AB 10 | 11 | .equ FLASH_KEY, 0x04 12 | .equ FLASH_OPTKEY, 0x08 13 | .equ FLASH_CR, 0x10 14 | .equ FLASH_SR, 0x0C 15 | 16 | .equ OPTPG, 0x10 17 | 18 | .equ BSY, 0x01 19 | 20 | .syntax unified 21 | 22 | _start: 23 | @; Load FLASH controller base address 24 | ldr r2, =FLASHBASE 25 | 26 | @; Do unlocking sequence 27 | ldr r3, =KEY1 28 | str r3, [r2, #FLASH_KEY] 29 | ldr r3, =KEY2 30 | str r3, [r2, #FLASH_KEY] 31 | 32 | @; Same for option bytes 33 | ldr r3, =KEY1 34 | str r3, [r2, #FLASH_OPTKEY] 35 | ldr r3, =KEY2 36 | str r3, [r2, #FLASH_OPTKEY] 37 | 38 | @; Set OPTPG bit in FLASH_CR 39 | ldr r3, [r2, #FLASH_CR] 40 | orr r3, r3, #OPTPG 41 | str r3, [r2, #FLASH_CR] 42 | @; Write data at address 43 | strh r1, [r0] 44 | 45 | _wait: @; Wait for BSY bit to clear 46 | ldr r4, [r2, #FLASH_SR] 47 | mov r6, #BSY 48 | tst r4, r6 49 | bne _wait 50 | 51 | bkpt 52 | 53 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | PROBE_HOST ?= native 2 | PLATFORM_DIR = platforms/$(PROBE_HOST) 3 | VPATH += $(PLATFORM_DIR) platforms/common target 4 | ENABLE_DEBUG ?= 5 | 6 | ifneq ($(V), 1) 7 | MAKEFLAGS += --no-print-dir 8 | Q := @ 9 | endif 10 | 11 | OPT_FLAGS ?= -O2 12 | 13 | CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts\ 14 | $(OPT_FLAGS) -std=gnu99 -g3 -MD \ 15 | -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) 16 | LDFLAGS += $(OPT_FLAGS) 17 | 18 | ifeq ($(ENABLE_DEBUG), 1) 19 | CFLAGS += -DENABLE_DEBUG 20 | endif 21 | 22 | SRC = \ 23 | adiv5.c \ 24 | adiv5_jtagdp.c \ 25 | adiv5_swdp.c \ 26 | command.c \ 27 | cortexa.c \ 28 | cortexm.c \ 29 | crc32.c \ 30 | efm32.c \ 31 | exception.c \ 32 | gdb_if.c \ 33 | gdb_main.c \ 34 | gdb_hostio.c \ 35 | gdb_packet.c \ 36 | hex_utils.c \ 37 | jtag_scan.c \ 38 | jtagtap.c \ 39 | jtagtap_generic.c \ 40 | lmi.c \ 41 | lpc_common.c \ 42 | lpc11xx.c \ 43 | lpc15xx.c \ 44 | lpc43xx.c \ 45 | kinetis.c \ 46 | main.c \ 47 | morse.c \ 48 | nrf51.c \ 49 | platform.c \ 50 | sam3x.c \ 51 | sam4l.c \ 52 | samd.c \ 53 | stm32f1.c \ 54 | stm32f4.c \ 55 | stm32l0.c \ 56 | stm32l4.c \ 57 | swdptap.c \ 58 | swdptap_generic.c \ 59 | target.c \ 60 | 61 | include $(PLATFORM_DIR)/Makefile.inc 62 | 63 | OBJ = $(SRC:.c=.o) 64 | 65 | blackmagic: include/version.h $(OBJ) 66 | @echo " LD $@" 67 | $(Q)$(CC) -o $@ $(OBJ) $(LDFLAGS) 68 | 69 | %.o: %.c 70 | @echo " CC $<" 71 | $(Q)$(CC) $(CFLAGS) -c $< -o $@ 72 | 73 | %.bin: % 74 | @echo " OBJCOPY $@" 75 | $(Q)$(OBJCOPY) -O binary $^ $@ 76 | 77 | %.hex: % 78 | @echo " OBJCOPY $@" 79 | $(Q)$(OBJCOPY) -O ihex $^ $@ 80 | 81 | .PHONY: clean host_clean all_platforms FORCE 82 | 83 | clean: host_clean 84 | $(Q)echo " CLEAN" 85 | -$(Q)$(RM) -f *.o *.d *~ blackmagic $(HOSTFILES) 86 | -$(Q)$(RM) -f platforms/*/*.o platforms/*/*.d mapfile 87 | 88 | all_platforms: 89 | $(Q)set -e ;\ 90 | mkdir -p artifacts/$(shell git describe --always) ;\ 91 | echo "
    " > artifacts/index.html ;\ 92 | for i in platforms/*/Makefile.inc ; do \ 93 | export DIRNAME=`dirname $$i` ;\ 94 | export PROBE_HOST=`basename $$DIRNAME` ;\ 95 | export CFLAGS=-Werror ;\ 96 | echo "Building for hardware platform: $$PROBE_HOST" ;\ 97 | $(MAKE) $(MAKEFLAGS) clean ;\ 98 | $(MAKE) $(MAKEFLAGS);\ 99 | if [ -f blackmagic.bin ]; then \ 100 | mv blackmagic.bin artifacts/blackmagic-$$PROBE_HOST.bin ;\ 101 | echo "
  • $$PROBE_HOST
  • "\ 102 | >> artifacts/index.html ;\ 103 | fi ;\ 104 | done ;\ 105 | echo "
" >> artifacts/index.html ;\ 106 | cp artifacts/*.bin artifacts/$(shell git describe --always) 107 | 108 | 109 | include/version.h: FORCE 110 | $(Q)echo " GIT include/version.h" 111 | $(Q)echo "#define FIRMWARE_VERSION \"`git describe --always --dirty`\"" > $@ 112 | 113 | -include *.d 114 | -------------------------------------------------------------------------------- /src/exception.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "general.h" 22 | #include "exception.h" 23 | 24 | struct exception *innermost_exception; 25 | 26 | void raise_exception(uint32_t type, const char *msg) 27 | { 28 | struct exception *e; 29 | DEBUG("Exception: %s\n", msg); 30 | for (e = innermost_exception; e; e = e->outer) { 31 | if (e->mask & type) { 32 | e->type = type; 33 | e->msg = msg; 34 | innermost_exception = e->outer; 35 | longjmp(e->jmpbuf, type); 36 | } 37 | } 38 | abort(); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/gdb_hostio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "general.h" 22 | #include "target.h" 23 | #include "gdb_main.h" 24 | #include "gdb_hostio.h" 25 | #include "gdb_packet.h" 26 | 27 | int gdb_main_loop(struct target_controller *, bool in_syscall); 28 | 29 | int hostio_reply(struct target_controller *tc, char *pbuf, int len) 30 | { 31 | (void)len; 32 | int retcode, items, errno_; 33 | char c, *p; 34 | if (pbuf[1] == '-') 35 | p = &pbuf[2]; 36 | else 37 | p = &pbuf[1]; 38 | items = sscanf(p, "%x,%x,%c", &retcode, &errno_, &c); 39 | if (pbuf[1] == '-') 40 | retcode = -retcode; 41 | 42 | /* if break is requested */ 43 | tc->interrupted = items == 3 && c == 'C'; 44 | tc->errno_ = errno_; 45 | 46 | return retcode; 47 | } 48 | 49 | /* Interface to host system calls */ 50 | int hostio_open(struct target_controller *tc, 51 | target_addr path, size_t path_len, 52 | enum target_open_flags flags, mode_t mode) 53 | { 54 | gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", path, path_len, flags, mode);;;; 55 | return gdb_main_loop(tc, true); 56 | } 57 | 58 | int hostio_close(struct target_controller *tc, int fd) 59 | { 60 | gdb_putpacket_f("Fclose,%08X", fd); 61 | return gdb_main_loop(tc, true); 62 | } 63 | 64 | int hostio_read(struct target_controller *tc, 65 | int fd, target_addr buf, unsigned int count) 66 | { 67 | gdb_putpacket_f("Fread,%08X,%08X,%08X", fd, buf, count); 68 | return gdb_main_loop(tc, true); 69 | } 70 | 71 | int hostio_write(struct target_controller *tc, 72 | int fd, target_addr buf, unsigned int count) 73 | { 74 | gdb_putpacket_f("Fwrite,%08X,%08X,%08X", fd, buf, count); 75 | return gdb_main_loop(tc, true); 76 | } 77 | 78 | long hostio_lseek(struct target_controller *tc, 79 | int fd, long offset, enum target_seek_flag flag) 80 | { 81 | gdb_putpacket_f("Flseek,%08X,%08X,%08X", fd, offset, flag); 82 | return gdb_main_loop(tc, true); 83 | } 84 | 85 | int hostio_rename(struct target_controller *tc, 86 | target_addr oldpath, size_t old_len, 87 | target_addr newpath, size_t new_len) 88 | { 89 | gdb_putpacket_f("Frename,%08X/%X,%08X/%X", 90 | oldpath, old_len, newpath, new_len); 91 | return gdb_main_loop(tc, true); 92 | } 93 | 94 | int hostio_unlink(struct target_controller *tc, 95 | target_addr path, size_t path_len) 96 | { 97 | gdb_putpacket_f("Funlink,%08X/%X", path, path_len); 98 | return gdb_main_loop(tc, true); 99 | } 100 | 101 | int hostio_stat(struct target_controller *tc, 102 | target_addr path, size_t path_len, target_addr buf) 103 | { 104 | gdb_putpacket_f("Fstat,%08X/%X,%08X", path, path_len, buf); 105 | return gdb_main_loop(tc, true); 106 | } 107 | 108 | int hostio_fstat(struct target_controller *tc, int fd, target_addr buf) 109 | { 110 | gdb_putpacket_f("Ffstat,%X,%08X", fd, buf); 111 | return gdb_main_loop(tc, true); 112 | } 113 | 114 | int hostio_gettimeofday(struct target_controller *tc, 115 | target_addr tv, target_addr tz) 116 | { 117 | gdb_putpacket_f("Fgettimeofday,%08X,%08X", tv, tz); 118 | return gdb_main_loop(tc, true); 119 | } 120 | 121 | int hostio_isatty(struct target_controller *tc, int fd) 122 | { 123 | gdb_putpacket_f("Fisatty,%08X", fd); 124 | return gdb_main_loop(tc, true); 125 | } 126 | 127 | int hostio_system(struct target_controller *tc, 128 | target_addr cmd, size_t cmd_len) 129 | { 130 | gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len); 131 | return gdb_main_loop(tc, true); 132 | } 133 | 134 | -------------------------------------------------------------------------------- /src/gdb_hostio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __GDB_SYSCALLS_H 21 | #define __GDB_SYSCALLS_H 22 | 23 | #include "target.h" 24 | 25 | int hostio_reply(struct target_controller *tc, char *packet, int len); 26 | 27 | /* Interface to host system calls */ 28 | int hostio_open(struct target_controller *, 29 | target_addr path, size_t path_len, 30 | enum target_open_flags flags, mode_t mode); 31 | int hostio_close(struct target_controller *, int fd); 32 | int hostio_read(struct target_controller *, 33 | int fd, target_addr buf, unsigned int count); 34 | int hostio_write(struct target_controller *, 35 | int fd, target_addr buf, unsigned int count); 36 | long hostio_lseek(struct target_controller *, 37 | int fd, long offset, enum target_seek_flag flag); 38 | int hostio_rename(struct target_controller *, 39 | target_addr oldpath, size_t old_len, 40 | target_addr newpath, size_t new_len); 41 | int hostio_unlink(struct target_controller *, 42 | target_addr path, size_t path_len); 43 | int hostio_stat(struct target_controller *, 44 | target_addr path, size_t path_len, target_addr buf); 45 | int hostio_fstat(struct target_controller *, int fd, target_addr buf); 46 | int hostio_gettimeofday(struct target_controller *, 47 | target_addr tv, target_addr tz); 48 | int hostio_isatty(struct target_controller *, int fd); 49 | int hostio_system(struct target_controller *, 50 | target_addr cmd, size_t cmd_len); 51 | 52 | #endif 53 | 54 | -------------------------------------------------------------------------------- /src/gdb_packet.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the GDB Remote Serial Debugging protocol packet 22 | * reception and transmission as well as some convenience functions. 23 | */ 24 | 25 | #include "general.h" 26 | #include "gdb_if.h" 27 | #include "gdb_packet.h" 28 | #include "hex_utils.h" 29 | 30 | #include 31 | 32 | int gdb_getpacket(char *packet, int size) 33 | { 34 | unsigned char c; 35 | unsigned char csum; 36 | char recv_csum[3]; 37 | int i; 38 | 39 | while(1) { 40 | /* Wait for packet start */ 41 | while((packet[0] = gdb_if_getchar()) != '$') 42 | if(packet[0] == 0x04) return 1; 43 | 44 | i = 0; csum = 0; 45 | /* Capture packet data into buffer */ 46 | while((c = gdb_if_getchar()) != '#') { 47 | 48 | if(i == size) break; /* Oh shit */ 49 | 50 | if(c == '$') { /* Restart capture */ 51 | i = 0; 52 | csum = 0; 53 | continue; 54 | } 55 | if(c == '}') { /* escaped char */ 56 | c = gdb_if_getchar(); 57 | csum += c + '}'; 58 | packet[i++] = c ^ 0x20; 59 | continue; 60 | } 61 | csum += c; 62 | packet[i++] = c; 63 | } 64 | recv_csum[0] = gdb_if_getchar(); 65 | recv_csum[1] = gdb_if_getchar(); 66 | recv_csum[2] = 0; 67 | 68 | /* return packet if checksum matches */ 69 | if(csum == strtol(recv_csum, NULL, 16)) break; 70 | 71 | /* get here if checksum fails */ 72 | gdb_if_putchar('-', 1); /* send nack */ 73 | } 74 | gdb_if_putchar('+', 1); /* send ack */ 75 | packet[i] = 0; 76 | 77 | #ifdef DEBUG_GDBPACKET 78 | DEBUG("%s : ", __func__); 79 | for(int j = 0; j < i; j++) { 80 | c = packet[j]; 81 | if ((c >= 32) && (c < 127)) 82 | DEBUG("%c", c); 83 | else 84 | DEBUG("\\x%02X", c); 85 | } 86 | DEBUG("\n"); 87 | #endif 88 | return i; 89 | } 90 | 91 | void gdb_putpacket(const char *packet, int size) 92 | { 93 | int i; 94 | unsigned char csum; 95 | unsigned char c; 96 | char xmit_csum[3]; 97 | int tries = 0; 98 | 99 | do { 100 | #ifdef DEBUG_GDBPACKET 101 | DEBUG("%s : ", __func__); 102 | #endif 103 | csum = 0; 104 | gdb_if_putchar('$', 0); 105 | for(i = 0; i < size; i++) { 106 | c = packet[i]; 107 | #ifdef DEBUG_GDBPACKET 108 | if ((c >= 32) && (c < 127)) 109 | DEBUG("%c", c); 110 | else 111 | DEBUG("\\x%02X", c); 112 | #endif 113 | if((c == '$') || (c == '#') || (c == '}')) { 114 | gdb_if_putchar('}', 0); 115 | gdb_if_putchar(c ^ 0x20, 0); 116 | csum += '}' + (c ^ 0x20); 117 | } else { 118 | gdb_if_putchar(c, 0); 119 | csum += c; 120 | } 121 | } 122 | gdb_if_putchar('#', 0); 123 | sprintf(xmit_csum, "%02X", csum); 124 | gdb_if_putchar(xmit_csum[0], 0); 125 | gdb_if_putchar(xmit_csum[1], 1); 126 | #ifdef DEBUG_GDBPACKET 127 | DEBUG("\n"); 128 | #endif 129 | } while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); 130 | } 131 | 132 | void gdb_putpacket_f(const char *fmt, ...) 133 | { 134 | va_list ap; 135 | char *buf; 136 | int size; 137 | 138 | va_start(ap, fmt); 139 | size = vasprintf(&buf, fmt, ap); 140 | gdb_putpacket(buf, size); 141 | free(buf); 142 | va_end(ap); 143 | } 144 | 145 | void gdb_out(const char *buf) 146 | { 147 | char *hexdata; 148 | int i; 149 | 150 | hexdata = alloca((i = strlen(buf)*2 + 1) + 1); 151 | hexdata[0] = 'O'; 152 | hexify(hexdata+1, buf, strlen(buf)); 153 | gdb_putpacket(hexdata, i); 154 | } 155 | 156 | void gdb_voutf(const char *fmt, va_list ap) 157 | { 158 | char *buf; 159 | 160 | if (vasprintf(&buf, fmt, ap) < 0) 161 | return; 162 | gdb_out(buf); 163 | free(buf); 164 | } 165 | 166 | void gdb_outf(const char *fmt, ...) 167 | { 168 | va_list ap; 169 | 170 | va_start(ap, fmt); 171 | gdb_voutf(fmt, ap); 172 | va_end(ap); 173 | } 174 | -------------------------------------------------------------------------------- /src/hex_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* Convenience function to convert to/from ascii strings of hex digits. 22 | */ 23 | 24 | #include "general.h" 25 | #include "hex_utils.h" 26 | 27 | static const char hexdigits[] = "0123456789abcdef"; 28 | 29 | char * hexify(char *hex, const void *buf, size_t size) 30 | { 31 | char *tmp = hex; 32 | const uint8_t *b = buf; 33 | 34 | while (size--) { 35 | *tmp++ = hexdigits[*b >> 4]; 36 | *tmp++ = hexdigits[*b++ & 0xF]; 37 | } 38 | *tmp++ = 0; 39 | 40 | return hex; 41 | } 42 | 43 | static uint8_t unhex_digit(char hex) 44 | { 45 | uint8_t tmp = hex - '0'; 46 | if(tmp > 9) 47 | tmp -= 'A' - '0' - 10; 48 | if(tmp > 16) 49 | tmp -= 'a' - 'A'; 50 | return tmp; 51 | } 52 | 53 | char * unhexify(void *buf, const char *hex, size_t size) 54 | { 55 | uint8_t *b = buf; 56 | while (size--) { 57 | *b = unhex_digit(*hex++) << 4; 58 | *b++ |= unhex_digit(*hex++); 59 | } 60 | return buf; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /src/include/command.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __COMMAND_H 22 | #define __COMMAND_H 23 | 24 | #include "target.h" 25 | 26 | int command_process(target *t, char *cmd); 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /src/include/crc32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __CRC32_H 22 | #define __CRC32_H 23 | 24 | uint32_t generic_crc32(target *t, uint32_t base, int len); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/include/exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* Exception handling to escape deep nesting. 22 | * Used for the case of communicaiton failure and timeouts. 23 | */ 24 | 25 | /* Example usage: 26 | * 27 | * volatile struct exception e; 28 | * TRY_CATCH (e, EXCEPTION_TIMEOUT) { 29 | * ... 30 | * raise_exception(EXCEPTION_TIMEOUT, "Timeout occurred"); 31 | * ... 32 | * } 33 | * if (e.type == EXCEPTION_TIMEOUT) { 34 | * printf("timeout: %s\n", e.msg); 35 | * } 36 | */ 37 | 38 | /* Limitations: 39 | * Can't use break, return, goto, etc from inside the TRY_CATCH block. 40 | */ 41 | 42 | #ifndef __EXCEPTION_H 43 | #define __EXCEPTION_H 44 | 45 | #include 46 | #include 47 | 48 | #define EXCEPTION_ERROR 0x01 49 | #define EXCEPTION_TIMEOUT 0x02 50 | #define EXCEPTION_ALL -1 51 | 52 | struct exception { 53 | uint32_t type; 54 | const char *msg; 55 | /* private */ 56 | uint32_t mask; 57 | jmp_buf jmpbuf; 58 | struct exception *outer; 59 | }; 60 | 61 | extern struct exception *innermost_exception; 62 | 63 | #define TRY_CATCH(e, type_mask) \ 64 | (e).type = 0; \ 65 | (e).mask = (type_mask); \ 66 | (e).outer = innermost_exception; \ 67 | innermost_exception = (void*)&(e); \ 68 | if (setjmp(innermost_exception->jmpbuf) == 0) \ 69 | for (;innermost_exception == &(e); innermost_exception = (e).outer) 70 | 71 | void raise_exception(uint32_t type, const char *msg); 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /src/include/gdb_if.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __GDB_IF_H 22 | #define __GDB_IF_H 23 | 24 | #if !defined(LIBFTDI) 25 | #include 26 | void gdb_usb_out_cb(usbd_device *dev, uint8_t ep); 27 | #endif 28 | 29 | int gdb_if_init(void); 30 | unsigned char gdb_if_getchar(void); 31 | unsigned char gdb_if_getchar_to(int timeout); 32 | void gdb_if_putchar(unsigned char c, int flush); 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /src/include/gdb_main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __GDB_MAIN_H 22 | #define __GDB_MAIN_H 23 | 24 | void gdb_main(void); 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /src/include/gdb_packet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __GDB_PACKET_H 22 | #define __GDB_PACKET_H 23 | 24 | #include 25 | 26 | int gdb_getpacket(char *packet, int size); 27 | void gdb_putpacket(const char *packet, int size); 28 | #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) 29 | void gdb_putpacket_f(const char *packet, ...); 30 | 31 | void gdb_out(const char *buf); 32 | void gdb_voutf(const char *fmt, va_list); 33 | void gdb_outf(const char *fmt, ...); 34 | 35 | #endif 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/include/general.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __GENERAL_H 22 | #define __GENERAL_H 23 | 24 | #define _GNU_SOURCE 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "platform.h" 34 | #include "platform_support.h" 35 | 36 | #ifndef DEBUG 37 | #include 38 | #define DEBUG printf 39 | #endif 40 | 41 | #define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1)) 42 | #undef MIN 43 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 44 | 45 | #endif 46 | 47 | -------------------------------------------------------------------------------- /src/include/hex_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __HEX_UTILS_H 22 | #define __HEX_UTILS_H 23 | 24 | char * hexify(char *hex, const void *buf, size_t size); 25 | char * unhexify(void *buf, const char *hex, size_t size); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/include/jtagtap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __JTAGTAP_H 22 | #define __JTAGTAP_H 23 | 24 | /* Note: Signal names are as for the device under test. */ 25 | 26 | int jtagtap_init(void); 27 | 28 | void jtagtap_reset(void); 29 | 30 | uint8_t jtagtap_next(const uint8_t TMS, const uint8_t TDI); 31 | /* tap_next executes one state transision in the JTAG TAP state machine: 32 | * - Ensure TCK is low 33 | * - Assert the values of TMS and TDI 34 | * - Assert TCK (TMS and TDO are latched on rising edge 35 | * - Caputure the value on TDO 36 | * - Release TCK. 37 | */ 38 | 39 | void jtagtap_tms_seq(uint32_t MS, int ticks); 40 | void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks); 41 | void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks); 42 | /* Shift out a sequence on MS and DI, capture data to DO. 43 | * - This is not endian safe: First byte will always be first shifted out. 44 | * - DO may be NULL to ignore captured data. 45 | * - DO may be point to the same address as DI. 46 | */ 47 | 48 | /* generic soft reset: 1, 1, 1, 1, 1, 0 */ 49 | #define jtagtap_soft_reset() \ 50 | jtagtap_tms_seq(0x1F, 6) 51 | 52 | /* Goto Shift-IR: 1, 1, 0, 0 */ 53 | #define jtagtap_shift_ir() \ 54 | jtagtap_tms_seq(0x03, 4) 55 | 56 | /* Goto Shift-DR: 1, 0, 0 */ 57 | #define jtagtap_shift_dr() \ 58 | jtagtap_tms_seq(0x01, 3) 59 | 60 | /* Goto Run-test/Idle: 1, 1, 0 */ 61 | #define jtagtap_return_idle() \ 62 | jtagtap_tms_seq(0x01, 2) 63 | 64 | #endif 65 | 66 | -------------------------------------------------------------------------------- /src/include/morse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __MORSE_H 22 | #define __MORSE_H 23 | 24 | extern const char *morse_msg; 25 | 26 | void morse(const char *msg, char repeat); 27 | bool morse_update(void); 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /src/include/platform_support.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef __PLATFORM_SUPPORT_H 21 | #define __PLATFORM_SUPPORT_H 22 | 23 | #ifndef __GENERAL_H 24 | # error "Include 'general.h' instead" 25 | #endif 26 | 27 | #if defined(LIBFTDI) 28 | void platform_init(int argc, char **argv); 29 | #else 30 | void platform_init(void); 31 | #endif 32 | 33 | typedef struct platform_timeout platform_timeout; 34 | void platform_timeout_set(platform_timeout *t, uint32_t ms); 35 | bool platform_timeout_is_expired(platform_timeout *t); 36 | void platform_delay(uint32_t ms); 37 | 38 | const char *platform_target_voltage(void); 39 | int platform_hwversion(void); 40 | void platform_srst_set_val(bool assert); 41 | bool platform_srst_get_val(void); 42 | bool platform_target_get_power(void); 43 | void platform_target_set_power(bool power); 44 | void platform_request_boot(void); 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /src/include/swdptap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __SWDPTAP_H 22 | #define __SWDPTAP_H 23 | 24 | int swdptap_init(void); 25 | 26 | /* Primitive functions */ 27 | bool swdptap_bit_in(void); 28 | void swdptap_bit_out(bool val); 29 | 30 | /* High level functions, provided as weak in swdptap_generic.c */ 31 | uint32_t swdptap_seq_in(int ticks); 32 | bool swdptap_seq_in_parity(uint32_t *data, int ticks); 33 | void swdptap_seq_out(uint32_t MS, int ticks); 34 | void swdptap_seq_out_parity(uint32_t MS, int ticks); 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* Provides main entry point. Initialise subsystems and enter GDB 22 | * protocol loop. 23 | */ 24 | 25 | #include "general.h" 26 | #include "gdb_if.h" 27 | #include "gdb_main.h" 28 | #include "target.h" 29 | #include "exception.h" 30 | #include "gdb_packet.h" 31 | #include "morse.h" 32 | 33 | int 34 | main(int argc, char **argv) 35 | { 36 | #if defined(LIBFTDI) 37 | platform_init(argc, argv); 38 | #else 39 | (void) argc; 40 | (void) argv; 41 | platform_init(); 42 | #endif 43 | 44 | while (true) { 45 | volatile struct exception e; 46 | TRY_CATCH(e, EXCEPTION_ALL) { 47 | gdb_main(); 48 | } 49 | if (e.type) { 50 | gdb_putpacketz("EFF"); 51 | target_list_free(); 52 | morse("TARGET LOST.", 1); 53 | } 54 | } 55 | 56 | /* Should never get here */ 57 | return 0; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/morse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "general.h" 21 | #include "morse.h" 22 | 23 | /* Morse code patterns and lengths */ 24 | static const struct { 25 | uint16_t code; 26 | uint8_t bits; 27 | } morse_letter[] = { 28 | { 0b00011101, 8}, // 'A' .- 29 | { 0b000101010111, 12}, // 'B' -... 30 | { 0b00010111010111, 14}, // 'C' -.-. 31 | { 0b0001010111, 10}, // 'D' -.. 32 | { 0b0001, 4}, // 'E' . 33 | { 0b000101110101, 12}, // 'F' ..-. 34 | { 0b000101110111, 12}, // 'G' --. 35 | { 0b0001010101, 10}, // 'H' .... 36 | { 0b000101, 6}, // 'I' .. 37 | {0b0001110111011101, 16}, // 'J' .--- 38 | { 0b000111010111, 12}, // 'K' -.- 39 | { 0b000101011101, 12}, // 'L' .-.. 40 | { 0b0001110111, 10}, // 'M' -- 41 | { 0b00010111, 8}, // 'N' -. 42 | { 0b00011101110111, 14}, // 'O' --- 43 | { 0b00010111011101, 14}, // 'P' .--. 44 | {0b0001110101110111, 16}, // 'Q' --.- 45 | { 0b0001011101, 10}, // 'R' .-. 46 | { 0b00010101, 8}, // 'S' ... 47 | { 0b000111, 6}, // 'T' - 48 | { 0b0001110101, 10}, // 'U' ..- 49 | { 0b000111010101, 12}, // 'V' ...- 50 | { 0b000111011101, 12}, // 'W' .-- 51 | { 0b00011101010111, 14}, // 'X' -..- 52 | {0b0001110111010111, 16}, // 'Y' -.-- 53 | { 0b00010101110111, 14}, // 'Z' --.. 54 | }; 55 | 56 | const char *morse_msg; 57 | static const char * volatile morse_ptr; 58 | static char morse_repeat; 59 | 60 | void morse(const char *msg, char repeat) 61 | { 62 | morse_msg = morse_ptr = msg; 63 | morse_repeat = repeat; 64 | } 65 | 66 | bool morse_update(void) 67 | { 68 | static uint16_t code; 69 | static uint8_t bits; 70 | 71 | if (!morse_ptr) 72 | return false; 73 | 74 | if (!bits) { 75 | char c = *morse_ptr++; 76 | if (!c) { 77 | if(morse_repeat) { 78 | morse_ptr = morse_msg; 79 | c = *morse_ptr++; 80 | } else { 81 | morse_ptr = 0; 82 | return false; 83 | } 84 | } 85 | if ((c >= 'A') && (c <= 'Z')) { 86 | c -= 'A'; 87 | code = morse_letter[c].code; 88 | bits = morse_letter[c].bits; 89 | } else { 90 | code = 0; bits = 4; 91 | } 92 | } 93 | 94 | bool ret = code & 1; 95 | code >>= 1; 96 | bits--; 97 | 98 | return ret; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/platforms/common/cdcacm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements a the USB Communications Device Class - Abstract 22 | * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. 23 | * A Device Firmware Upgrade (DFU 1.1) class interface is provided for 24 | * field firmware upgrade. 25 | * 26 | * The device's unique id is used as the USB serial number string. 27 | */ 28 | #ifndef __CDCACM_H 29 | #define __CDCACM_H 30 | 31 | #include 32 | 33 | #define CDCACM_PACKET_SIZE 64 34 | 35 | #define CDCACM_GDB_ENDPOINT 1 36 | #define CDCACM_UART_ENDPOINT 3 37 | 38 | extern usbd_device *usbdev; 39 | 40 | void cdcacm_init(void); 41 | /* Returns current usb configuration, or 0 if not configured. */ 42 | int cdcacm_get_config(void); 43 | int cdcacm_get_dtr(void); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/platforms/common/serialno.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __SERIALNO_H 21 | #define __SERIALNO_H 22 | 23 | char *serialno_read(char *s); 24 | 25 | #endif 26 | 27 | -------------------------------------------------------------------------------- /src/platforms/common/swdptap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the low-level SW-DP interface. */ 22 | 23 | #include "general.h" 24 | #include "swdptap.h" 25 | 26 | int swdptap_init(void) 27 | { 28 | return 0; 29 | } 30 | 31 | static void swdptap_turnaround(uint8_t dir) 32 | { 33 | static uint8_t olddir = 0; 34 | 35 | /* Don't turnaround if direction not changing */ 36 | if(dir == olddir) return; 37 | olddir = dir; 38 | 39 | #ifdef DEBUG_SWD_BITS 40 | DEBUG("%s", dir ? "\n-> ":"\n<- "); 41 | #endif 42 | 43 | if(dir) 44 | SWDIO_MODE_FLOAT(); 45 | gpio_set(SWCLK_PORT, SWCLK_PIN); 46 | gpio_clear(SWCLK_PORT, SWCLK_PIN); 47 | if(!dir) 48 | SWDIO_MODE_DRIVE(); 49 | } 50 | 51 | bool swdptap_bit_in(void) 52 | { 53 | uint16_t ret; 54 | 55 | swdptap_turnaround(1); 56 | 57 | ret = gpio_get(SWDIO_PORT, SWDIO_PIN); 58 | gpio_set(SWCLK_PORT, SWCLK_PIN); 59 | gpio_clear(SWCLK_PORT, SWCLK_PIN); 60 | 61 | #ifdef DEBUG_SWD_BITS 62 | DEBUG("%d", ret?1:0); 63 | #endif 64 | 65 | return ret != 0; 66 | } 67 | 68 | void swdptap_bit_out(bool val) 69 | { 70 | #ifdef DEBUG_SWD_BITS 71 | DEBUG("%d", val); 72 | #endif 73 | 74 | swdptap_turnaround(0); 75 | 76 | gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); 77 | gpio_set(SWCLK_PORT, SWCLK_PIN); 78 | gpio_clear(SWCLK_PORT, SWCLK_PIN); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/platforms/common/timing.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "general.h" 21 | 22 | void platform_timeout_set(platform_timeout *t, uint32_t ms) 23 | { 24 | t->time = platform_time_ms() + ms; 25 | } 26 | 27 | bool platform_timeout_is_expired(platform_timeout *t) 28 | { 29 | return platform_time_ms() > t->time; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/platforms/common/timing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __TIMING_H 21 | #define __TIMING_H 22 | 23 | struct platform_timeout { 24 | uint32_t time; 25 | }; 26 | 27 | uint32_t platform_time_ms(void); 28 | 29 | #endif /* __TIMING_H */ 30 | 31 | -------------------------------------------------------------------------------- /src/platforms/common/traceswo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2012 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __TRACESWO_H 21 | #define __TRACESWO_H 22 | 23 | #include 24 | 25 | void traceswo_init(void); 26 | void trace_buf_drain(usbd_device *dev, uint8_t ep); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/platforms/common/usbuart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2012 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __USBUART_H 21 | #define __USBUART_H 22 | 23 | #include 24 | #include 25 | 26 | void usbuart_init(void); 27 | 28 | void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); 29 | void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); 30 | void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/platforms/f4discovery/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ 6 | -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ 7 | -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \ 8 | -Iplatforms/stm32 9 | 10 | LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \ 11 | -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ 12 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ 13 | -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ 14 | -L../libopencm3/lib 15 | 16 | VPATH += platforms/stm32 17 | 18 | SRC += cdcacm.c \ 19 | traceswo.c \ 20 | usbuart.c \ 21 | serialno.c \ 22 | timing.c \ 23 | timing_stm32.c \ 24 | 25 | all: blackmagic.bin 26 | 27 | host_clean: 28 | -$(Q)$(RM) blackmagic.bin 29 | -------------------------------------------------------------------------------- /src/platforms/f4discovery/Readme: -------------------------------------------------------------------------------- 1 | System vs BMP Bootloader 2 | ======================== 3 | For the BMP bootloader, flashing qas not reliable. So we use the system 4 | bootloder unconditional. 5 | 6 | Connections: 7 | ==================== 8 | 9 | PA0: User button to force system bootloader entry with reset 10 | PA2/PA3 eventual connected to the STLINK/ STM32F103C8 11 | 12 | PC2: TDI 13 | PC4: TMS/SWDIO 14 | PC5: TCK/SWCLK 15 | PC6: TDO/TRACESWO 16 | 17 | PC1: TRST 18 | PC8: SRST 19 | 20 | Blue Led: Indicator that system bootloader is entered via BMP 21 | 22 | Bootstrapping the F4Discovery on-board ST-Link 23 | ============================================== 24 | http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe has some hints 25 | how to modify the F4Discovery on-board ST-Link. If you try to do so and hit 26 | a problem that stands some test like that you load the right firmware to the 27 | right device via the right BMP probe, explain, report and ask on the 28 | blackmagic mailing list http://sourceforge.net/mail/?group_id=407419. 29 | -------------------------------------------------------------------------------- /src/platforms/f4discovery/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the platform specific functions for the STM32 22 | * implementation. 23 | */ 24 | 25 | #include "general.h" 26 | #include "cdcacm.h" 27 | #include "usbuart.h" 28 | #include "morse.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | jmp_buf fatal_error_jmpbuf; 39 | 40 | void platform_init(void) 41 | { 42 | /* Check the USER button*/ 43 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 44 | if(gpio_get(GPIOA, GPIO0)) { 45 | platform_request_boot(); 46 | scb_reset_core(); 47 | } 48 | 49 | rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]); 50 | 51 | /* Enable peripherals */ 52 | rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); 53 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); 54 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 55 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_CRCEN); 56 | 57 | /* Set up USB Pins and alternate function*/ 58 | gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, 59 | GPIO9 | GPIO11 | GPIO12); 60 | gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); 61 | 62 | GPIOC_OSPEEDR &=~0xF30; 63 | GPIOC_OSPEEDR |= 0xA20; 64 | gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, 65 | GPIO_PUPD_NONE, 66 | TMS_PIN | TCK_PIN | TDI_PIN); 67 | 68 | gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, 69 | GPIO_PUPD_NONE, 70 | TDO_PIN); 71 | 72 | gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, 73 | GPIO_PUPD_NONE, 74 | LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); 75 | 76 | platform_timing_init(); 77 | usbuart_init(); 78 | cdcacm_init(); 79 | } 80 | 81 | void platform_srst_set_val(bool assert) { (void)assert; } 82 | bool platform_srst_get_val(void) { return false; } 83 | 84 | const char *platform_target_voltage(void) 85 | { 86 | return "ABSENT!"; 87 | } 88 | 89 | void platform_request_boot(void) 90 | { 91 | /* Disconnect USB cable */ 92 | usbd_disconnect(usbdev, 1); 93 | nvic_disable_irq(USB_IRQ); 94 | 95 | /* Assert blue LED as indicator we are in the bootloader */ 96 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 97 | gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, 98 | GPIO_PUPD_NONE, LED_BOOTLOADER); 99 | gpio_set(LED_PORT, LED_BOOTLOADER); 100 | 101 | /* Jump to the built in bootloader by mapping System flash */ 102 | rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN); 103 | SYSCFG_MEMRM &= ~3; 104 | SYSCFG_MEMRM |= 1; 105 | } 106 | -------------------------------------------------------------------------------- /src/platforms/f4discovery/usbdfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "general.h" 21 | #include "usbdfu.h" 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | void dfu_detach(void) 29 | { 30 | /* USB device must detach, we just reset... */ 31 | scb_reset_system(); 32 | } 33 | 34 | int main(void) 35 | { 36 | /* Check the force bootloader pin*/ 37 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 38 | if(!gpio_get(GPIOA, GPIO0)) 39 | dfu_jump_app_if_valid(); 40 | 41 | dfu_protect_enable(); 42 | 43 | /* Set up clock*/ 44 | rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); 45 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 46 | systick_set_reload(2100000); 47 | 48 | systick_interrupt_enable(); 49 | systick_counter_enable(); 50 | 51 | /* Handle LEDs */ 52 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 53 | gpio_clear(GPIOD, GPIO12 | GPIO13 | GPIO14 |GPIO15); 54 | gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 55 | GPIO12 | GPIO13 | GPIO14 |GPIO15); 56 | 57 | /* Set up USB*/ 58 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 59 | rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); 60 | 61 | /* Set up USB Pins and alternate function*/ 62 | gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, 63 | GPIO9 | GPIO10 | GPIO11 | GPIO12); 64 | gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10| GPIO11 | GPIO12); 65 | dfu_init(&stm32f107_usb_driver); 66 | 67 | dfu_main(); 68 | } 69 | 70 | 71 | void sys_tick_handler(void) 72 | { 73 | gpio_toggle(GPIOD, GPIO12); /* Green LED on/off */ 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/platforms/hydrabus/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ 6 | -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ 7 | -DSTM32F4 -DHYDRABUS -I../libopencm3/include \ 8 | -Iplatforms/stm32 9 | 10 | LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \ 11 | -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ 12 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ 13 | -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ 14 | -L../libopencm3/lib 15 | 16 | VPATH += platforms/stm32 17 | 18 | SRC += cdcacm.c \ 19 | traceswo.c \ 20 | usbuart.c \ 21 | serialno.c \ 22 | timing.c \ 23 | timing_stm32.c \ 24 | 25 | all: blackmagic.bin blackmagic.hex blackmagic.dfu 26 | 27 | blackmagic.dfu: blackmagic.hex 28 | @echo Creating $@ 29 | @python ../scripts/dfu-convert.py -i $< $@ 30 | 31 | host_clean: 32 | -$(Q)$(RM) blackmagic.bin blackmagic.hex blackmagic.dfu 33 | -------------------------------------------------------------------------------- /src/platforms/hydrabus/Readme.md: -------------------------------------------------------------------------------- 1 | Connections 2 | ==================== 3 | * PA0: User button to force system bootloader entry with reset (enter USB DFU) 4 | 5 | * JTAG/SWD 6 | * PC0: TMS/SWDIO 7 | * PC1: TCK/SWCLK 8 | * PC2: TDI 9 | * PC3: TDO/TRACESWO 10 | * PC4: SRST (NRST/System Reset) 11 | * PC5: TRST (optional Test Reset) 12 | 13 | * Green Led(ULED/PA4): Indicator that system bootloader is entered via BMP 14 | 15 | * USB USART 16 | * PA9: USART1 TX (usbuart_xxx) 17 | * PA10: USART1 RX (usbuart_xxx) 18 | 19 | How to Build 20 | ============ 21 | ``` 22 | cd blackmagic 23 | make clean 24 | make PROBE_HOST=hydrabus 25 | ``` 26 | 27 | How to Flash the firmware with Windows 28 | ======================================== 29 | * After build: 30 | * 1) Download files from https://github.com/bvernoux/hydrafw/tree/master/update_fw_dfu_usb_hydrafw 31 | * 2) Force the F4 into system bootloader mode by jumpering "BOOT0" to "3V3" and "PB2/BOOT1" to "GND" and reset (RESET button). System bootloader should appear. 32 | * 3) Run the command `DfuSeCommand.exe -c --de 0 -d --fn .\src\blackmagic.dfu` 33 | 34 | -------------------------------------------------------------------------------- /src/platforms/hydrabus/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the platform specific functions for the STM32 22 | * implementation. 23 | */ 24 | 25 | #include "general.h" 26 | #include "cdcacm.h" 27 | #include "usbuart.h" 28 | #include "morse.h" 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | jmp_buf fatal_error_jmpbuf; 39 | 40 | void platform_init(void) 41 | { 42 | /* Check the USER button*/ 43 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 44 | if(gpio_get(GPIOA, GPIO0)) { 45 | platform_request_boot(); 46 | scb_reset_core(); 47 | } 48 | 49 | rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]); 50 | 51 | /* Enable peripherals */ 52 | rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); 53 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); 54 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 55 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_CRCEN); 56 | 57 | /* Set up USB Pins and alternate function*/ 58 | gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, 59 | GPIO9 | GPIO11 | GPIO12); 60 | gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); 61 | 62 | GPIOC_OSPEEDR &=~0xF30; 63 | GPIOC_OSPEEDR |= 0xA20; 64 | gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, 65 | GPIO_PUPD_NONE, 66 | TMS_PIN | TCK_PIN | TDI_PIN); 67 | 68 | gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, 69 | GPIO_PUPD_NONE, 70 | TDO_PIN); 71 | 72 | gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, 73 | GPIO_PUPD_NONE, 74 | LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); 75 | 76 | platform_timing_init(); 77 | usbuart_init(); 78 | cdcacm_init(); 79 | } 80 | 81 | void platform_srst_set_val(bool assert) { (void)assert; } 82 | bool platform_srst_get_val(void) { return false; } 83 | 84 | const char *platform_target_voltage(void) 85 | { 86 | return "ABSENT!"; 87 | } 88 | 89 | void platform_request_boot(void) 90 | { 91 | /* Disconnect USB cable */ 92 | usbd_disconnect(usbdev, 1); 93 | nvic_disable_irq(USB_IRQ); 94 | 95 | /* Assert blue LED as indicator we are in the bootloader */ 96 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 97 | gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, 98 | GPIO_PUPD_NONE, LED_BOOTLOADER); 99 | gpio_set(LED_PORT, LED_BOOTLOADER); 100 | 101 | /* Jump to the built in bootloader by mapping System flash */ 102 | rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN); 103 | SYSCFG_MEMRM &= ~3; 104 | SYSCFG_MEMRM |= 1; 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/platforms/hydrabus/usbdfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * Copyright (C) 2015 Benjamin Vernoux 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "general.h" 22 | #include "usbdfu.h" 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | void dfu_detach(void) 30 | { 31 | /* USB device must detach, we just reset... */ 32 | scb_reset_system(); 33 | } 34 | 35 | int main(void) 36 | { 37 | /* Check the force bootloader pin*/ 38 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 39 | if(!gpio_get(GPIOA, GPIO0)) 40 | dfu_jump_app_if_valid(); 41 | 42 | dfu_protect_enable(); 43 | 44 | /* Set up clock*/ 45 | rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); 46 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 47 | systick_set_reload(2100000); 48 | 49 | systick_interrupt_enable(); 50 | systick_counter_enable(); 51 | 52 | /* Handle LED */ 53 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); 54 | gpio_clear(GPIOA, GPIO4); 55 | gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, 56 | GPIO4); 57 | 58 | /* Set up USB*/ 59 | rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); 60 | rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); 61 | 62 | /* Set up USB Pins and alternate function*/ 63 | gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, 64 | GPIO9 | GPIO10 | GPIO11 | GPIO12); 65 | gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10| GPIO11 | GPIO12); 66 | dfu_init(&stm32f107_usb_driver); 67 | 68 | dfu_main(); 69 | } 70 | 71 | 72 | void sys_tick_handler(void) 73 | { 74 | gpio_toggle(GPIOA, GPIO4); /* Green LED on/off */ 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/platforms/launchpad-icdi/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | INCLUDES = -I../libopencm3/include 6 | 7 | CPU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard 8 | CFLAGS += $(INCLUDES) $(CPU_FLAGS) -DTARGET_IS_BLIZZARD_RB1 -DLM4F -DPART_TM4C123GH6PM 9 | 10 | LINKER_SCRIPT="platforms/tm4c/tm4c.ld" 11 | LDFLAGS = -nostartfiles -lc $(CPU_FLAGS) -nodefaultlibs -T$(LINKER_SCRIPT) -Wl,--gc-sections \ 12 | -L../libopencm3/lib -lopencm3_lm4f -lnosys -lm -lgcc 13 | 14 | VPATH += platforms/tm4c 15 | 16 | SRC += cdcacm.c \ 17 | usbuart.c \ 18 | timing.c \ 19 | traceswo.o 20 | 21 | all: blackmagic.bin 22 | 23 | -------------------------------------------------------------------------------- /src/platforms/launchpad-icdi/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #include "general.h" 18 | #include "gdb_if.h" 19 | #include "cdcacm.h" 20 | #include "usbuart.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define SYSTICKHZ 100 29 | #define SYSTICKMS (1000 / SYSTICKHZ) 30 | 31 | #define PLL_DIV_80MHZ 5 32 | #define PLL_DIV_25MHZ 16 33 | 34 | extern void trace_tick(void); 35 | 36 | volatile platform_timeout * volatile head_timeout; 37 | uint8_t running_status; 38 | static volatile uint32_t time_ms; 39 | 40 | void sys_tick_handler(void) 41 | { 42 | trace_tick(); 43 | time_ms += 10; 44 | } 45 | 46 | uint32_t platform_time_ms(void) 47 | { 48 | return time_ms; 49 | } 50 | 51 | void 52 | platform_init(void) 53 | { 54 | int i; 55 | for(i=0; i<1000000; i++); 56 | 57 | rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLL_DIV_80MHZ); 58 | 59 | // Enable all JTAG ports and set pins to output 60 | periph_clock_enable(RCC_GPIOA); 61 | periph_clock_enable(RCC_GPIOB); 62 | 63 | gpio_enable_ahb_aperture(); 64 | 65 | gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); 66 | gpio_mode_setup(TCK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TCK_PIN); 67 | gpio_mode_setup(TDI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TDI_PIN); 68 | gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TDO_PIN); 69 | gpio_mode_setup(SRST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SRST_PIN); 70 | gpio_set_output_config(SRST_PORT, GPIO_OTYPE_OD, GPIO_DRIVE_2MA, SRST_PIN); 71 | gpio_set(SRST_PORT, SRST_PIN); 72 | 73 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 74 | systick_set_reload(rcc_get_system_clock_frequency() / (SYSTICKHZ * 8)); 75 | 76 | systick_interrupt_enable(); 77 | systick_counter_enable(); 78 | 79 | nvic_enable_irq(NVIC_SYSTICK_IRQ); 80 | nvic_enable_irq(NVIC_UART0_IRQ); 81 | 82 | periph_clock_enable(RCC_GPIOD); 83 | __asm__("nop"); __asm__("nop"); __asm__("nop"); 84 | gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); 85 | usbuart_init(); 86 | cdcacm_init(); 87 | 88 | usb_enable_interrupts(USB_INT_RESET | USB_INT_DISCON | 89 | USB_INT_RESUME | USB_INT_SUSPEND, 90 | 0xff, 0xff); 91 | } 92 | 93 | void platform_srst_set_val(bool assert) 94 | { 95 | volatile int i; 96 | if (assert) { 97 | gpio_clear(SRST_PORT, SRST_PIN); 98 | for(i = 0; i < 10000; i++) asm("nop"); 99 | } else { 100 | gpio_set(SRST_PORT, SRST_PIN); 101 | } 102 | } 103 | 104 | bool platform_srst_get_val(void) 105 | { 106 | return gpio_get(SRST_PORT, SRST_PIN) == 0; 107 | } 108 | 109 | void platform_delay(uint32_t ms) 110 | { 111 | platform_timeout timeout; 112 | platform_timeout_set(&timeout, ms); 113 | while (!platform_timeout_is_expired(&timeout)); 114 | } 115 | 116 | const char *platform_target_voltage(void) 117 | { 118 | return "not supported"; 119 | } 120 | 121 | char *serialno_read(char *s) 122 | { 123 | /* FIXME: Store a unique serial number somewhere and retreive here */ 124 | uint32_t unique_id = 1; 125 | int i; 126 | 127 | /* Fetch serial number from chip's unique ID */ 128 | for(i = 0; i < 8; i++) { 129 | s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; 130 | } 131 | for(i = 0; i < 8; i++) 132 | if(s[i] > '9') 133 | s[i] += 'A' - '9' - 1; 134 | s[8] = 0; 135 | 136 | return s; 137 | } 138 | 139 | void platform_request_boot(void) 140 | { 141 | } 142 | 143 | -------------------------------------------------------------------------------- /src/platforms/launchpad-icdi/platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | #ifndef __PLATFORM_H 18 | #define __PLATFORM_H 19 | 20 | #include 21 | #include 22 | 23 | #include "timing.h" 24 | #include "version.h" 25 | 26 | #define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware " FIRMWARE_VERSION ")" 27 | #define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware " FIRMWARE_VERSION ")" 28 | #define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" 29 | #define DFU_IFACE_STRING "lolwut" 30 | 31 | extern uint8_t running_status; 32 | 33 | #define TMS_PORT GPIOA_BASE 34 | #define TMS_PIN GPIO3 35 | 36 | #define TCK_PORT GPIOA_BASE 37 | #define TCK_PIN GPIO2 38 | 39 | #define TDI_PORT GPIOA_BASE 40 | #define TDI_PIN GPIO5 41 | 42 | #define TDO_PORT GPIOA_BASE 43 | #define TDO_PIN GPIO4 44 | 45 | #define SWO_PORT GPIOD_BASE 46 | #define SWO_PIN GPIO6 47 | 48 | #define SWDIO_PORT TMS_PORT 49 | #define SWDIO_PIN TMS_PIN 50 | 51 | #define SWCLK_PORT TCK_PORT 52 | #define SWCLK_PIN TCK_PIN 53 | 54 | #define SRST_PORT GPIOA_BASE 55 | #define SRST_PIN GPIO6 56 | 57 | #define TMS_SET_MODE() { \ 58 | gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); \ 59 | gpio_set_output_config(TMS_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, TMS_PIN); \ 60 | } 61 | 62 | #define SWDIO_MODE_FLOAT() { \ 63 | gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWDIO_PIN); \ 64 | } 65 | 66 | #define SWDIO_MODE_DRIVE() { \ 67 | gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SWDIO_PIN); \ 68 | gpio_set_output_config(SWDIO_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, SWDIO_PIN); \ 69 | } 70 | 71 | extern usbd_driver lm4f_usb_driver; 72 | #define USB_DRIVER lm4f_usb_driver 73 | #define USB_IRQ NVIC_USB0_IRQ 74 | #define USB_ISR usb0_isr 75 | 76 | #define IRQ_PRI_USB (2 << 4) 77 | 78 | #define USBUART UART0 79 | #define USBUART_CLK RCC_UART0 80 | #define USBUART_IRQ NVIC_UART0_IRQ 81 | #define USBUART_ISR uart0_isr 82 | #define UART_PIN_SETUP() do { \ 83 | periph_clock_enable(RCC_GPIOA); \ 84 | __asm__("nop"); __asm__("nop"); __asm__("nop"); \ 85 | gpio_set_af(GPIOA_BASE, 0x1, GPIO0 | GPIO1); \ 86 | gpio_mode_setup(GPIOA_BASE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO0); \ 87 | gpio_mode_setup(GPIOA_BASE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); \ 88 | } while (0) 89 | 90 | #define TRACEUART UART2 91 | #define TRACEUART_CLK RCC_UART2 92 | #define TRACEUART_IRQ NVIC_UART2_IRQ 93 | #define TRACEUART_ISR uart2_isr 94 | 95 | /* Use newlib provided integer only stdio functions */ 96 | #define sscanf siscanf 97 | #define sprintf siprintf 98 | #define vasprintf vasiprintf 99 | #define snprintf sniprintf 100 | 101 | #define DEBUG(...) 102 | 103 | #define SET_RUN_STATE(state) {running_status = (state);} 104 | #define SET_IDLE_STATE(state) {} 105 | #define SET_ERROR_STATE(state) SET_IDLE_STATE(state) 106 | 107 | #define PLATFORM_HAS_TRACESWO 108 | 109 | inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { 110 | gpio_write(port, pin, val == 0 ? 0 : 0xff); 111 | } 112 | 113 | inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { 114 | return !(gpio_read(port, pin) == 0); 115 | } 116 | 117 | #define disconnect_usb() do { usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) 118 | 119 | static inline int platform_hwversion(void) 120 | { 121 | return 0; 122 | } 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /src/platforms/libftdi/Makefile.inc: -------------------------------------------------------------------------------- 1 | CFLAGS += -DLIBFTDI 2 | LDFLAGS += -lftdi -lusb 3 | 4 | SRC += timing.c \ 5 | -------------------------------------------------------------------------------- /src/platforms/libftdi/gdb_if.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements a transparent channel over which the GDB Remote 22 | * Serial Debugging protocol is implemented. This implementation for Linux 23 | * uses a TCP server on port 2000. 24 | */ 25 | #include 26 | 27 | #ifndef WIN32 28 | # include 29 | # include 30 | # include 31 | # include 32 | #else 33 | # include 34 | # include 35 | # include 36 | #endif 37 | 38 | #include 39 | 40 | #include "general.h" 41 | #include "gdb_if.h" 42 | 43 | static int gdb_if_serv, gdb_if_conn; 44 | 45 | int gdb_if_init(void) 46 | { 47 | #ifdef WIN32 48 | WSADATA wsaData; 49 | WSAStartup(MAKEWORD(2, 2), &wsaData); 50 | #endif 51 | struct sockaddr_in addr; 52 | int opt; 53 | 54 | addr.sin_family = AF_INET; 55 | addr.sin_port = htons(2000); 56 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 57 | 58 | assert((gdb_if_serv = socket(PF_INET, SOCK_STREAM, 0)) != -1); 59 | opt = 1; 60 | assert(setsockopt(gdb_if_serv, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) != -1); 61 | assert(setsockopt(gdb_if_serv, IPPROTO_TCP, TCP_NODELAY, (void*)&opt, sizeof(opt)) != -1); 62 | 63 | assert(bind(gdb_if_serv, (void*)&addr, sizeof(addr)) != -1); 64 | assert(listen(gdb_if_serv, 1) != -1); 65 | 66 | DEBUG("Listening on TCP:2000\n"); 67 | 68 | return 0; 69 | } 70 | 71 | 72 | unsigned char gdb_if_getchar(void) 73 | { 74 | unsigned char ret; 75 | int i = 0; 76 | 77 | while(i <= 0) { 78 | if(gdb_if_conn <= 0) { 79 | gdb_if_conn = accept(gdb_if_serv, NULL, NULL); 80 | DEBUG("Got connection\n"); 81 | } 82 | i = recv(gdb_if_conn, (void*)&ret, 1, 0); 83 | if(i <= 0) { 84 | gdb_if_conn = -1; 85 | DEBUG("Dropped broken connection\n"); 86 | /* Return '+' in case we were waiting for an ACK */ 87 | return '+'; 88 | } 89 | } 90 | return ret; 91 | } 92 | 93 | unsigned char gdb_if_getchar_to(int timeout) 94 | { 95 | fd_set fds; 96 | struct timeval tv; 97 | 98 | if(gdb_if_conn == -1) return -1; 99 | 100 | tv.tv_sec = timeout / 1000; 101 | tv.tv_usec = (timeout % 1000) * 1000; 102 | 103 | FD_ZERO(&fds); 104 | FD_SET(gdb_if_conn, &fds); 105 | 106 | if(select(gdb_if_conn+1, &fds, NULL, NULL, &tv) > 0) 107 | return gdb_if_getchar(); 108 | 109 | return -1; 110 | } 111 | 112 | void gdb_if_putchar(unsigned char c, int flush) 113 | { 114 | static uint8_t buf[2048]; 115 | static int bufsize = 0; 116 | if (gdb_if_conn > 0) { 117 | buf[bufsize++] = c; 118 | if (flush || (bufsize == sizeof(buf))) { 119 | send(gdb_if_conn, buf, bufsize, 0); 120 | bufsize = 0; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/platforms/libftdi/platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __PLATFORM_H 22 | #define __PLATFORM_H 23 | 24 | #include 25 | 26 | #include "timing.h" 27 | 28 | #ifndef WIN32 29 | # include 30 | #else 31 | # ifndef alloca 32 | # define alloca __builtin_alloca 33 | # endif 34 | #endif 35 | 36 | #define FT2232_VID 0x0403 37 | #define FT2232_PID 0x6010 38 | 39 | #define PLATFORM_HAS_DEBUG 40 | 41 | #define SET_RUN_STATE(state) 42 | #define SET_IDLE_STATE(state) 43 | #define SET_ERROR_STATE(state) 44 | 45 | extern struct ftdi_context *ftdic; 46 | 47 | void platform_buffer_flush(void); 48 | int platform_buffer_write(const uint8_t *data, int size); 49 | int platform_buffer_read(uint8_t *data, int size); 50 | 51 | static inline int platform_hwversion(void) 52 | { 53 | return 0; 54 | } 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /src/platforms/libftdi/swdptap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* Quick hack for bit-banging SW-DP interface over FT2232. 22 | * Intended as proof of concept, not for production. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "general.h" 30 | #include "swdptap.h" 31 | 32 | static uint8_t olddir = 0; 33 | 34 | int swdptap_init(void) 35 | { 36 | int err; 37 | 38 | assert(ftdic != NULL); 39 | 40 | if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) { 41 | fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", 42 | err, ftdi_get_error_string(ftdic)); 43 | abort(); 44 | } 45 | 46 | assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2); 47 | olddir = 0; 48 | 49 | return 0; 50 | } 51 | 52 | static void swdptap_turnaround(uint8_t dir) 53 | { 54 | platform_buffer_flush(); 55 | 56 | if (dir == olddir) 57 | return; 58 | olddir = dir; 59 | 60 | if(dir) /* SWDIO goes to input */ 61 | assert(ftdi_set_bitmode(ftdic, 0xA3, BITMODE_BITBANG) == 0); 62 | 63 | /* One clock cycle */ 64 | ftdi_write_data(ftdic, (void *)"\xAB\xA8", 2); 65 | 66 | if(!dir) /* SWDIO goes to output */ 67 | assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0); 68 | } 69 | 70 | bool swdptap_bit_in(void) 71 | { 72 | uint8_t ret; 73 | 74 | swdptap_turnaround(1); 75 | 76 | ftdi_read_pins(ftdic, &ret); 77 | ret &= 0x08; 78 | ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2); 79 | 80 | return ret; 81 | } 82 | 83 | void swdptap_bit_out(bool val) 84 | { 85 | uint8_t buf[3] = "\xA0\xA1\xA0"; 86 | 87 | swdptap_turnaround(0); 88 | 89 | if (val) { 90 | for(int i = 0; i < 3; i++) 91 | buf[i] |= 0x08; 92 | } 93 | platform_buffer_write(buf, 3); 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/platforms/native/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ 6 | -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include \ 7 | -Iplatforms/stm32 8 | 9 | LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ 10 | -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc \ 11 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ 12 | -L../libopencm3/lib 13 | LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 14 | 15 | ifeq ($(ENABLE_DEBUG), 1) 16 | LDFLAGS += --specs=rdimon.specs 17 | else 18 | LDFLAGS += --specs=nosys.specs 19 | endif 20 | 21 | VPATH += platforms/stm32 22 | 23 | SRC += cdcacm.c \ 24 | traceswo.c \ 25 | usbuart.c \ 26 | serialno.c \ 27 | timing.c \ 28 | timing_stm32.c \ 29 | 30 | all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex 31 | 32 | blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o 33 | @echo " LD $@" 34 | $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) 35 | 36 | host_clean: 37 | -$(Q)$(RM) -f blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex 38 | 39 | -------------------------------------------------------------------------------- /src/platforms/native/usbdfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "usbdfu.h" 27 | #include "platform.h" 28 | 29 | uint32_t app_address = 0x08002000; 30 | int dfu_activity_counter = 0; 31 | 32 | void dfu_detach(void) 33 | { 34 | /* USB device must detach, we just reset... */ 35 | scb_reset_system(); 36 | } 37 | 38 | int main(void) 39 | { 40 | /* Check the force bootloader pin*/ 41 | rcc_periph_clock_enable(RCC_GPIOB); 42 | if(gpio_get(GPIOB, GPIO12)) 43 | dfu_jump_app_if_valid(); 44 | 45 | dfu_protect(DFU_MODE); 46 | 47 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 48 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 49 | systick_set_reload(900000); 50 | 51 | /* Configure USB related clocks and pins. */ 52 | rcc_periph_clock_enable(RCC_GPIOA); 53 | rcc_periph_clock_enable(RCC_USB); 54 | gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); 55 | 56 | systick_interrupt_enable(); 57 | systick_counter_enable(); 58 | 59 | /* Configure the LED pins. */ 60 | gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, 61 | GPIO_CNF_OUTPUT_PUSHPULL, LED_0 | LED_1 | LED_2); 62 | 63 | dfu_init(&stm32f103_usb_driver, DFU_MODE); 64 | 65 | /* Configure the USB pull up pin. */ 66 | gpio_set(GPIOA, GPIO8); 67 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 68 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO8); 69 | 70 | dfu_main(); 71 | } 72 | 73 | void dfu_event(void) 74 | { 75 | /* If the counter was at 0 before we should reset LED status. */ 76 | if (dfu_activity_counter == 0) { 77 | gpio_clear(LED_PORT, LED_0 | LED_1 | LED_2); 78 | } 79 | 80 | /* Prevent the sys_tick_handler from blinking leds for a bit. */ 81 | dfu_activity_counter = 10; 82 | 83 | /* Toggle the DFU activity LED. */ 84 | gpio_toggle(LED_PORT, LED_1); 85 | } 86 | 87 | void sys_tick_handler(void) 88 | { 89 | static int count = 0; 90 | static bool reset = true; 91 | 92 | /* Run the LED show only if there is no DFU activity. */ 93 | if (dfu_activity_counter != 0) { 94 | dfu_activity_counter--; 95 | reset = true; 96 | } else { 97 | if (reset) { 98 | gpio_clear(LED_PORT, LED_0 | LED_1 | LED_2); 99 | count = 0; 100 | reset = false; 101 | } 102 | 103 | switch (count) { 104 | case 0: 105 | gpio_toggle(LED_PORT, LED_2); /* LED2 on/off */ 106 | count++; 107 | break; 108 | case 1: 109 | gpio_toggle(LED_PORT, LED_1); /* LED1 on/off */ 110 | count++; 111 | break; 112 | case 2: 113 | gpio_toggle(LED_PORT, LED_0); /* LED0 on/off */ 114 | count=0; 115 | break; 116 | } 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/platforms/stlink-bootloader/Connector: -------------------------------------------------------------------------------- 1 | == SWD Connector CN2 -- 2 | 1 VDD_TARGET VDD from application 3 | 2 SWCLK SWD clock 4 | 3 GND Ground 5 | 4 SWDIO SWD data input/output 6 | 5 NRST RESET of target MCU 7 | 6 SWO Reserved 8 | -------------------------------------------------------------------------------- /src/platforms/stlink-bootloader/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | OPT_FLAGS = -Os 6 | CFLAGS += -mcpu=cortex-m3 -mthumb \ 7 | -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \ 8 | -I platforms/stm32 9 | LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs \ 10 | -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ 11 | -Wl,-T,platforms/stm32/stlink-bootloader.ld -nostartfiles -lc -lnosys \ 12 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ 13 | -L../libopencm3/lib 14 | LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8004000 15 | 16 | VPATH += platforms/stm32 17 | 18 | SRC += cdcacm.c \ 19 | usbuart.c \ 20 | serialno.c \ 21 | timing.c \ 22 | timing_stm32.c \ 23 | 24 | all: blackmagic.bin 25 | 26 | host_clean: 27 | -$(Q)$(RM) blackmagic.bin 28 | -------------------------------------------------------------------------------- /src/platforms/stlink-bootloader/Readme: -------------------------------------------------------------------------------- 1 | Find a description how to modify a Discovery Board to use it's Stlink as 2 | black magic debug at 3 | http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe 4 | 5 | Differences between V1/V2 6 | 7 | V1 V2 8 | ID Pins PC13/14 unconnected PC 13 pulled low 9 | LED STLINK PA8, active High PA9, Dual Led 10 | MCO Out NA PA8 11 | RESET(Target) T_JRST(PB1) NRST (PB0) 12 | -------------------------------------------------------------------------------- /src/platforms/stlink-bootloader/dfu_upgrade.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "usbdfu.h" 27 | uint32_t app_address = 0x08000000; 28 | 29 | static uint8_t rev; 30 | static uint16_t led_idle_run; 31 | static uint32_t led2_state = 0; 32 | 33 | void dfu_detach(void) 34 | { 35 | /* Disconnect USB cable by resetting USB Device 36 | and pulling USB_DP low*/ 37 | rcc_periph_reset_pulse(RST_USB); 38 | rcc_periph_clock_enable(RCC_USB); 39 | rcc_periph_clock_enable(RCC_GPIOA); 40 | gpio_clear(GPIOA, GPIO12); 41 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 42 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 43 | /* Pull PB0 (T_NRST) low 44 | */ 45 | rcc_periph_clock_enable(RCC_GPIOB); 46 | gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, 47 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO0); 48 | gpio_clear(GPIOB, GPIO0); 49 | SCB_VTOR = 0; 50 | scb_reset_core(); 51 | } 52 | 53 | void stlink_set_rev(void) 54 | { 55 | int i; 56 | 57 | /* First, get Board revision by pulling PC13/14 up. Read 58 | * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 59 | * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 60 | */ 61 | rcc_periph_clock_enable(RCC_GPIOC); 62 | gpio_set_mode(GPIOC, GPIO_MODE_INPUT, 63 | GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); 64 | gpio_set(GPIOC, GPIO14 | GPIO13); 65 | for (i = 0; i < 100; i++) 66 | rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; 67 | 68 | switch (rev) { 69 | case 0: 70 | led_idle_run = GPIO8; 71 | break; 72 | default: 73 | led_idle_run = GPIO9; 74 | } 75 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 76 | GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); 77 | } 78 | 79 | int main(void) 80 | { 81 | 82 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 83 | 84 | stlink_set_rev(); 85 | 86 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 87 | systick_set_reload(900000); 88 | 89 | dfu_protect(UPD_MODE); 90 | 91 | /* Handle USB disconnect/connect */ 92 | /* Just in case: Disconnect USB cable by resetting USB Device 93 | * and pulling USB_DP low 94 | * Device will reconnect automatically as Pull-Up is hard wired*/ 95 | rcc_periph_reset_pulse(RST_USB); 96 | rcc_periph_clock_enable(RCC_USB); 97 | rcc_periph_clock_enable(RCC_GPIOA); 98 | gpio_clear(GPIOA, GPIO12); 99 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 100 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 101 | 102 | systick_interrupt_enable(); 103 | systick_counter_enable(); 104 | 105 | dfu_init(&stm32f103_usb_driver, UPD_MODE); 106 | 107 | dfu_main(); 108 | } 109 | 110 | void dfu_event(void) 111 | { 112 | } 113 | 114 | void sys_tick_handler(void) 115 | { 116 | if (rev == 0) { 117 | gpio_toggle(GPIOA, led_idle_run); 118 | } else { 119 | if (led2_state & 1) { 120 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 121 | GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); 122 | gpio_set(GPIOA, led_idle_run); 123 | } else { 124 | gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 125 | GPIO_CNF_INPUT_ANALOG, led_idle_run); 126 | } 127 | led2_state++; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/platforms/stlink/Connector: -------------------------------------------------------------------------------- 1 | == SWD Connector CN2 -- 2 | 1 VDD_TARGET VDD from application 3 | 2 SWCLK SWD clock 4 | 3 GND Ground 5 | 4 SWDIO SWD data input/output 6 | 5 NRST RESET of target MCU 7 | 6 SWO Reserved 8 | -------------------------------------------------------------------------------- /src/platforms/stlink/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | OPT_FLAGS = -Os 6 | CFLAGS += -mcpu=cortex-m3 -mthumb \ 7 | -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \ 8 | -I platforms/stm32 9 | LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs \ 10 | -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ 11 | -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ 12 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ 13 | -L../libopencm3/lib 14 | LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 15 | 16 | VPATH += platforms/stm32 17 | 18 | SRC += cdcacm.c \ 19 | usbuart.c \ 20 | serialno.c \ 21 | timing.c \ 22 | timing_stm32.c \ 23 | 24 | all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex 25 | 26 | blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o 27 | @echo " LD $@" 28 | $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) 29 | 30 | dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o 31 | @echo " LD $@" 32 | $(Q)$(CC) $^ -o $@ $(LDFLAGS) 33 | 34 | host_clean: 35 | -$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex 36 | 37 | -------------------------------------------------------------------------------- /src/platforms/stlink/Readme: -------------------------------------------------------------------------------- 1 | Find a description how to modify a Discovery Board to use it's Stlink as 2 | black magic debug at 3 | http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe 4 | 5 | Differences between V1/V2 6 | 7 | V1 V2 8 | ID Pins PC13/14 unconnected PC 13 pulled low 9 | LED STLINK PA8, active High PA9, Dual Led 10 | MCO Out NA PA8 11 | RESET(Target) T_JRST(PB1) NRST (PB0) 12 | -------------------------------------------------------------------------------- /src/platforms/stlink/dfu_upgrade.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "usbdfu.h" 27 | uint32_t app_address = 0x08000000; 28 | 29 | static uint8_t rev; 30 | static uint16_t led_idle_run; 31 | static uint32_t led2_state = 0; 32 | 33 | void dfu_detach(void) 34 | { 35 | /* Disconnect USB cable by resetting USB Device 36 | and pulling USB_DP low*/ 37 | rcc_periph_reset_pulse(RST_USB); 38 | rcc_periph_clock_enable(RCC_USB); 39 | rcc_periph_clock_enable(RCC_GPIOA); 40 | gpio_clear(GPIOA, GPIO12); 41 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 42 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 43 | /* Pull PB0 (T_NRST) low 44 | */ 45 | rcc_periph_clock_enable(RCC_GPIOB); 46 | gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, 47 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO0); 48 | gpio_clear(GPIOB, GPIO0); 49 | SCB_VTOR = 0; 50 | scb_reset_core(); 51 | } 52 | 53 | void stlink_set_rev(void) 54 | { 55 | int i; 56 | 57 | /* First, get Board revision by pulling PC13/14 up. Read 58 | * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 59 | * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 60 | */ 61 | rcc_periph_clock_enable(RCC_GPIOC); 62 | gpio_set_mode(GPIOC, GPIO_MODE_INPUT, 63 | GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); 64 | gpio_set(GPIOC, GPIO14 | GPIO13); 65 | for (i = 0; i < 100; i++) 66 | rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; 67 | 68 | switch (rev) { 69 | case 0: 70 | led_idle_run = GPIO8; 71 | break; 72 | default: 73 | led_idle_run = GPIO9; 74 | } 75 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 76 | GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); 77 | } 78 | 79 | int main(void) 80 | { 81 | 82 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 83 | 84 | stlink_set_rev(); 85 | 86 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 87 | systick_set_reload(900000); 88 | 89 | dfu_protect(UPD_MODE); 90 | 91 | /* Handle USB disconnect/connect */ 92 | /* Just in case: Disconnect USB cable by resetting USB Device 93 | * and pulling USB_DP low 94 | * Device will reconnect automatically as Pull-Up is hard wired*/ 95 | rcc_periph_reset_pulse(RST_USB); 96 | rcc_periph_clock_enable(RCC_USB); 97 | rcc_periph_clock_enable(RCC_GPIOA); 98 | gpio_clear(GPIOA, GPIO12); 99 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 100 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 101 | 102 | systick_interrupt_enable(); 103 | systick_counter_enable(); 104 | 105 | dfu_init(&stm32f103_usb_driver, UPD_MODE); 106 | 107 | dfu_main(); 108 | } 109 | 110 | void dfu_event(void) 111 | { 112 | } 113 | 114 | void sys_tick_handler(void) 115 | { 116 | if (rev == 0) { 117 | gpio_toggle(GPIOA, led_idle_run); 118 | } else { 119 | if (led2_state & 1) { 120 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 121 | GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); 122 | gpio_set(GPIOA, led_idle_run); 123 | } else { 124 | gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 125 | GPIO_CNF_INPUT_ANALOG, led_idle_run); 126 | } 127 | led2_state++; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/platforms/stm32/blackmagic.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopenstm32 project. 3 | * 4 | * Copyright (C) 2010 Thomas Otto 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_stm32f1.ld 29 | 30 | -------------------------------------------------------------------------------- /src/platforms/stm32/dfu_f1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "general.h" 20 | #include "usbdfu.h" 21 | 22 | #include 23 | #include 24 | 25 | #define FLASH_OBP_RDP 0x1FFFF800 26 | #define FLASH_OBP_WRP10 0x1FFFF808 27 | 28 | #define FLASH_OBP_RDP_KEY 0x5aa5 29 | 30 | #if defined (STM32_CAN) 31 | # define FLASHBLOCKSIZE 2048 32 | #else 33 | # define FLASHBLOCKSIZE 1024 34 | #endif 35 | 36 | static uint32_t last_erased_page = 0xffffffff; 37 | 38 | void dfu_check_and_do_sector_erase(uint32_t sector) 39 | { 40 | sector &= (~(FLASHBLOCKSIZE - 1)); 41 | if (sector != last_erased_page) { 42 | flash_erase_page(sector); 43 | last_erased_page = sector; 44 | } 45 | } 46 | 47 | void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) 48 | { 49 | for(int i = 0; i < len; i += 2) 50 | flash_program_half_word(baseaddr + i, 51 | *(uint16_t*)(buf+i)); 52 | 53 | /* Call the platform specific dfu event callback. */ 54 | dfu_event(); 55 | } 56 | 57 | uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) 58 | { 59 | (void)cmd; 60 | (void)addr; 61 | (void)blocknum; 62 | return 100; 63 | } 64 | 65 | void dfu_protect(dfu_mode_t mode) 66 | { 67 | if (mode == DFU_MODE) { 68 | #ifdef DFU_SELF_PROTECT 69 | if ((FLASH_WRPR & 0x03) != 0x00) { 70 | flash_unlock(); 71 | FLASH_CR = 0; 72 | flash_erase_option_bytes(); 73 | flash_program_option_bytes(FLASH_OBP_RDP, FLASH_OBP_RDP_KEY); 74 | /* CL Device: Protect 2 bits with (2 * 2k pages each)*/ 75 | /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ 76 | flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); 77 | } 78 | #endif 79 | } 80 | else if (mode == UPD_MODE) { 81 | flash_unlock(); 82 | FLASH_CR = 0; 83 | flash_erase_option_bytes(); 84 | } 85 | } 86 | 87 | void dfu_jump_app_if_valid(void) 88 | { 89 | /* Boot the application if it's valid */ 90 | if((*(volatile uint32_t*)app_address & 0x2FFE0000) == 0x20000000) { 91 | /* Set vector table base address */ 92 | SCB_VTOR = app_address & 0x1FFFFF; /* Max 2 MByte Flash*/ 93 | /* Initialise master stack pointer */ 94 | asm volatile ("msr msp, %0"::"g" 95 | (*(volatile uint32_t*)app_address)); 96 | /* Jump to application */ 97 | (*(void(**)())(app_address + 4))(); 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /src/platforms/stm32/dfu_f4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "general.h" 20 | #include "usbdfu.h" 21 | 22 | #if defined(STM32F2) 23 | # include 24 | #elif defined(STM32F4) 25 | # include 26 | #endif 27 | #include 28 | 29 | static uint32_t sector_addr[] = { 30 | 0x8000000, 0x8004000, 0x8008000, 0x800c000, 31 | 0x8010000, 0x8020000, 0x8040000, 0x8060000, 32 | 0x8080000, 0x80a0000, 0x80c0000, 0x80e0000, 33 | 0x8100000, 0 34 | }; 35 | static uint16_t sector_erase_time[12]= { 36 | 500, 500, 500, 500, 37 | 1100, 2600, 2600, 2600, 38 | 2600, 2600, 2600, 2600 39 | }; 40 | static uint8_t sector_num = 0xff; 41 | 42 | /* Find the sector number for a given address*/ 43 | static void get_sector_num(uint32_t addr) 44 | { 45 | int i = 0; 46 | while(sector_addr[i+1]) { 47 | if (addr < sector_addr[i+1]) 48 | break; 49 | i++; 50 | } 51 | if (!sector_addr[i]) 52 | return; 53 | sector_num = i; 54 | } 55 | 56 | void dfu_check_and_do_sector_erase(uint32_t addr) 57 | { 58 | if(addr == sector_addr[sector_num]) { 59 | flash_erase_sector((sector_num & 0x1f)<<3, FLASH_PROGRAM_X32); 60 | } 61 | } 62 | 63 | void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) 64 | { 65 | for(int i = 0; i < len; i += 4) 66 | flash_program_word(baseaddr + i, *(uint32_t*)(buf+i), 67 | FLASH_PROGRAM_X32); 68 | } 69 | 70 | uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) 71 | { 72 | /* Erase for big pages on STM2/4 needs "long" time 73 | Try not to hit USB timeouts*/ 74 | if ((blocknum == 0) && (cmd == CMD_ERASE)) { 75 | get_sector_num(addr); 76 | if(addr == sector_addr[sector_num]) 77 | return sector_erase_time[sector_num]; 78 | } 79 | 80 | /* Programming 256 word with 100 us(max) per word*/ 81 | return 26; 82 | } 83 | 84 | void dfu_protect_enable(void) 85 | { 86 | #ifdef DFU_SELF_PROTECT 87 | if ((FLASH_OPTCR & 0x10000) != 0) { 88 | flash_program_option_bytes(FLASH_OPTCR & ~0x10000); 89 | flash_lock_option_bytes(); 90 | } 91 | #endif 92 | } 93 | 94 | void dfu_jump_app_if_valid(void) 95 | { 96 | /* Boot the application if it's valid */ 97 | /* Vector table may be anywhere in 128 kByte RAM 98 | CCM not handled*/ 99 | if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) { 100 | /* Set vector table base address */ 101 | SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ 102 | /* Initialise master stack pointer */ 103 | asm volatile ("msr msp, %0"::"g" 104 | (*(volatile uint32_t*)APP_ADDRESS)); 105 | /* Jump to application */ 106 | (*(void(**)())(APP_ADDRESS + 4))(); 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/platforms/stm32/f4discovery.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopenstm32 project. 3 | * 4 | * Copyright (C) 2010 Thomas Otto 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_stm32f4.ld 29 | 30 | -------------------------------------------------------------------------------- /src/platforms/stm32/gdb_if.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements a transparent channel over which the GDB Remote 22 | * Serial Debugging protocol is implemented. This implementation for STM32 23 | * uses the USB CDC-ACM device bulk endpoints to implement the channel. 24 | */ 25 | #include "general.h" 26 | #include "cdcacm.h" 27 | #include "gdb_if.h" 28 | 29 | static uint32_t count_out; 30 | static uint32_t count_in; 31 | static uint32_t out_ptr; 32 | static uint8_t buffer_out[CDCACM_PACKET_SIZE]; 33 | static uint8_t buffer_in[CDCACM_PACKET_SIZE]; 34 | #ifdef STM32F4 35 | static volatile uint32_t count_new; 36 | static uint8_t double_buffer_out[CDCACM_PACKET_SIZE]; 37 | #endif 38 | 39 | void gdb_if_putchar(unsigned char c, int flush) 40 | { 41 | buffer_in[count_in++] = c; 42 | if(flush || (count_in == CDCACM_PACKET_SIZE)) { 43 | /* Refuse to send if USB isn't configured, and 44 | * don't bother if nobody's listening */ 45 | if((cdcacm_get_config() != 1) || !cdcacm_get_dtr()) { 46 | count_in = 0; 47 | return; 48 | } 49 | while(usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, 50 | buffer_in, count_in) <= 0); 51 | 52 | if (flush && (count_in == CDCACM_PACKET_SIZE)) { 53 | /* We need to send an empty packet for some hosts 54 | * to accept this as a complete transfer. */ 55 | /* libopencm3 needs a change for us to confirm when 56 | * that transfer is complete, so we just send a packet 57 | * containing a null byte for now. 58 | */ 59 | while (usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, 60 | "\0", 1) <= 0); 61 | } 62 | 63 | count_in = 0; 64 | } 65 | } 66 | 67 | #ifdef STM32F4 68 | void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) 69 | { 70 | (void)ep; 71 | usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 1); 72 | count_new = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, 73 | double_buffer_out, CDCACM_PACKET_SIZE); 74 | if(!count_new) { 75 | usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 0); 76 | } 77 | } 78 | #endif 79 | 80 | static void gdb_if_update_buf(void) 81 | { 82 | while (cdcacm_get_config() != 1); 83 | #ifdef STM32F4 84 | asm volatile ("cpsid i; isb"); 85 | if (count_new) { 86 | memcpy(buffer_out, double_buffer_out, count_new); 87 | count_out = count_new; 88 | count_new = 0; 89 | out_ptr = 0; 90 | usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); 91 | } 92 | asm volatile ("cpsie i; isb"); 93 | #else 94 | count_out = usbd_ep_read_packet(usbdev, CDCACM_GDB_ENDPOINT, 95 | buffer_out, CDCACM_PACKET_SIZE); 96 | out_ptr = 0; 97 | #endif 98 | } 99 | 100 | unsigned char gdb_if_getchar(void) 101 | { 102 | 103 | while (!(out_ptr < count_out)) { 104 | /* Detach if port closed */ 105 | if (!cdcacm_get_dtr()) 106 | return 0x04; 107 | 108 | gdb_if_update_buf(); 109 | } 110 | 111 | return buffer_out[out_ptr++]; 112 | } 113 | 114 | unsigned char gdb_if_getchar_to(int timeout) 115 | { 116 | platform_timeout t; 117 | platform_timeout_set(&t, timeout); 118 | 119 | if (!(out_ptr < count_out)) do { 120 | /* Detach if port closed */ 121 | if (!cdcacm_get_dtr()) 122 | return 0x04; 123 | 124 | gdb_if_update_buf(); 125 | } while (!platform_timeout_is_expired(&t) && !(out_ptr < count_out)); 126 | 127 | if(out_ptr < count_out) 128 | return gdb_if_getchar(); 129 | 130 | return -1; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/platforms/stm32/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __GPIO_H 21 | #define __GPIO_H 22 | 23 | #include 24 | 25 | #ifndef STM32F4 26 | # include 27 | # include 28 | #else 29 | # include 30 | # include 31 | #endif 32 | 33 | #define INLINE_GPIO 34 | 35 | #define gpio_set_val(port, pin, val) do { \ 36 | if(val) \ 37 | gpio_set((port), (pin)); \ 38 | else \ 39 | gpio_clear((port), (pin)); \ 40 | } while(0) 41 | 42 | #ifdef INLINE_GPIO 43 | static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) 44 | { 45 | GPIO_BSRR(gpioport) = gpios; 46 | #ifdef STM32F4 47 | GPIO_BSRR(gpioport) = gpios; 48 | #endif 49 | } 50 | #define gpio_set _gpio_set 51 | 52 | static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) 53 | { 54 | #ifndef STM32F4 55 | GPIO_BRR(gpioport) = gpios; 56 | #else 57 | GPIO_BSRR(gpioport) = gpios<<16; 58 | GPIO_BSRR(gpioport) = gpios<<16; 59 | #endif 60 | } 61 | #define gpio_clear _gpio_clear 62 | 63 | static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) 64 | { 65 | return (uint16_t)GPIO_IDR(gpioport) & gpios; 66 | } 67 | #define gpio_get _gpio_get 68 | #endif 69 | 70 | #endif 71 | 72 | -------------------------------------------------------------------------------- /src/platforms/stm32/jtagtap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the low-level JTAG TAP interface. */ 22 | 23 | #include 24 | 25 | #include "general.h" 26 | #include "jtagtap.h" 27 | #include "gdb_packet.h" 28 | 29 | int jtagtap_init(void) 30 | { 31 | TMS_SET_MODE(); 32 | 33 | /* Go to JTAG mode for SWJ-DP */ 34 | for(int i = 0; i <= 50; i++) jtagtap_next(1, 0); /* Reset SW-DP */ 35 | jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */ 36 | jtagtap_soft_reset(); 37 | 38 | return 0; 39 | } 40 | 41 | void jtagtap_reset(void) 42 | { 43 | #ifdef TRST_PORT 44 | if (platform_hwversion() == 0) { 45 | volatile int i; 46 | gpio_clear(TRST_PORT, TRST_PIN); 47 | for(i = 0; i < 10000; i++) asm("nop"); 48 | gpio_set(TRST_PORT, TRST_PIN); 49 | } 50 | #endif 51 | jtagtap_soft_reset(); 52 | } 53 | 54 | inline uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDI) 55 | { 56 | uint16_t ret; 57 | 58 | gpio_set_val(TMS_PORT, TMS_PIN, dTMS); 59 | gpio_set_val(TDI_PORT, TDI_PIN, dTDI); 60 | gpio_set(TCK_PORT, TCK_PIN); 61 | ret = gpio_get(TDO_PORT, TDO_PIN); 62 | gpio_clear(TCK_PORT, TCK_PIN); 63 | 64 | //DEBUG("jtagtap_next(TMS = %d, TDI = %d) = %d\n", dTMS, dTDI, ret); 65 | 66 | return ret != 0; 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/platforms/stm32/serialno.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "general.h" 21 | 22 | char *serialno_read(char *s) 23 | { 24 | #if defined(STM32F4) 25 | volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; 26 | #else 27 | volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; 28 | #endif 29 | uint32_t unique_id = *unique_id_p + 30 | *(unique_id_p + 1) + 31 | *(unique_id_p + 2); 32 | int i; 33 | 34 | /* Fetch serial number from chip's unique ID */ 35 | for(i = 0; i < 8; i++) { 36 | s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; 37 | } 38 | for(i = 0; i < 8; i++) 39 | if(s[i] > '9') 40 | s[i] += 'A' - '9' - 1; 41 | s[8] = 0; 42 | 43 | return s; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/platforms/stm32/stlink-bootloader.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopenstm32 project. 3 | * 4 | * Copyright (C) 2010 Thomas Otto 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_stm32f1.ld 29 | -------------------------------------------------------------------------------- /src/platforms/stm32/stlink.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopenstm32 project. 3 | * 4 | * Copyright (C) 2010 Thomas Otto 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 64K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_stm32f1.ld 29 | -------------------------------------------------------------------------------- /src/platforms/stm32/stm32_can.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopenstm32 project. 3 | * 4 | * Copyright (C) 2010 Thomas Otto 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 64K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_stm32f1.ld 29 | -------------------------------------------------------------------------------- /src/platforms/stm32/timing_stm32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "general.h" 20 | #include "morse.h" 21 | 22 | #include 23 | #include 24 | 25 | uint8_t running_status; 26 | static volatile uint32_t time_ms; 27 | 28 | void platform_timing_init(void) 29 | { 30 | /* Setup heartbeat timer */ 31 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 32 | systick_set_reload(900000); /* Interrupt us at 10 Hz */ 33 | SCB_SHPR(11) &= ~((15 << 4) & 0xff); 34 | SCB_SHPR(11) |= ((14 << 4) & 0xff); 35 | systick_interrupt_enable(); 36 | systick_counter_enable(); 37 | } 38 | 39 | void platform_delay(uint32_t ms) 40 | { 41 | platform_timeout timeout; 42 | platform_timeout_set(&timeout, ms); 43 | while (!platform_timeout_is_expired(&timeout)); 44 | } 45 | 46 | void sys_tick_handler(void) 47 | { 48 | if(running_status) 49 | gpio_toggle(LED_PORT, LED_IDLE_RUN); 50 | 51 | time_ms += 100; 52 | 53 | SET_ERROR_STATE(morse_update()); 54 | } 55 | 56 | uint32_t platform_time_ms(void) 57 | { 58 | return time_ms; 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/platforms/stm32/timing_stm32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #ifndef __TIMING_STM32_H 20 | #define __TIMING_STM32_H 21 | 22 | extern uint8_t running_status; 23 | 24 | void platform_timing_init(void); 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /src/platforms/stm32/usbdfu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef __USBDFU_H 21 | #define __USBDFU_H 22 | 23 | #include 24 | 25 | /* Commands sent with wBlockNum == 0 as per ST implementation. */ 26 | #define CMD_SETADDR 0x21 27 | #define CMD_ERASE 0x41 28 | extern uint32_t app_address; 29 | 30 | typedef enum { 31 | DFU_MODE = 0, 32 | UPD_MODE = 1 33 | } dfu_mode_t; 34 | 35 | /* dfucore.c - DFU core, common to libopencm3 platforms. */ 36 | void dfu_init(const usbd_driver *driver, dfu_mode_t mode); 37 | void dfu_main(void); 38 | 39 | /* Device specific functions */ 40 | void dfu_check_and_do_sector_erase(uint32_t sector); 41 | void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len); 42 | uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum); 43 | void dfu_protect(dfu_mode_t mode); 44 | void dfu_jump_app_if_valid(void); 45 | void dfu_event(void); 46 | 47 | /* Platform specific function */ 48 | void dfu_detach(void); 49 | 50 | #endif /* __USBDFU_H */ 51 | -------------------------------------------------------------------------------- /src/platforms/swlink/Connectors: -------------------------------------------------------------------------------- 1 | CN5 JTAG Conn 2 | -------------- 3 | 4 | JRST - o o - GND 5 | JTDI - o o - JTMS/SWDIO 6 | JTCK/SWCLK - o o - JTDO 7 | o - +3v3 8 | 9 | 10 | CN7 SWIM Conn 11 | -------------- 12 | 13 | o - VDD - (V_target) - Unconnected/Floating if Jtag-PCB is broken away from STM8-Board 14 | o - USART1_RX - (SWIM_IN) 15 | STM8-Board <-- o - GND 16 | o - USART1_TX - (SWIM_RST) 17 | 18 | | 19 | v 20 | 21 | XTAL 22 | 23 | -------------------------------------------------------------------------------- /src/platforms/swlink/Makefile.inc: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | CC = $(CROSS_COMPILE)gcc 3 | OBJCOPY = $(CROSS_COMPILE)objcopy 4 | 5 | OPT_FLAGS = -Os 6 | CFLAGS += -mcpu=cortex-m3 -mthumb \ 7 | -DSTM32F1 -DDISCOVERY_SWLINK -I../libopencm3/include \ 8 | -I platforms/stm32 9 | LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs \ 10 | -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ 11 | -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ 12 | -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ 13 | -L../libopencm3/lib 14 | LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 15 | 16 | VPATH += platforms/stm32 17 | 18 | SRC += cdcacm.c \ 19 | usbuart.c \ 20 | serialno.c \ 21 | timing.c \ 22 | timing_stm32.c \ 23 | 24 | all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex 25 | 26 | blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o 27 | @echo " LD $@" 28 | $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) 29 | 30 | host_clean: 31 | -$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex 32 | 33 | -------------------------------------------------------------------------------- /src/platforms/swlink/Readme: -------------------------------------------------------------------------------- 1 | Blackmagic for the STM8S Discovery Board 2 | ======================================== 3 | 4 | The board is a ST-Link V1 Board, but with access to JTAG pins accessible 5 | on CN5. This allows easy reprogramming and reuse of the JTAG header. 6 | Programmatical it seems indistinguishable from a e.g. STM32VL 7 | Discovery. So here avariant that uses CN5 for JTAG/SWD_TRACESWO and CN7 for 8 | UART. 9 | 10 | Force Bootloader entry is done with shorting CN7 Pin3/4 so PB6 read low while 11 | pulled up momentary by PB6. 12 | 13 | Reuse SWIM Pins for Uart (USART1) 14 | RX: CN7 Pin2 ->SWIM_IN (PB7)/USART1_RX / SWIM_IN(PB9) 15 | TX: CN7 Pin4 -> SWIM_RST_IN(PB6)/USART1_TX 16 | -------------------------------------------------------------------------------- /src/platforms/swlink/platform.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the platform specific functions for the ST-Link 22 | * implementation. 23 | */ 24 | 25 | #include "general.h" 26 | #include "cdcacm.h" 27 | #include "usbuart.h" 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | void platform_init(void) 37 | { 38 | uint32_t data; 39 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 40 | 41 | /* Enable peripherals */ 42 | rcc_periph_clock_enable(RCC_USB); 43 | rcc_periph_clock_enable(RCC_GPIOA); 44 | rcc_periph_clock_enable(RCC_GPIOB); 45 | rcc_periph_clock_enable(RCC_AFIO); 46 | rcc_periph_clock_enable(RCC_CRC); 47 | 48 | /* Unmap JTAG Pins so we can reuse as GPIO */ 49 | data = AFIO_MAPR; 50 | data &= ~AFIO_MAPR_SWJ_MASK; 51 | data |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; 52 | AFIO_MAPR = data; 53 | /* Setup JTAG GPIO ports */ 54 | gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_10_MHZ, 55 | GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); 56 | gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_10_MHZ, 57 | GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); 58 | gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_10_MHZ, 59 | GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); 60 | 61 | gpio_set_mode(TDO_PORT, GPIO_MODE_INPUT, 62 | GPIO_CNF_INPUT_FLOAT, TDO_PIN); 63 | 64 | gpio_set(NRST_PORT,NRST_PIN); 65 | gpio_set_mode(NRST_PORT, GPIO_MODE_INPUT, 66 | GPIO_CNF_INPUT_PULL_UPDOWN, NRST_PIN); 67 | 68 | gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, 69 | GPIO_CNF_OUTPUT_PUSHPULL, LED_IDLE_RUN); 70 | 71 | /* Remap TIM2 TIM2_REMAP[1] 72 | * TIM2_CH1_ETR -> PA15 (TDI, set as output above) 73 | * TIM2_CH2 -> PB3 (TDO) 74 | */ 75 | data = AFIO_MAPR; 76 | data &= ~AFIO_MAPR_TIM2_REMAP_FULL_REMAP; 77 | data |= AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP1; 78 | AFIO_MAPR = data; 79 | 80 | SCB_VTOR = 0x2000; // Relocate interrupt vector table here 81 | 82 | platform_timing_init(); 83 | cdcacm_init(); 84 | usbuart_init(); 85 | } 86 | 87 | void platform_srst_set_val(bool assert) { (void)assert; } 88 | bool platform_srst_get_val(void) { return false; } 89 | 90 | const char *platform_target_voltage(void) 91 | { 92 | return "unknown"; 93 | } 94 | 95 | void platform_request_boot(void) 96 | { 97 | /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ 98 | rcc_periph_reset_pulse(RST_USB); 99 | rcc_periph_clock_enable(RCC_USB); 100 | rcc_periph_clock_enable(RCC_GPIOA); 101 | gpio_clear(GPIOA, GPIO12); 102 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 103 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 104 | 105 | /* Assert bootloader pin */ 106 | uint32_t crl = GPIOA_CRL; 107 | rcc_periph_clock_enable(RCC_GPIOA); 108 | /* Enable Pull on GPIOA1. We don't rely on the external pin 109 | * really pulled, but only on the value of the CNF register 110 | * changed from the reset value 111 | */ 112 | crl &= 0xffffff0f; 113 | crl |= 0x80; 114 | GPIOA_CRL = crl; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/platforms/swlink/usbdfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2013 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "usbdfu.h" 27 | 28 | uint32_t app_address = 0x08002000; 29 | 30 | void dfu_detach(void) 31 | { 32 | /* Disconnect USB cable by resetting USB Device 33 | and pulling USB_DP low*/ 34 | rcc_periph_reset_pulse(RST_USB); 35 | rcc_periph_clock_enable(RCC_USB); 36 | rcc_periph_clock_enable(RCC_GPIOA); 37 | gpio_clear(GPIOA, GPIO12); 38 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 39 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 40 | scb_reset_system(); 41 | } 42 | 43 | int main(void) 44 | { 45 | /* Check the force bootloader pin*/ 46 | uint16_t pin_b; 47 | rcc_periph_clock_enable(RCC_GPIOA); 48 | rcc_periph_clock_enable(RCC_GPIOB); 49 | /* Switch PB5 (SWIM_RST_IN) up */ 50 | gpio_set(GPIOB, GPIO5); 51 | gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, 52 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); 53 | gpio_set(GPIOB, GPIO5); 54 | pin_b = gpio_get(GPIOB, GPIO6); 55 | /* Check state on PB6 ((SWIM_RST) and release PB5*/ 56 | pin_b = gpio_get(GPIOB, GPIO6); 57 | gpio_set_mode(GPIOB, GPIO_MODE_INPUT, 58 | GPIO_CNF_INPUT_FLOAT, GPIO5); 59 | if(((GPIOA_CRL & 0x40) == 0x40) && pin_b) 60 | dfu_jump_app_if_valid(); 61 | 62 | dfu_protect(DFU_MODE); 63 | 64 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 65 | systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); 66 | systick_set_reload(900000); 67 | 68 | /* Handle USB disconnect/connect */ 69 | /* Just in case: Disconnect USB cable by resetting USB Device 70 | * and pulling USB_DP low 71 | * Device will reconnect automatically as Pull-Up is hard wired*/ 72 | rcc_periph_reset_pulse(RST_USB); 73 | rcc_periph_clock_enable(RCC_USB); 74 | rcc_periph_clock_enable(RCC_GPIOA); 75 | gpio_clear(GPIOA, GPIO12); 76 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 77 | GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); 78 | 79 | /* Handle LED*/ 80 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, 81 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO8); 82 | 83 | systick_interrupt_enable(); 84 | systick_counter_enable(); 85 | 86 | dfu_init(&stm32f103_usb_driver, DFU_MODE); 87 | 88 | dfu_main(); 89 | } 90 | 91 | void dfu_event(void) 92 | { 93 | } 94 | 95 | void sys_tick_handler(void) 96 | { 97 | gpio_toggle(GPIOA, GPIO8); 98 | } 99 | -------------------------------------------------------------------------------- /src/platforms/tm4c/gdb_if.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements a transparent channel over which the GDB Remote 22 | * Serial Debugging protocol is implemented. This implementation for STM32 23 | * uses the USB CDC-ACM device bulk endpoints to implement the channel. 24 | */ 25 | 26 | #include "general.h" 27 | #include "gdb_if.h" 28 | #include "cdcacm.h" 29 | 30 | #include 31 | 32 | static volatile uint32_t head_out, tail_out; 33 | static volatile uint32_t count_in; 34 | static volatile uint8_t buffer_out[16*CDCACM_PACKET_SIZE]; 35 | static volatile uint8_t buffer_in[CDCACM_PACKET_SIZE]; 36 | 37 | void gdb_if_putchar(unsigned char c, int flush) 38 | { 39 | buffer_in[count_in++] = c; 40 | if(flush || (count_in == CDCACM_PACKET_SIZE)) { 41 | /* Refuse to send if USB isn't configured, and 42 | * don't bother if nobody's listening */ 43 | if((cdcacm_get_config() != 1) || !cdcacm_get_dtr()) { 44 | count_in = 0; 45 | return; 46 | } 47 | while(usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, 48 | (uint8_t *)buffer_in, count_in) <= 0); 49 | count_in = 0; 50 | } 51 | } 52 | 53 | void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) 54 | { 55 | (void)ep; 56 | static uint8_t buf[CDCACM_PACKET_SIZE]; 57 | 58 | usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 1); 59 | uint32_t count = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, 60 | (uint8_t *)buf, CDCACM_PACKET_SIZE); 61 | 62 | 63 | uint32_t idx; 64 | for (idx=0; idx 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | /* Define memory regions. */ 21 | MEMORY 22 | { 23 | rom (rx) : ORIGIN = 0x00000000, LENGTH = 256K 24 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K 25 | } 26 | 27 | /* Include the common ld script from libopenstm32. */ 28 | INCLUDE libopencm3_lm4f.ld 29 | 30 | -------------------------------------------------------------------------------- /src/platforms/tm4c/traceswo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2012 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * Copyright (C) 2014 Fredrik Ahlberg 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | */ 22 | 23 | /* This file implements capture of the TRACESWO output. 24 | * 25 | * ARM DDI 0403D - ARMv7M Architecture Reference Manual 26 | * ARM DDI 0337I - Cortex-M3 Technical Reference Manual 27 | * ARM DDI 0314H - CoreSight Components Technical Reference Manual 28 | */ 29 | 30 | #include "general.h" 31 | #include "cdcacm.h" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | void traceswo_init(void) 40 | { 41 | periph_clock_enable(RCC_GPIOD); 42 | periph_clock_enable(TRACEUART_CLK); 43 | __asm__("nop"); __asm__("nop"); __asm__("nop"); 44 | 45 | gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); 46 | gpio_set_af(SWO_PORT, 1, SWO_PIN); /* U2RX */ 47 | 48 | uart_disable(TRACEUART); 49 | 50 | /* Setup UART parameters. */ 51 | uart_clock_from_sysclk(TRACEUART); 52 | uart_set_baudrate(TRACEUART, 800000); 53 | uart_set_databits(TRACEUART, 8); 54 | uart_set_stopbits(TRACEUART, 1); 55 | uart_set_parity(TRACEUART, UART_PARITY_NONE); 56 | 57 | // Enable FIFO 58 | uart_enable_fifo(TRACEUART); 59 | 60 | // Set FIFO interrupt trigger levels to 4/8 full for RX buffer and 61 | // 7/8 empty (1/8 full) for TX buffer 62 | uart_set_fifo_trigger_levels(TRACEUART, UART_FIFO_RX_TRIG_1_2, UART_FIFO_TX_TRIG_7_8); 63 | 64 | uart_clear_interrupt_flag(TRACEUART, UART_INT_RX | UART_INT_RT); 65 | 66 | /* Enable interrupts */ 67 | uart_enable_interrupts(TRACEUART, UART_INT_RX | UART_INT_RT); 68 | 69 | /* Finally enable the USART. */ 70 | uart_enable(TRACEUART); 71 | 72 | nvic_set_priority(TRACEUART_IRQ, 0); 73 | nvic_enable_irq(TRACEUART_IRQ); 74 | 75 | /* Un-stall USB endpoint */ 76 | usbd_ep_stall_set(usbdev, 0x85, 0); 77 | 78 | gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3); 79 | } 80 | 81 | void traceswo_baud(unsigned int baud) 82 | { 83 | uart_set_baudrate(TRACEUART, baud); 84 | uart_set_databits(TRACEUART, 8); 85 | } 86 | 87 | #define FIFO_SIZE 256 88 | 89 | /* RX Fifo buffer */ 90 | static volatile uint8_t buf_rx[FIFO_SIZE]; 91 | /* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ 92 | static volatile uint32_t buf_rx_in = 0; 93 | /* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ 94 | static volatile uint32_t buf_rx_out = 0; 95 | 96 | void trace_buf_push(void) 97 | { 98 | size_t len; 99 | 100 | if (buf_rx_in == buf_rx_out) { 101 | return; 102 | } else if (buf_rx_in > buf_rx_out) { 103 | len = buf_rx_in - buf_rx_out; 104 | } else { 105 | len = FIFO_SIZE - buf_rx_out; 106 | } 107 | 108 | if (len > 64) { 109 | len = 64; 110 | } 111 | 112 | if (usbd_ep_write_packet(usbdev, 0x85, (uint8_t *)&buf_rx[buf_rx_out], len) == len) { 113 | buf_rx_out += len; 114 | buf_rx_out %= FIFO_SIZE; 115 | } 116 | } 117 | 118 | void trace_buf_drain(usbd_device *dev, uint8_t ep) 119 | { 120 | (void) dev; 121 | (void) ep; 122 | trace_buf_push(); 123 | } 124 | 125 | void trace_tick(void) 126 | { 127 | trace_buf_push(); 128 | } 129 | 130 | void TRACEUART_ISR(void) 131 | { 132 | uint32_t flush = uart_is_interrupt_source(TRACEUART, UART_INT_RT); 133 | 134 | while (!uart_is_rx_fifo_empty(TRACEUART)) { 135 | uint32_t c = uart_recv(TRACEUART); 136 | 137 | /* If the next increment of rx_in would put it at the same point 138 | * as rx_out, the FIFO is considered full. 139 | */ 140 | if (((buf_rx_in + 1) % FIFO_SIZE) != buf_rx_out) 141 | { 142 | /* insert into FIFO */ 143 | buf_rx[buf_rx_in++] = c; 144 | 145 | /* wrap out pointer */ 146 | if (buf_rx_in >= FIFO_SIZE) 147 | { 148 | buf_rx_in = 0; 149 | } 150 | } else { 151 | flush = 1; 152 | break; 153 | } 154 | } 155 | 156 | if (flush) { 157 | /* advance fifo out pointer by amount written */ 158 | trace_buf_push(); 159 | } 160 | } 161 | 162 | -------------------------------------------------------------------------------- /src/target/adiv5_jtagdp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements the JTAG-DP specific functions of the 22 | * ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A. 23 | */ 24 | 25 | #include "general.h" 26 | #include "exception.h" 27 | #include "adiv5.h" 28 | #include "jtag_scan.h" 29 | #include "jtagtap.h" 30 | #include "morse.h" 31 | 32 | #define JTAGDP_ACK_OK 0x02 33 | #define JTAGDP_ACK_WAIT 0x01 34 | 35 | /* 35-bit registers that control the ADIv5 DP */ 36 | #define IR_ABORT 0x8 37 | #define IR_DPACC 0xA 38 | #define IR_APACC 0xB 39 | 40 | static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr); 41 | 42 | static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); 43 | 44 | static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, 45 | uint16_t addr, uint32_t value); 46 | 47 | static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort); 48 | 49 | void adiv5_jtag_dp_handler(jtag_dev_t *dev) 50 | { 51 | ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); 52 | 53 | dp->dev = dev; 54 | dp->idcode = dev->idcode; 55 | 56 | dp->dp_read = adiv5_jtagdp_read; 57 | dp->error = adiv5_jtagdp_error; 58 | dp->low_access = adiv5_jtagdp_low_access; 59 | dp->abort = adiv5_jtagdp_abort; 60 | 61 | adiv5_dp_init(dp); 62 | } 63 | 64 | static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr) 65 | { 66 | adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0); 67 | return adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, 68 | ADIV5_DP_RDBUFF, 0); 69 | } 70 | 71 | static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp) 72 | { 73 | adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0); 74 | return adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, 75 | ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32; 76 | } 77 | 78 | static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, 79 | uint16_t addr, uint32_t value) 80 | { 81 | bool APnDP = addr & ADIV5_APnDP; 82 | addr &= 0xff; 83 | uint64_t request, response; 84 | uint8_t ack; 85 | platform_timeout timeout; 86 | 87 | request = ((uint64_t)value << 3) | ((addr >> 1) & 0x06) | (RnW?1:0); 88 | 89 | jtag_dev_write_ir(dp->dev, APnDP ? IR_APACC : IR_DPACC); 90 | 91 | platform_timeout_set(&timeout, 2000); 92 | do { 93 | jtag_dev_shift_dr(dp->dev, (uint8_t*)&response, (uint8_t*)&request, 35); 94 | ack = response & 0x07; 95 | } while(!platform_timeout_is_expired(&timeout) && (ack == JTAGDP_ACK_WAIT)); 96 | 97 | if (ack == JTAGDP_ACK_WAIT) 98 | raise_exception(EXCEPTION_TIMEOUT, "JTAG-DP ACK timeout"); 99 | 100 | if((ack != JTAGDP_ACK_OK)) 101 | raise_exception(EXCEPTION_ERROR, "JTAG-DP invalid ACK"); 102 | 103 | return (uint32_t)(response >> 3); 104 | } 105 | 106 | static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort) 107 | { 108 | uint64_t request = (uint64_t)abort << 3; 109 | jtag_dev_write_ir(dp->dev, IR_ABORT); 110 | jtag_dev_shift_dr(dp->dev, NULL, (const uint8_t*)&request, 35); 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/target/flashstub/Makefile: -------------------------------------------------------------------------------- 1 | CROSS_COMPILE ?= arm-none-eabi- 2 | AS = $(CROSS_COMPILE)as 3 | CC = $(CROSS_COMPILE)gcc 4 | OBJCOPY = $(CROSS_COMPILE)objcopy 5 | HEXDUMP = hexdump 6 | 7 | ifneq ($(V), 1) 8 | Q = @ 9 | endif 10 | 11 | CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../../../libopencm3/include 12 | ASFLAGS=-mcpu=cortex-m3 -mthumb 13 | 14 | all: lmi.stub stm32f4.stub stm32l4.stub nrf51.stub stm32f1.stub efm32.stub 15 | 16 | stm32f1.o: CFLAGS += -DSTM32F1 17 | stm32f4.o: CFLAGS += -DSTM32F4 18 | 19 | %.o: %.c 20 | $(Q)echo " CC $<" 21 | $(Q)$(CC) $(CFLAGS) -o $@ -c $< 22 | 23 | %.o: %.s 24 | $(Q)echo " AS $<" 25 | $(Q)$(AS) $(ASFLAGS) -o $@ $< 26 | 27 | %.bin: %.o 28 | $(Q)echo " OBJCOPY $@" 29 | $(Q)$(OBJCOPY) -O binary $< $@ 30 | 31 | %.stub: %.bin 32 | $(Q)echo " HEXDUMP $@" 33 | $(Q)$(HEXDUMP) -v -e '/2 "0x%04X, "' $< > $@ 34 | 35 | .PHONY: clean 36 | 37 | clean: 38 | $(Q)echo " CLEAN" 39 | -$(Q)rm -f *.o *.bin *.stub 40 | 41 | -------------------------------------------------------------------------------- /src/target/flashstub/README.md: -------------------------------------------------------------------------------- 1 | Flash Stubs 2 | =========== 3 | 4 | These are simple routines for programming the flash on various Cortex-M 5 | microcontrollers. The routines should be provided with the naked attribute 6 | as the stack may not be available, and must not make any function calls. 7 | The stub must call `stub_exit(code)` provided by `stub.h` to return control 8 | to the debugger. Up to 4 word sized parameters may be taken. 9 | 10 | These stubs are compiled instructions comma separated hex values in the 11 | resulting `*.stub` files here, which may be included in the drivers for the 12 | specific device. The drivers call these flash stubs on the target by calling 13 | `cortexm_run_stub` defined in `cortexm.h`. 14 | -------------------------------------------------------------------------------- /src/target/flashstub/efm32.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Richard Meadows 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include 20 | #include "stub.h" 21 | 22 | #define EFM32_MSC ((volatile uint32_t *)0x400c0000) 23 | #define EFM32_MSC_WRITECTRL EFM32_MSC[2] 24 | #define EFM32_MSC_WRITECMD EFM32_MSC[3] 25 | #define EFM32_MSC_ADDRB EFM32_MSC[4] 26 | #define EFM32_MSC_WDATA EFM32_MSC[6] 27 | #define EFM32_MSC_STATUS EFM32_MSC[7] 28 | #define EFM32_MSC_LOCK EFM32_MSC[15] 29 | 30 | #define EFM32_MSC_LOCK_LOCKKEY 0x1b71 31 | 32 | #define EFM32_MSC_WRITECMD_LADDRIM (1<<0) 33 | #define EFM32_MSC_WRITECMD_ERASEPAGE (1<<1) 34 | #define EFM32_MSC_WRITECMD_WRITEEND (1<<2) 35 | #define EFM32_MSC_WRITECMD_WRITEONCE (1<<3) 36 | #define EFM32_MSC_WRITECMD_WRITETRIG (1<<4) 37 | #define EFM32_MSC_WRITECMD_ERASEABORT (1<<5) 38 | 39 | #define EFM32_MSC_STATUS_BUSY (1<<0) 40 | #define EFM32_MSC_STATUS_LOCKED (1<<1) 41 | #define EFM32_MSC_STATUS_INVADDR (1<<2) 42 | #define EFM32_MSC_STATUS_WDATAREADY (1<<3) 43 | #define EFM32_MSC_STATUS_WORDTIMEOUT (1<<4) 44 | 45 | void __attribute__((naked)) 46 | efm32_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size) 47 | { 48 | uint32_t i; 49 | 50 | EFM32_MSC_LOCK = EFM32_MSC_LOCK_LOCKKEY; 51 | EFM32_MSC_WRITECTRL = 1; 52 | 53 | for (i = 0; i < size/4; i++) { 54 | EFM32_MSC_ADDRB = (uint32_t)&dest[i];; 55 | EFM32_MSC_WRITECMD = EFM32_MSC_WRITECMD_LADDRIM; 56 | 57 | /* Wait for WDATAREADY */ 58 | while ((EFM32_MSC_STATUS & EFM32_MSC_STATUS_WDATAREADY) == 0); 59 | 60 | EFM32_MSC_WDATA = src[i]; 61 | EFM32_MSC_WRITECMD = EFM32_MSC_WRITECMD_WRITEONCE; 62 | 63 | /* Wait for BUSY */ 64 | while ((EFM32_MSC_STATUS & EFM32_MSC_STATUS_BUSY)); 65 | } 66 | 67 | stub_exit(0); 68 | } 69 | -------------------------------------------------------------------------------- /src/target/flashstub/efm32.stub: -------------------------------------------------------------------------------- 1 | [0x0/2] = 0x4c10, 2 | [0x2/2] = 0x4b11, 3 | [0x4/2] = 0x0892, 4 | [0x6/2] = 0x601c, 5 | [0x8/2] = 0x2401, 6 | [0xa/2] = 0x4b10, 7 | [0xc/2] = 0x0092, 8 | [0xe/2] = 0x601c, 9 | [0x10/2] = 0x2400, 10 | [0x12/2] = 0x4294, 11 | [0x14/2] = 0xd015, 12 | [0x16/2] = 0x4d0e, 13 | [0x18/2] = 0x1903, 14 | [0x1a/2] = 0x602b, 15 | [0x1c/2] = 0x2501, 16 | [0x1e/2] = 0x4b0d, 17 | [0x20/2] = 0x601d, 18 | [0x22/2] = 0x2608, 19 | [0x24/2] = 0x4d0c, 20 | [0x26/2] = 0x682f, 21 | [0x28/2] = 0x46ac, 22 | [0x2a/2] = 0x4237, 23 | [0x2c/2] = 0xd0f9, 24 | [0x2e/2] = 0x590d, 25 | [0x30/2] = 0x4f0a, 26 | [0x32/2] = 0x603d, 27 | [0x34/2] = 0x601e, 28 | [0x36/2] = 0x4663, 29 | [0x38/2] = 0x681b, 30 | [0x3a/2] = 0x07db, 31 | [0x3c/2] = 0xd4fb, 32 | [0x3e/2] = 0x3404, 33 | [0x40/2] = 0xe7e7, 34 | [0x42/2] = 0xbe00, 35 | [0x44/2] = 0x1b71, 0x0000, 36 | [0x48/2] = 0x003c, 0x400c, 37 | [0x4c/2] = 0x0008, 0x400c, 38 | [0x50/2] = 0x0010, 0x400c, 39 | [0x54/2] = 0x000c, 0x400c, 40 | [0x58/2] = 0x001c, 0x400c, 41 | [0x5c/2] = 0x0018, 0x400c, 42 | -------------------------------------------------------------------------------- /src/target/flashstub/lmi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include 21 | #include "stub.h" 22 | 23 | #define LMI_FLASH_BASE ((volatile uint32_t *)0x400FD000) 24 | #define LMI_FLASH_FMA LMI_FLASH_BASE[0] 25 | #define LMI_FLASH_FMD LMI_FLASH_BASE[1] 26 | #define LMI_FLASH_FMC LMI_FLASH_BASE[2] 27 | 28 | #define LMI_FLASH_FMC_WRITE (1 << 0) 29 | #define LMI_FLASH_FMC_ERASE (1 << 1) 30 | #define LMI_FLASH_FMC_MERASE (1 << 2) 31 | #define LMI_FLASH_FMC_COMT (1 << 3) 32 | #define LMI_FLASH_FMC_WRKEY 0xA4420000 33 | 34 | void __attribute__((naked)) 35 | stm32f1_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size) 36 | { 37 | size /= 4; 38 | for (int i; i < size; i++) { 39 | LMI_FLASH_FMA = (uint32_t)&dest[i]; 40 | LMI_FLASH_FMD = src[i]; 41 | LMI_FLASH_FMC = LMI_FLASH_FMC_WRKEY | LMI_FLASH_FMC_WRITE; 42 | while (LMI_FLASH_FMC & LMI_FLASH_FMC_WRITE) 43 | ; 44 | } 45 | 46 | stub_exit(0); 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/target/flashstub/lmi.stub: -------------------------------------------------------------------------------- 1 | 0x2300, 0x009C, 0x1909, 0x1C1C, 0x0892, 0x4293, 0xD20E, 0x4E08, 0x1905, 0x6035, 0x590E, 0x4D07, 0x602E, 0x4D07, 0x4E07, 0x602E, 0x682E, 0x07F6, 0xD4FC, 0x3301, 0x3404, 0xE7EE, 0xBE00, 0x46C0, 0xD000, 0x400F, 0xD004, 0x400F, 0xD008, 0x400F, 0x0001, 0xA442, -------------------------------------------------------------------------------- /src/target/flashstub/nrf51.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | 3 | _start: 4 | ldr r0, _ready 5 | ldr r1, _addr 6 | mov r2, pc 7 | add r2, #(_data - . - 2) 8 | ldr r3, _size 9 | _next: 10 | cmp r3, #0 11 | beq _done 12 | @ Write data to flash 13 | ldr r4, [r2] 14 | str r4, [r1] 15 | 16 | _wait: @ Wait for READY bit 17 | ldr r4, [r0] 18 | mov r6, #1 19 | tst r4, r6 20 | beq _wait 21 | 22 | sub r3, #4 23 | add r1, #4 24 | add r2, #4 25 | b _next 26 | _done: 27 | bkpt 28 | 29 | @.align 4 30 | .org 0x24 31 | _ready: 32 | .word 0x4001E400 33 | _addr: 34 | .word 0 35 | _size: 36 | .word 12 37 | _data: 38 | .word 0xAAAAAAAA 39 | .word 0xBBBBBBBB 40 | .word 0xCCCCCCCC 41 | -------------------------------------------------------------------------------- /src/target/flashstub/nrf51.stub: -------------------------------------------------------------------------------- 1 | 0x4808, 0x4909, 0x467A, 0x3228, 0x4B08, 0x2B00, 0xD009, 0x6814, 0x600C, 0x6804, 0x2601, 0x4234, 0xD0FB, 0x3B04, 0x3104, 0x3204, 0xE7F3, 0xBE00, 0xE400, 0x4001, 0x0000, 0x0000, 0x000C, 0x0000, 0xAAAA, 0xAAAA, 0xBBBB, 0xBBBB, 0xCCCC, 0xCCCC, -------------------------------------------------------------------------------- /src/target/flashstub/stm32f1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "libopencm3/stm32/flash.h" 21 | #include "stub.h" 22 | 23 | #define SR_ERROR_MASK 0x14 24 | 25 | void __attribute__((naked)) 26 | stm32f1_flash_write_stub(uint16_t *dest, uint16_t *src, uint32_t size) 27 | { 28 | for (int i; i < size; i += 2) { 29 | FLASH_CR = FLASH_CR_PG; 30 | *dest++ = *src++; 31 | while (FLASH_SR & FLASH_SR_BSY) 32 | ; 33 | } 34 | 35 | if (FLASH_SR & SR_ERROR_MASK) 36 | stub_exit(1); 37 | 38 | stub_exit(0); 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/target/flashstub/stm32f1.stub: -------------------------------------------------------------------------------- 1 | 0x2300, 0x4C09, 0x4293, 0xD209, 0x2601, 0x4D08, 0x602E, 0x5ACD, 0x52C5, 0x6825, 0x07ED, 0xD4FC, 0x3302, 0xE7F2, 0x2314, 0x6822, 0x421A, 0xD000, 0xBE01, 0xBE00, 0x200C, 0x4002, 0x2010, 0x4002, -------------------------------------------------------------------------------- /src/target/flashstub/stm32f4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "libopencm3/stm32/flash.h" 21 | #include "stub.h" 22 | 23 | #define SR_ERROR_MASK 0xF2 24 | 25 | void __attribute__((naked)) 26 | stm32f4_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size) 27 | { 28 | for (int i = 0; i < size; i += 4) { 29 | FLASH_CR = FLASH_CR_PROGRAM_X32 | FLASH_CR_PG; 30 | *dest++ = *src++; 31 | __asm("dsb"); 32 | while (FLASH_SR & FLASH_SR_BSY) 33 | ; 34 | } 35 | 36 | if (FLASH_SR & SR_ERROR_MASK) 37 | stub_exit(1); 38 | 39 | stub_exit(0); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /src/target/flashstub/stm32f4.stub: -------------------------------------------------------------------------------- 1 | 0x2300, 0x4C0A, 0x4293, 0xD20B, 0x4E09, 0x4D0A, 0x602E, 0x58CD, 0x50C5, 0xF3BF, 0x8F4F, 0x6825, 0x03ED, 0xD4FC, 0x3304, 0xE7F0, 0x23F2, 0x6822, 0x421A, 0xD000, 0xBE01, 0xBE00, 0x3C0C, 0x4002, 0x0201, 0x0000, 0x3C10, 0x4002, -------------------------------------------------------------------------------- /src/target/flashstub/stm32l4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "stub.h" 21 | #include 22 | 23 | /* No STM32L4 definitions in libopencm3 yet */ 24 | #define FLASH_SR ((volatile uint32_t *) 0x40022010) 25 | #define FLASH_SR_EOP (1 << 0) 26 | #define SR_ERROR_MASK 0xC3FA 27 | #define FLASH_SR_BSY (1 << 16) 28 | 29 | #define FLASH_CR ((volatile uint32_t *) 0x40022014) 30 | #define FLASH_CR_PG (1 << 0) 31 | #define FLASH_CR_EOPIE (1 << 24) 32 | #define FLASH_CR_ERRIE (1 << 25) 33 | #define FLASH_SR_EOP (1 << 0) 34 | 35 | void __attribute__((naked)) 36 | stm32l4_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size) 37 | { 38 | if ((size & 7) || ((uint32_t)dest & 7)) 39 | stub_exit(1); 40 | for (int i = 0; i < size; i += 8) { 41 | *FLASH_CR = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_PG; 42 | *dest++ = *src++; 43 | *dest++ = *src++; 44 | __asm("dsb"); 45 | while (*FLASH_SR & FLASH_SR_BSY) 46 | ; 47 | if ((*FLASH_SR & SR_ERROR_MASK) || !(*FLASH_SR & FLASH_SR_EOP)) 48 | stub_exit(1); 49 | *FLASH_SR |= FLASH_SR_EOP; 50 | } 51 | *FLASH_CR = 0; 52 | stub_exit(0); 53 | } 54 | -------------------------------------------------------------------------------- /src/target/flashstub/stm32l4.stub: -------------------------------------------------------------------------------- 1 | 0x1C04, 0x4314, 0x2300, 0x0764, 0xD011, 0xBE01, 0xE00F, 0x4C11, 0x6825, 0x03ED, 0xD4FB, 0x6826, 0x4D0F, 0x422E, 0xD115, 0x6825, 0x07ED, 0xD512, 0x2601, 0x6825, 0x3308, 0x4335, 0x6025, 0x4C0B, 0x4293, 0xD20C, 0x4D0A, 0x6025, 0x58CC, 0x50C4, 0x18CC, 0x6865, 0x18C4, 0x6065, 0xF3BF, 0x8F4F, 0xE7E1, 0xBE01, 0xE7EA, 0x2300, 0x6023, 0xBE00, 0x2010, 0x4002, 0xC3FA, 0x0000, 0x2014, 0x4002, 0x0001, 0x0300, -------------------------------------------------------------------------------- /src/target/flashstub/stub.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __STUB_H 21 | #define __STUB_H 22 | 23 | static inline void __attribute__((always_inline)) 24 | stub_exit(const int code) 25 | { 26 | asm("bkpt %0"::"i"(code)); 27 | } 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /src/target/jtag_scan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifndef __JTAG_SCAN_H 22 | #define __JTAG_SCAN_H 23 | 24 | #define JTAG_MAX_DEVS 32 25 | #define JTAG_MAX_IR_LEN 16 26 | 27 | typedef struct jtag_dev_s { 28 | union { 29 | uint8_t dev; 30 | uint8_t dr_prescan; 31 | }; 32 | uint8_t dr_postscan; 33 | 34 | uint8_t ir_len; 35 | uint8_t ir_prescan; 36 | uint8_t ir_postscan; 37 | 38 | uint32_t idcode; 39 | char *descr; 40 | 41 | uint32_t current_ir; 42 | 43 | } jtag_dev_t; 44 | 45 | extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1]; 46 | extern int jtag_dev_count; 47 | 48 | void jtag_dev_write_ir(jtag_dev_t *dev, uint32_t ir); 49 | void jtag_dev_shift_dr(jtag_dev_t *dev, uint8_t *dout, const uint8_t *din, int ticks); 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /src/target/jtagtap_generic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file provides generic forms of the low-level jtagtap functions 22 | * for platforms that don't require optimised forms. 23 | */ 24 | #include "general.h" 25 | #include "jtagtap.h" 26 | 27 | void __attribute__((weak)) 28 | jtagtap_tms_seq(uint32_t MS, int ticks) 29 | { 30 | while(ticks--) { 31 | jtagtap_next(MS & 1, 1); 32 | MS >>= 1; 33 | } 34 | } 35 | 36 | void __attribute__((weak)) 37 | jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) 38 | { 39 | uint8_t index = 1; 40 | while(ticks--) { 41 | if(jtagtap_next(ticks?0:final_tms, *DI & index)) { 42 | *DO |= index; 43 | } else { 44 | *DO &= ~index; 45 | } 46 | if(!(index <<= 1)) { 47 | index = 1; 48 | DI++; DO++; 49 | } 50 | } 51 | } 52 | 53 | void __attribute__((weak)) 54 | jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) 55 | { 56 | uint8_t index = 1; 57 | while(ticks--) { 58 | jtagtap_next(ticks?0:final_tms, *DI & index); 59 | if(!(index <<= 1)) { 60 | index = 1; 61 | DI++; 62 | } 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /src/target/lmi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* This file implements TI/LMI LM3S target specific functions providing 22 | * the XML memory map and Flash memory programming. 23 | * 24 | * According to: TivaTM TM4C123GH6PM Microcontroller Datasheet 25 | */ 26 | 27 | #include "general.h" 28 | #include "target.h" 29 | #include "target_internal.h" 30 | #include "cortexm.h" 31 | 32 | #define SRAM_BASE 0x20000000 33 | #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(lmi_flash_write_stub), 4) 34 | 35 | #define BLOCK_SIZE 0x400 36 | 37 | #define LMI_SCB_BASE 0x400FE000 38 | #define LMI_SCB_DID1 (LMI_SCB_BASE + 0x004) 39 | 40 | #define LMI_FLASH_BASE 0x400FD000 41 | #define LMI_FLASH_FMA (LMI_FLASH_BASE + 0x000) 42 | #define LMI_FLASH_FMC (LMI_FLASH_BASE + 0x008) 43 | 44 | #define LMI_FLASH_FMC_WRITE (1 << 0) 45 | #define LMI_FLASH_FMC_ERASE (1 << 1) 46 | #define LMI_FLASH_FMC_MERASE (1 << 2) 47 | #define LMI_FLASH_FMC_COMT (1 << 3) 48 | #define LMI_FLASH_FMC_WRKEY 0xA4420000 49 | 50 | static int lmi_flash_erase(struct target_flash *f, target_addr addr, size_t len); 51 | static int lmi_flash_write(struct target_flash *f, 52 | target_addr dest, const void *src, size_t len); 53 | 54 | static const char lmi_driver_str[] = "TI Stellaris/Tiva"; 55 | 56 | static const uint16_t lmi_flash_write_stub[] = { 57 | #include "flashstub/lmi.stub" 58 | }; 59 | 60 | static void lmi_add_flash(target *t, size_t length) 61 | { 62 | struct target_flash *f = calloc(1, sizeof(*f)); 63 | f->start = 0; 64 | f->length = length; 65 | f->blocksize = 0x400; 66 | f->erase = lmi_flash_erase; 67 | f->write = lmi_flash_write; 68 | f->align = 4; 69 | f->erased = 0xff; 70 | target_add_flash(t, f); 71 | } 72 | 73 | bool lmi_probe(target *t) 74 | { 75 | uint32_t did1 = target_mem_read32(t, LMI_SCB_DID1); 76 | switch (did1 >> 16) { 77 | case 0x1049: /* LM3S3748 */ 78 | t->driver = lmi_driver_str; 79 | target_add_ram(t, 0x20000000, 0x8000); 80 | lmi_add_flash(t, 0x40000); 81 | return true; 82 | 83 | case 0x10A1: /* TM4C123GH6PM */ 84 | t->driver = lmi_driver_str; 85 | target_add_ram(t, 0x20000000, 0x10000); 86 | lmi_add_flash(t, 0x80000); 87 | return true; 88 | } 89 | return false; 90 | } 91 | 92 | int lmi_flash_erase(struct target_flash *f, target_addr addr, size_t len) 93 | { 94 | target *t = f->t; 95 | while(len) { 96 | target_mem_write32(t, LMI_FLASH_FMA, addr); 97 | target_mem_write32(t, LMI_FLASH_FMC, 98 | LMI_FLASH_FMC_WRKEY | LMI_FLASH_FMC_ERASE); 99 | while (target_mem_read32(t, LMI_FLASH_FMC) & 100 | LMI_FLASH_FMC_ERASE); 101 | 102 | len -= BLOCK_SIZE; 103 | addr += BLOCK_SIZE; 104 | } 105 | return 0; 106 | } 107 | 108 | int lmi_flash_write(struct target_flash *f, 109 | target_addr dest, const void *src, size_t len) 110 | { 111 | target *t = f->t; 112 | 113 | target_mem_write(t, SRAM_BASE, lmi_flash_write_stub, 114 | sizeof(lmi_flash_write_stub)); 115 | target_mem_write(t, STUB_BUFFER_BASE, src, len); 116 | return cortexm_run_stub(t, SRAM_BASE, dest, STUB_BUFFER_BASE, len, 0); 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/target/lpc11xx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Mike Smith 5 | * Copyright (C) 2016 Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #include "general.h" 22 | #include "target.h" 23 | #include "target_internal.h" 24 | #include "cortexm.h" 25 | #include "lpc_common.h" 26 | 27 | #define IAP_PGM_CHUNKSIZE 512 /* should fit in RAM on any device */ 28 | 29 | #define MIN_RAM_SIZE 1024 30 | #define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ 31 | 32 | #define IAP_ENTRYPOINT 0x1fff1ff1 33 | #define IAP_RAM_BASE 0x10000000 34 | 35 | #define LPC11XX_DEVICE_ID 0x400483F4 36 | #define LPC8XX_DEVICE_ID 0x400483F8 37 | 38 | void lpc11xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize) 39 | { 40 | struct lpc_flash *lf = lpc_add_flash(t, addr, len); 41 | lf->f.blocksize = erasesize; 42 | lf->f.buf_size = IAP_PGM_CHUNKSIZE; 43 | lf->f.write_buf = lpc_flash_write_magic_vect; 44 | lf->iap_entry = IAP_ENTRYPOINT; 45 | lf->iap_ram = IAP_RAM_BASE; 46 | lf->iap_msp = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES; 47 | } 48 | 49 | bool 50 | lpc11xx_probe(target *t) 51 | { 52 | uint32_t idcode; 53 | 54 | /* read the device ID register */ 55 | idcode = target_mem_read32(t, LPC11XX_DEVICE_ID); 56 | switch (idcode) { 57 | case 0x041E502B: 58 | case 0x2516D02B: 59 | case 0x0416502B: 60 | case 0x2516902B: /* lpc1111 */ 61 | case 0x2524D02B: 62 | case 0x0425502B: 63 | case 0x2524902B: 64 | case 0x1421102B: /* lpc1112 */ 65 | case 0x0434502B: 66 | case 0x2532902B: 67 | case 0x0434102B: 68 | case 0x2532102B: /* lpc1113 */ 69 | case 0x0444502B: 70 | case 0x2540902B: 71 | case 0x0444102B: 72 | case 0x2540102B: 73 | case 0x1440102B: /* lpc1114 */ 74 | case 0x0A40902B: 75 | case 0x1A40902B: 76 | case 0x2058002B: /* lpc1115 */ 77 | case 0x1431102B: /* lpc11c22 */ 78 | case 0x1430102B: /* lpc11c24 */ 79 | case 0x095C802B: /* lpc11u12x/201 */ 80 | case 0x295C802B: 81 | case 0x097A802B: /* lpc11u13/201 */ 82 | case 0x297A802B: 83 | case 0x0998802B: /* lpc11u14x/201 */ 84 | case 0x2998802B: 85 | case 0x2972402B: /* lpc11u23/301 */ 86 | case 0x2988402B: /* lpc11u24x/301 */ 87 | case 0x2980002B: /* lpc11u24x/401 */ 88 | t->driver = "LPC11xx"; 89 | target_add_ram(t, 0x10000000, 0x2000); 90 | lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000); 91 | return true; 92 | } 93 | 94 | idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); 95 | switch (idcode) { 96 | case 0x00008100: /* LPC810M021FN8 */ 97 | case 0x00008110: /* LPC811M001JDH16 */ 98 | case 0x00008120: /* LPC812M101JDH16 */ 99 | case 0x00008121: /* LPC812M101JD20 */ 100 | case 0x00008122: /* LPC812M101JDH20 / LPC812M101JTB16 */ 101 | t->driver = "LPC81x"; 102 | target_add_ram(t, 0x10000000, 0x1000); 103 | lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400); 104 | return true; 105 | case 0x00008221: /* LPC822M101JHI33 */ 106 | case 0x00008222: /* LPC822M101JDH20 */ 107 | case 0x00008241: /* LPC824M201JHI33 */ 108 | case 0x00008242: /* LPC824M201JDH20 */ 109 | t->driver = "LPC82x"; 110 | target_add_ram(t, 0x10000000, 0x2000); 111 | lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400); 112 | return true; 113 | 114 | } 115 | 116 | return false; 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/target/lpc15xx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Mike Smith 5 | * Copyright (C) 2016 Gareth McMullin 6 | * Copyright (C) 2016 David Lawrence 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program. If not, see . 20 | */ 21 | 22 | #include "general.h" 23 | #include "target.h" 24 | #include "target_internal.h" 25 | #include "cortexm.h" 26 | #include "lpc_common.h" 27 | 28 | #define IAP_PGM_CHUNKSIZE 512 /* should fit in RAM on any device */ 29 | 30 | #define MIN_RAM_SIZE 1024 31 | #define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ 32 | 33 | #define IAP_ENTRYPOINT 0x03000205 34 | #define IAP_RAM_BASE 0x02000000 35 | 36 | #define LPC15XX_DEVICE_ID 0x400743F8 37 | 38 | void lpc15xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize) 39 | { 40 | struct lpc_flash *lf = lpc_add_flash(t, addr, len); 41 | lf->f.blocksize = erasesize; 42 | lf->f.buf_size = IAP_PGM_CHUNKSIZE; 43 | lf->f.write_buf = lpc_flash_write_magic_vect; 44 | lf->iap_entry = IAP_ENTRYPOINT; 45 | lf->iap_ram = IAP_RAM_BASE; 46 | lf->iap_msp = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES; 47 | } 48 | 49 | bool 50 | lpc15xx_probe(target *t) 51 | { 52 | uint32_t idcode; 53 | uint32_t ram_size = 0; 54 | 55 | /* read the device ID register */ 56 | idcode = target_mem_read32(t, LPC15XX_DEVICE_ID); 57 | switch (idcode) { 58 | case 0x00001549: 59 | case 0x00001519: 60 | ram_size = 0x9000; 61 | break; 62 | case 0x00001548: 63 | case 0x00001518: 64 | ram_size = 0x5000; 65 | break; 66 | case 0x00001547: 67 | case 0x00001517: 68 | ram_size = 0x3000; 69 | break; 70 | } 71 | if (ram_size) { 72 | t->driver = "LPC15xx"; 73 | target_add_ram(t, 0x02000000, ram_size); 74 | lpc15xx_add_flash(t, 0x00000000, 0x40000, 0x1000); 75 | return true; 76 | } 77 | 78 | return false; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/target/lpc_common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2015 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | #include "general.h" 20 | #include "target.h" 21 | #include "target_internal.h" 22 | #include "cortexm.h" 23 | #include "lpc_common.h" 24 | 25 | #include 26 | 27 | struct flash_param { 28 | uint16_t opcode; 29 | uint16_t pad0; 30 | uint32_t command; 31 | uint32_t words[4]; 32 | uint32_t result; 33 | } __attribute__((aligned(4))); 34 | 35 | 36 | struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length) 37 | { 38 | struct lpc_flash *lf = calloc(1, sizeof(*lf)); 39 | struct target_flash *f = &lf->f; 40 | f->start = addr; 41 | f->length = length; 42 | f->erase = lpc_flash_erase; 43 | f->write = target_flash_write_buffered; 44 | f->done = target_flash_done_buffered; 45 | f->write_buf = lpc_flash_write; 46 | f->erased = 0xff; 47 | target_add_flash(t, f); 48 | return lf; 49 | } 50 | 51 | enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...) 52 | { 53 | target *t = f->f.t; 54 | struct flash_param param = { 55 | .opcode = ARM_THUMB_BREAKPOINT, 56 | .command = cmd, 57 | }; 58 | 59 | /* Pet WDT before each IAP call, if it is on */ 60 | if (f->wdt_kick) 61 | f->wdt_kick(t); 62 | 63 | /* fill out the remainder of the parameters */ 64 | va_list ap; 65 | va_start(ap, cmd); 66 | for (int i = 0; i < 4; i++) 67 | param.words[i] = va_arg(ap, uint32_t); 68 | va_end(ap); 69 | 70 | /* copy the structure to RAM */ 71 | target_mem_write(t, f->iap_ram, ¶m, sizeof(param)); 72 | 73 | /* set up for the call to the IAP ROM */ 74 | uint32_t regs[t->regs_size / sizeof(uint32_t)]; 75 | target_regs_read(t, regs); 76 | regs[0] = f->iap_ram + offsetof(struct flash_param, command); 77 | regs[1] = f->iap_ram + offsetof(struct flash_param, result); 78 | regs[REG_MSP] = f->iap_msp; 79 | regs[REG_LR] = f->iap_ram | 1; 80 | regs[REG_PC] = f->iap_entry; 81 | target_regs_write(t, regs); 82 | 83 | /* start the target and wait for it to halt again */ 84 | target_halt_resume(t, false); 85 | while (!target_halt_poll(t, NULL)); 86 | 87 | /* copy back just the parameters structure */ 88 | target_mem_read(t, ¶m, f->iap_ram, sizeof(param)); 89 | return param.result; 90 | } 91 | 92 | static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr) 93 | { 94 | return f->base_sector + (addr - f->f.start) / f->f.blocksize; 95 | } 96 | 97 | int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) 98 | { 99 | struct lpc_flash *f = (struct lpc_flash *)tf; 100 | uint32_t start = lpc_sector_for_addr(f, addr); 101 | uint32_t end = lpc_sector_for_addr(f, addr + len - 1); 102 | 103 | if (lpc_iap_call(f, IAP_CMD_PREPARE, start, end, f->bank)) 104 | return -1; 105 | 106 | /* and now erase them */ 107 | if (lpc_iap_call(f, IAP_CMD_ERASE, start, end, CPU_CLK_KHZ, f->bank)) 108 | return -2; 109 | 110 | /* check erase ok */ 111 | if (lpc_iap_call(f, IAP_CMD_BLANKCHECK, start, end, f->bank)) 112 | return -3; 113 | 114 | return 0; 115 | } 116 | 117 | int lpc_flash_write(struct target_flash *tf, 118 | target_addr dest, const void *src, size_t len) 119 | { 120 | struct lpc_flash *f = (struct lpc_flash *)tf; 121 | /* prepare... */ 122 | uint32_t sector = lpc_sector_for_addr(f, dest); 123 | if (lpc_iap_call(f, IAP_CMD_PREPARE, sector, sector, f->bank)) 124 | return -1; 125 | 126 | /* Write payload to target ram */ 127 | uint32_t bufaddr = ALIGN(f->iap_ram + sizeof(struct flash_param), 4); 128 | target_mem_write(f->f.t, bufaddr, src, len); 129 | 130 | /* set the destination address and program */ 131 | if (lpc_iap_call(f, IAP_CMD_PROGRAM, dest, bufaddr, len, CPU_CLK_KHZ)) 132 | return -2; 133 | 134 | return 0; 135 | } 136 | 137 | int lpc_flash_write_magic_vect(struct target_flash *f, 138 | target_addr dest, const void *src, size_t len) 139 | { 140 | if (dest == 0) { 141 | /* Fill in the magic vector to allow booting the flash */ 142 | uint32_t *w = (uint32_t *)src; 143 | uint32_t sum = 0; 144 | 145 | for (unsigned i = 0; i < 7; i++) 146 | sum += w[i]; 147 | w[7] = ~sum + 1; 148 | } 149 | return lpc_flash_write(f, dest, src, len); 150 | } 151 | 152 | -------------------------------------------------------------------------------- /src/target/lpc_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Gareth McMullin 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef __LPC_COMMON_H 21 | #define __LPC_COMMON_H 22 | 23 | enum iap_cmd { 24 | IAP_CMD_INIT = 49, 25 | IAP_CMD_PREPARE = 50, 26 | IAP_CMD_PROGRAM = 51, 27 | IAP_CMD_ERASE = 52, 28 | IAP_CMD_BLANKCHECK = 53, 29 | IAP_CMD_SET_ACTIVE_BANK = 60, 30 | }; 31 | 32 | enum iap_status { 33 | IAP_STATUS_CMD_SUCCESS = 0, 34 | IAP_STATUS_INVALID_COMMAND = 1, 35 | IAP_STATUS_SRC_ADDR_ERROR = 2, 36 | IAP_STATUS_DST_ADDR_ERROR = 3, 37 | IAP_STATUS_SRC_ADDR_NOT_MAPPED = 4, 38 | IAP_STATUS_DST_ADDR_NOT_MAPPED = 5, 39 | IAP_STATUS_COUNT_ERROR = 6, 40 | IAP_STATUS_INVALID_SECTOR = 7, 41 | IAP_STATUS_SECTOR_NOT_BLANK = 8, 42 | IAP_STATUS_SECTOR_NOT_PREPARED = 9, 43 | IAP_STATUS_COMPARE_ERROR = 10, 44 | IAP_STATUS_BUSY = 11, 45 | }; 46 | 47 | /* CPU Frequency */ 48 | #define CPU_CLK_KHZ 12000 49 | 50 | struct lpc_flash { 51 | struct target_flash f; 52 | uint8_t base_sector; 53 | uint8_t bank; 54 | /* Info filled in by specific driver */ 55 | void (*wdt_kick)(target *t); 56 | uint32_t iap_entry; 57 | uint32_t iap_ram; 58 | uint32_t iap_msp; 59 | }; 60 | 61 | struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length); 62 | enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...); 63 | int lpc_flash_erase(struct target_flash *f, target_addr addr, size_t len); 64 | int lpc_flash_write(struct target_flash *f, 65 | target_addr dest, const void *src, size_t len); 66 | int lpc_flash_write_magic_vect(struct target_flash *f, 67 | target_addr dest, const void *src, size_t len); 68 | 69 | #endif 70 | 71 | -------------------------------------------------------------------------------- /src/target/swdptap_generic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2016 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include "general.h" 21 | #include "swdptap.h" 22 | 23 | uint32_t __attribute__((weak)) 24 | swdptap_seq_in(int ticks) 25 | { 26 | uint32_t index = 1; 27 | uint32_t ret = 0; 28 | 29 | while (ticks--) { 30 | if (swdptap_bit_in()) 31 | ret |= index; 32 | index <<= 1; 33 | } 34 | 35 | return ret; 36 | } 37 | 38 | bool __attribute__((weak)) 39 | swdptap_seq_in_parity(uint32_t *ret, int ticks) 40 | { 41 | uint32_t index = 1; 42 | uint8_t parity = 0; 43 | *ret = 0; 44 | 45 | while (ticks--) { 46 | if (swdptap_bit_in()) { 47 | *ret |= index; 48 | parity ^= 1; 49 | } 50 | index <<= 1; 51 | } 52 | if (swdptap_bit_in()) 53 | parity ^= 1; 54 | 55 | return parity; 56 | } 57 | 58 | void __attribute__((weak)) 59 | swdptap_seq_out(uint32_t MS, int ticks) 60 | { 61 | while (ticks--) { 62 | swdptap_bit_out(MS & 1); 63 | MS >>= 1; 64 | } 65 | } 66 | 67 | void __attribute__((weak)) 68 | swdptap_seq_out_parity(uint32_t MS, int ticks) 69 | { 70 | uint8_t parity = 0; 71 | 72 | while (ticks--) { 73 | swdptap_bit_out(MS & 1); 74 | parity ^= MS; 75 | MS >>= 1; 76 | } 77 | swdptap_bit_out(parity & 1); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /upgrade/Makefile: -------------------------------------------------------------------------------- 1 | OUTFILE = blackmagic_upgrade 2 | 3 | CC = $(CROSS_COMPILE)gcc 4 | 5 | CFLAGS = -Wall -Wextra -std=gnu99 -O0 -g -MD -mno-ms-bitfields 6 | LDFLAGS = -lusb 7 | 8 | OBJ = bindata.o \ 9 | dfu.o \ 10 | stm32mem.o \ 11 | main.o 12 | 13 | all: $(OUTFILE) 14 | 15 | $(OUTFILE) $(OUTFILE).exe: $(OBJ) 16 | $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) 17 | 18 | .PHONY: clean 19 | clean: 20 | -rm -rf $(OUTFILE) $(OUTFILE).exe *.d *.o 21 | 22 | -include *.d 23 | 24 | -------------------------------------------------------------------------------- /upgrade/bindata.S: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | .section .rodata 21 | .global _bindata, _bindatalen 22 | 23 | _bindata: 24 | .incbin "../src/blackmagic.bin" 25 | 26 | _bindatalen: 27 | .long (. - _bindata) 28 | 29 | -------------------------------------------------------------------------------- /upgrade/bindata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __BINDATA_H 21 | #define __BINDATA_H 22 | 23 | #ifndef WIN32 24 | #define bindatalen _bindatalen 25 | #define bindata _bindata 26 | #endif 27 | 28 | extern const uint32_t bindatalen; 29 | extern const uint8_t bindata[]; 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /upgrade/dfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | #ifdef WIN32 22 | # include 23 | #else 24 | # include 25 | #endif 26 | 27 | #include "dfu.h" 28 | 29 | /* DFU Requests: Refer to Table 3.2 */ 30 | #define DFU_DETACH 0x00 31 | #define DFU_DNLOAD 0x01 32 | #define DFU_UPLOAD 0x02 33 | #define DFU_GETSTATUS 0x03 34 | #define DFU_CLRSTATUS 0x04 35 | #define DFU_GETSTATE 0x05 36 | #define DFU_ABORT 0x06 37 | 38 | #define USB_DEFAULT_TIMEOUT 1000 39 | #define DFU_DETACH_TIMEOUT 1000 40 | 41 | int dfu_detach(usb_dev_handle *dev, uint16_t iface, uint16_t wTimeout) 42 | { 43 | return usb_control_msg(dev, 44 | USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 45 | DFU_DETACH, wTimeout, iface, NULL, 0, 46 | USB_DEFAULT_TIMEOUT); 47 | } 48 | 49 | int dfu_dnload(usb_dev_handle *dev, uint16_t iface, 50 | uint16_t wBlockNum, void *data, uint16_t size) 51 | { 52 | return usb_control_msg(dev, 53 | USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 54 | DFU_DNLOAD, wBlockNum, iface, data, size, 55 | USB_DEFAULT_TIMEOUT); 56 | } 57 | 58 | int dfu_upload(usb_dev_handle *dev, uint16_t iface, 59 | uint16_t wBlockNum, void *data, uint16_t size) 60 | { 61 | return usb_control_msg(dev, 62 | USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 63 | DFU_DNLOAD, wBlockNum, iface, data, size, 64 | USB_DEFAULT_TIMEOUT); 65 | } 66 | 67 | int dfu_getstatus(usb_dev_handle *dev, uint16_t iface, dfu_status *status) 68 | { 69 | return usb_control_msg(dev, 70 | USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 71 | DFU_GETSTATUS, 0, iface, (void*)status, sizeof(dfu_status), 72 | USB_DEFAULT_TIMEOUT); 73 | } 74 | 75 | int dfu_clrstatus(usb_dev_handle *dev, uint16_t iface) 76 | { 77 | return usb_control_msg(dev, 78 | USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 79 | DFU_CLRSTATUS, 0, iface, NULL, 0, USB_DEFAULT_TIMEOUT); 80 | } 81 | 82 | int dfu_getstate(usb_dev_handle *dev, uint16_t iface) 83 | { 84 | int i; 85 | uint8_t state; 86 | do { 87 | i = usb_control_msg(dev, 88 | USB_ENDPOINT_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 89 | DFU_GETSTATE, 0, iface, (char*)&state, 1, 90 | USB_DEFAULT_TIMEOUT); 91 | } while(i == 0); 92 | 93 | if (i > 0) 94 | return state; 95 | else 96 | return i; 97 | } 98 | 99 | int dfu_abort(usb_dev_handle *dev, uint16_t iface) 100 | { 101 | return usb_control_msg(dev, 102 | USB_ENDPOINT_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 103 | DFU_ABORT, 0, iface, NULL, 0, USB_DEFAULT_TIMEOUT); 104 | } 105 | 106 | 107 | int dfu_makeidle(usb_dev_handle *dev, uint16_t iface) 108 | { 109 | int i; 110 | dfu_status status; 111 | 112 | for(i = 0; i < 3; i++) { 113 | if(dfu_getstatus(dev, iface, &status) < 0) { 114 | dfu_clrstatus(dev, iface); 115 | continue; 116 | } 117 | 118 | i--; 119 | 120 | switch(status.bState) { 121 | case STATE_DFU_IDLE: 122 | return 0; 123 | 124 | case STATE_DFU_DOWNLOAD_SYNC: 125 | case STATE_DFU_DOWNLOAD_IDLE: 126 | case STATE_DFU_MANIFEST_SYNC: 127 | case STATE_DFU_UPLOAD_IDLE: 128 | case STATE_DFU_DOWNLOAD_BUSY: 129 | case STATE_DFU_MANIFEST: 130 | dfu_abort(dev, iface); 131 | continue; 132 | 133 | case STATE_DFU_ERROR: 134 | dfu_clrstatus(dev, iface); 135 | continue; 136 | 137 | case STATE_APP_IDLE: 138 | dfu_detach(dev, iface, DFU_DETACH_TIMEOUT); 139 | continue; 140 | 141 | case STATE_APP_DETACH: 142 | case STATE_DFU_MANIFEST_WAIT_RESET: 143 | usb_reset(dev); 144 | return -1; 145 | 146 | default: 147 | return -1; 148 | } 149 | 150 | } 151 | 152 | return -1; 153 | } 154 | 155 | 156 | -------------------------------------------------------------------------------- /upgrade/dfu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __DFU_H 21 | #define __DFU_H 22 | 23 | #include 24 | 25 | #include 26 | 27 | /* DFU states as returned by DFU_GETSTATE and DFU_GETSTATUS request in bState field. 28 | * Refer to Section 6.1.2 29 | * Refer to Figure A.1 for state diagram 30 | */ 31 | #define STATE_APP_IDLE 0x00 32 | #define STATE_APP_DETACH 0x01 33 | #define STATE_DFU_IDLE 0x02 34 | #define STATE_DFU_DOWNLOAD_SYNC 0x03 35 | #define STATE_DFU_DOWNLOAD_BUSY 0x04 36 | #define STATE_DFU_DOWNLOAD_IDLE 0x05 37 | #define STATE_DFU_MANIFEST_SYNC 0x06 38 | #define STATE_DFU_MANIFEST 0x07 39 | #define STATE_DFU_MANIFEST_WAIT_RESET 0x08 40 | #define STATE_DFU_UPLOAD_IDLE 0x09 41 | #define STATE_DFU_ERROR 0x0a 42 | 43 | /* DFU status codes as returned by DFU_GETSTATUS request in bStatus field. 44 | * Refer to Section 6.1.2 */ 45 | #define DFU_STATUS_OK 0x00 46 | #define DFU_STATUS_ERROR_TARGET 0x01 47 | #define DFU_STATUS_ERROR_FILE 0x02 48 | #define DFU_STATUS_ERROR_WRITE 0x03 49 | #define DFU_STATUS_ERROR_ERASE 0x04 50 | #define DFU_STATUS_ERROR_CHECK_ERASED 0x05 51 | #define DFU_STATUS_ERROR_PROG 0x06 52 | #define DFU_STATUS_ERROR_VERIFY 0x07 53 | #define DFU_STATUS_ERROR_ADDRESS 0x08 54 | #define DFU_STATUS_ERROR_NOTDONE 0x09 55 | #define DFU_STATUS_ERROR_FIRMWARE 0x0a 56 | #define DFU_STATUS_ERROR_VENDOR 0x0b 57 | #define DFU_STATUS_ERROR_USBR 0x0c 58 | #define DFU_STATUS_ERROR_POR 0x0d 59 | #define DFU_STATUS_ERROR_UNKNOWN 0x0e 60 | #define DFU_STATUS_ERROR_STALLEDPKT 0x0f 61 | 62 | /* Device status structure returned by DFU_GETSTATUS request. 63 | * Refer to Section 6.1.2 */ 64 | typedef struct dfu_status { 65 | uint8_t bStatus; 66 | uint32_t bwPollTimeout:24; 67 | uint8_t bState; 68 | uint8_t iString; 69 | } __attribute__((packed)) dfu_status; 70 | 71 | 72 | int dfu_detach(usb_dev_handle *dev, uint16_t iface, uint16_t wTimeout); 73 | int dfu_dnload(usb_dev_handle *dev, uint16_t iface, 74 | uint16_t wBlockNum, void *data, uint16_t size); 75 | int dfu_upload(usb_dev_handle *dev, uint16_t iface, 76 | uint16_t wBlockNum, void *data, uint16_t size); 77 | int dfu_getstatus(usb_dev_handle *dev, uint16_t iface, dfu_status *status); 78 | int dfu_clrstatus(usb_dev_handle *dev, uint16_t iface); 79 | int dfu_getstate(usb_dev_handle *dev, uint16_t iface); 80 | int dfu_abort(usb_dev_handle *dev, uint16_t iface); 81 | 82 | int dfu_makeidle(usb_dev_handle *dev, uint16_t iface); 83 | 84 | 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /upgrade/stm32mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #include 21 | 22 | #ifdef WIN32 23 | # include 24 | # include 25 | #else 26 | # include 27 | # include 28 | #endif 29 | 30 | #include "dfu.h" 31 | #include "stm32mem.h" 32 | 33 | #define STM32_CMD_GETCOMMANDS 0x00 34 | #define STM32_CMD_SETADDRESSPOINTER 0x21 35 | #define STM32_CMD_ERASE 0x41 36 | 37 | static int stm32_download(usb_dev_handle *dev, uint16_t iface, 38 | uint16_t wBlockNum, void *data, int size) 39 | { 40 | dfu_status status; 41 | int i; 42 | 43 | if((i = dfu_dnload(dev, iface, wBlockNum, data, size)) < 0) return i; 44 | while(1) { 45 | if((i = dfu_getstatus(dev, iface, &status)) < 0) return i; 46 | switch(status.bState) { 47 | case STATE_DFU_DOWNLOAD_BUSY: 48 | #ifdef WIN32 49 | Sleep(status.bwPollTimeout); 50 | #else 51 | usleep(status.bwPollTimeout * 1000); 52 | #endif 53 | break; 54 | case STATE_DFU_DOWNLOAD_IDLE: 55 | return 0; 56 | default: 57 | return -1; 58 | } 59 | } 60 | } 61 | 62 | int stm32_mem_erase(usb_dev_handle *dev, uint16_t iface, uint32_t addr) 63 | { 64 | uint8_t request[5]; 65 | 66 | request[0] = STM32_CMD_ERASE; 67 | memcpy(request+1, &addr, sizeof(addr)); 68 | 69 | return stm32_download(dev, iface, 0, request, sizeof(request)); 70 | } 71 | 72 | int stm32_mem_write(usb_dev_handle *dev, uint16_t iface, void *data, int size) 73 | { 74 | return stm32_download(dev, iface, 2, data, size); 75 | } 76 | 77 | int stm32_mem_manifest(usb_dev_handle *dev, uint16_t iface) 78 | { 79 | dfu_status status; 80 | int i; 81 | 82 | if((i = dfu_dnload(dev, iface, 0, NULL, 0)) < 0) return i; 83 | while(1) { 84 | if((i = dfu_getstatus(dev, iface, &status)) < 0) return 0; 85 | #ifdef WIN32 86 | Sleep(status.bwPollTimeout); 87 | #else 88 | usleep(status.bwPollTimeout * 1000); 89 | #endif 90 | switch(status.bState) { 91 | case STATE_DFU_MANIFEST: 92 | return 0; 93 | default: 94 | return -1; 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /upgrade/stm32mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Black Magic Debug project. 3 | * 4 | * Copyright (C) 2011 Black Sphere Technologies Ltd. 5 | * Written by Gareth McMullin 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program. If not, see . 19 | */ 20 | #ifndef __STM32MEM_H 21 | #define __STM32MEM_H 22 | 23 | #ifdef WIN32 24 | # include 25 | #else 26 | # include 27 | #endif 28 | 29 | int stm32_mem_erase(usb_dev_handle *dev, uint16_t iface, uint32_t addr); 30 | int stm32_mem_write(usb_dev_handle *dev, uint16_t iface, void *data, int size); 31 | int stm32_mem_manifest(usb_dev_handle *dev, uint16_t iface); 32 | 33 | #endif 34 | 35 | --------------------------------------------------------------------------------