From 23282d72477b23d245666d4e87d60d090007c1a2 Mon Sep 17 00:00:00 2001 From: besonzore <1670739974@qq.com> Date: Sun, 1 Oct 2017 16:50:08 +0800 Subject: [PATCH] merge the last version from https://github.com/gnu-mcu-eclipse/openocd Revision: 8721a12 Author: Liviu Ionescu Date: 2017-09-03 00:57:08 [#16]; remove duplicate Makefile lines --- src/Makefile.am | 131 +- src/flash/Makefile.am | 30 +- src/flash/common.c | 4 +- src/flash/common.h | 11 +- src/flash/mflash.c | 32 +- src/flash/mflash.h | 10 +- src/flash/nand/Makefile.am | 79 +- src/flash/nand/arm_io.c | 4 +- src/flash/nand/arm_io.h | 10 +- src/flash/nand/at91sam9.c | 4 +- src/flash/nand/core.c | 4 +- src/flash/nand/core.h | 12 +- src/flash/nand/davinci.c | 4 +- src/flash/nand/driver.c | 4 +- src/flash/nand/driver.h | 10 +- src/flash/nand/ecc.c | 5 +- src/flash/nand/ecc_kw.c | 3 + src/flash/nand/fileio.c | 14 +- src/flash/nand/fileio.h | 12 +- src/flash/nand/imp.h | 10 +- src/flash/nand/lpc3180.c | 4 +- src/flash/nand/lpc3180.h | 10 +- src/flash/nand/lpc32xx.c | 4 +- src/flash/nand/lpc32xx.h | 10 +- src/flash/nand/mx3.c | 4 +- src/flash/nand/mx3.h | 9 +- src/flash/nand/mxc.c | 4 +- src/flash/nand/mxc.h | 10 +- src/flash/nand/nonce.c | 4 +- src/flash/nand/nuc910.c | 4 +- src/flash/nand/nuc910.h | 11 +- src/flash/nand/orion.c | 4 +- src/flash/nand/s3c2410.c | 4 +- src/flash/nand/s3c2412.c | 4 +- src/flash/nand/s3c2440.c | 4 +- src/flash/nand/s3c2443.c | 4 +- src/flash/nand/s3c24xx.c | 4 +- src/flash/nand/s3c24xx.h | 10 +- src/flash/nand/s3c24xx_regs.h | 11 +- src/flash/nand/s3c6400.c | 4 +- src/flash/nand/tcl.c | 18 +- src/flash/nor/Makefile.am | 126 +- src/flash/nor/aduc702x.c | 6 +- src/flash/nor/aducm360.c | 4 +- src/flash/nor/at91sam3.c | 16 +- src/flash/nor/at91sam4.c | 934 +- src/flash/nor/at91sam4l.c | 17 +- src/flash/nor/at91sam7.c | 34 +- src/flash/nor/at91samd.c | 149 +- src/flash/nor/atsamv.c | 15 +- src/flash/nor/avrf.c | 5 +- src/flash/nor/cfi.c | 161 +- src/flash/nor/cfi.h | 13 +- src/flash/nor/core.c | 74 +- src/flash/nor/core.h | 38 +- src/flash/nor/driver.h | 10 +- src/flash/nor/drivers.c | 132 +- src/flash/nor/dsp5680xx_flash.c | 4 +- src/flash/nor/efm32.c | 63 +- src/flash/nor/em357.c | 10 +- src/flash/nor/faux.c | 6 +- src/flash/nor/fm3.c | 4 +- src/flash/nor/imp.h | 10 +- src/flash/nor/jtagspi.c | 16 +- src/flash/nor/kinetis.c | 1835 ++- src/flash/nor/lpc2000.c | 21 +- src/flash/nor/lpc288x.c | 4 +- src/flash/nor/lpc2900.c | 13 +- src/flash/nor/lpcspifi.c | 55 +- src/flash/nor/mdr.c | 114 +- src/flash/nor/mrvlqspi.c | 9 +- src/flash/nor/niietcm4.c | 81 +- src/flash/nor/non_cfi.c | 5 +- src/flash/nor/non_cfi.h | 10 +- src/flash/nor/nrf51.c | 110 +- src/flash/nor/numicro.c | 3 + src/flash/nor/ocl.c | 4 +- src/flash/nor/ocl.h | 10 +- src/flash/nor/pic32mx.c | 105 +- src/flash/nor/psoc4.c | 9 +- src/flash/nor/sim3x.c | 7 +- src/flash/nor/spi.c | 23 +- src/flash/nor/spi.h | 9 +- src/flash/nor/stellaris.c | 10 +- src/flash/nor/stm32f1x.c | 8 +- src/flash/nor/stm32f2x.c | 439 +- src/flash/nor/stm32l4x.c | 81 +- src/flash/nor/stm32lx.c | 351 +- src/flash/nor/stmsmi.c | 8 +- src/flash/nor/str7x.c | 6 +- src/flash/nor/str9x.c | 6 +- src/flash/nor/str9xpec.c | 4 +- src/flash/nor/tcl.c | 150 +- src/flash/nor/tms470.c | 4 +- src/flash/nor/virtual.c | 5 +- src/flash/nor/xmc4xxx.c | 139 +- src/hello.c | 4 +- src/hello.h | 6 +- src/helper/Makefile.am | 83 +- src/helper/binarybuffer.c | 80 +- src/helper/binarybuffer.h | 14 +- src/helper/command.c | 10 +- src/helper/command.h | 16 +- src/helper/configuration.c | 4 +- src/helper/configuration.h | 10 +- src/helper/fileio.c | 133 +- src/helper/fileio.h | 19 +- src/helper/ioutil.c | 115 +- src/helper/ioutil.h | 10 +- src/helper/ioutil_stubs.c | 4 +- src/helper/jim-nvp.c | 5 +- src/helper/jim-nvp.h | 8 +- src/helper/list.h | 6 +- src/helper/log.c | 71 +- src/helper/log.h | 12 +- src/helper/options.c | 211 +- src/helper/replacements.c | 4 +- src/helper/replacements.h | 10 +- src/helper/system.h | 10 +- src/helper/time_support.c | 8 +- src/helper/time_support.h | 14 +- src/helper/time_support_common.c | 6 +- src/helper/types.h | 41 +- src/helper/util.c | 4 +- src/helper/util.h | 10 +- src/jtag/Makefile.am | 96 +- src/jtag/adapter.c | 4 +- src/jtag/aice/Makefile.am | 41 +- src/jtag/aice/aice_interface.c | 4 +- src/jtag/aice/aice_interface.h | 11 +- src/jtag/aice/aice_pipe.c | 10 +- src/jtag/aice/aice_pipe.h | 11 +- src/jtag/aice/aice_port.c | 4 +- src/jtag/aice/aice_port.h | 13 +- src/jtag/aice/aice_transport.c | 14 +- src/jtag/aice/aice_transport.h | 10 +- src/jtag/aice/aice_usb.c | 22 +- src/jtag/aice/aice_usb.h | 11 +- src/jtag/commands.c | 4 +- src/jtag/commands.h | 10 +- src/jtag/core.c | 136 +- src/jtag/driver.h | 10 +- src/jtag/drivers/Makefile.am | 212 +- src/jtag/drivers/Makefile.rlink | 4 +- src/jtag/drivers/OpenULINK/Makefile | 4 +- src/jtag/drivers/OpenULINK/include/common.h | 4 +- src/jtag/drivers/OpenULINK/include/delay.h | 4 +- src/jtag/drivers/OpenULINK/include/io.h | 4 +- src/jtag/drivers/OpenULINK/include/jtag.h | 4 +- src/jtag/drivers/OpenULINK/include/main.h | 4 +- src/jtag/drivers/OpenULINK/include/msgtypes.h | 4 +- src/jtag/drivers/OpenULINK/include/protocol.h | 4 +- .../drivers/OpenULINK/include/reg_ezusb.h | 4 +- src/jtag/drivers/OpenULINK/include/usb.h | 4 +- src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 | 4 +- src/jtag/drivers/OpenULINK/src/delay.c | 4 +- src/jtag/drivers/OpenULINK/src/jtag.c | 4 +- src/jtag/drivers/OpenULINK/src/main.c | 4 +- src/jtag/drivers/OpenULINK/src/protocol.c | 4 +- src/jtag/drivers/OpenULINK/src/usb.c | 4 +- src/jtag/drivers/amt_jtagaccel.c | 4 +- src/jtag/drivers/arm-jtag-ew.c | 4 +- src/jtag/drivers/at91rm9200.c | 4 +- src/jtag/drivers/bcm2835gpio.c | 8 +- src/jtag/drivers/bitbang.c | 4 +- src/jtag/drivers/bitbang.h | 10 +- src/jtag/drivers/bitq.c | 4 +- src/jtag/drivers/bitq.h | 10 +- src/jtag/drivers/buspirate.c | 4 +- src/jtag/drivers/cmsis_dap_usb.c | 583 +- src/jtag/drivers/driver.c | 4 +- src/jtag/drivers/dummy.c | 4 +- src/jtag/drivers/ep93xx.c | 4 +- src/jtag/drivers/ftdi.c | 200 +- src/jtag/drivers/gw16012.c | 4 +- src/jtag/drivers/jlink.c | 669 +- src/jtag/drivers/jtag_vpi.c | 6 + src/jtag/drivers/libusb0_common.c | 9 +- src/jtag/drivers/libusb0_common.h | 12 +- src/jtag/drivers/libusb1_common.c | 8 +- src/jtag/drivers/libusb1_common.h | 13 +- src/jtag/drivers/libusb_common.h | 13 +- src/jtag/drivers/minidriver_imp.h | 11 +- src/jtag/drivers/mpsse.c | 105 +- src/jtag/drivers/mpsse.h | 12 +- src/jtag/drivers/opendous.c | 4 +- src/jtag/drivers/openjtag.c | 428 +- src/jtag/drivers/osbdm.c | 4 +- src/jtag/drivers/parport.c | 4 +- src/jtag/drivers/presto.c | 223 +- src/jtag/drivers/remote_bitbang.c | 6 +- src/jtag/drivers/rlink.c | 4 +- src/jtag/drivers/rlink.h | 9 +- src/jtag/drivers/rlink_call.m4 | 4 +- src/jtag/drivers/rlink_dtc_cmd.h | 9 +- src/jtag/drivers/rlink_ep1_cmd.h | 9 +- src/jtag/drivers/rlink_init.m4 | 4 +- src/jtag/drivers/rlink_st7.h | 9 +- src/jtag/drivers/stlink_usb.c | 50 +- src/jtag/drivers/sysfsgpio.c | 4 +- src/jtag/drivers/ti_icdi_usb.c | 15 +- src/jtag/drivers/ulink.c | 12 +- src/jtag/drivers/usb_blaster/Makefile.am | 25 +- .../usb_blaster/ublast2_access_libusb.c | 3 + src/jtag/drivers/usb_blaster/ublast_access.h | 16 +- .../drivers/usb_blaster/ublast_access_ftdi.c | 3 + src/jtag/drivers/usb_blaster/usb_blaster.c | 12 +- src/jtag/drivers/usb_common.c | 4 +- src/jtag/drivers/usb_common.h | 10 +- src/jtag/drivers/usbprog.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtogpio.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtojtagraw.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtopwr.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtoswd.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtoxxx.c | 4 +- .../drivers/versaloon/usbtoxxx/usbtoxxx.h | 10 +- .../versaloon/usbtoxxx/usbtoxxx_internal.h | 10 +- src/jtag/drivers/versaloon/versaloon.c | 4 +- src/jtag/drivers/versaloon/versaloon.h | 11 +- .../drivers/versaloon/versaloon_include.h | 9 +- .../drivers/versaloon/versaloon_internal.h | 10 +- src/jtag/drivers/vsllink.c | 4 +- src/jtag/drivers/w_jtag_sj.c | 10 +- src/jtag/hla/Makefile.am | 34 +- src/jtag/hla/hla_interface.c | 4 +- src/jtag/hla/hla_interface.h | 10 +- src/jtag/hla/hla_layout.c | 4 +- src/jtag/hla/hla_layout.h | 10 +- src/jtag/hla/hla_tcl.c | 14 +- src/jtag/hla/hla_tcl.h | 10 +- src/jtag/hla/hla_transport.c | 4 +- src/jtag/hla/hla_transport.h | 10 +- src/jtag/interface.c | 4 +- src/jtag/interface.h | 4 +- src/jtag/interfaces.c | 36 +- src/jtag/interfaces.h | 4 +- src/jtag/jtag.h | 12 +- src/jtag/minidriver.h | 10 +- src/jtag/minidriver/minidriver_imp.h | 10 +- src/jtag/minidummy/jtag_minidriver.h | 4 +- src/jtag/minidummy/minidummy.c | 4 +- src/jtag/swd.h | 10 +- src/jtag/tcl.c | 16 +- src/jtag/tcl.h | 10 +- src/jtag/zy1000/jtag_minidriver.h | 4 +- src/jtag/zy1000/zy1000.c | 10 +- src/main.c | 4 +- src/openocd.c | 32 +- src/openocd.h | 10 +- src/pld/Makefile.am | 16 +- src/pld/pld.c | 4 +- src/pld/pld.h | 10 +- src/pld/virtex2.c | 4 +- src/pld/virtex2.h | 10 +- src/pld/xilinx_bit.c | 4 +- src/pld/xilinx_bit.h | 10 +- src/rtos/ChibiOS.c | 27 +- src/rtos/FreeRTOS.c | 62 +- src/rtos/Makefile.am | 58 +- src/rtos/ThreadX.c | 13 +- src/rtos/eCos.c | 11 +- src/rtos/embKernel.c | 11 +- src/rtos/linux.c | 17 +- src/rtos/linux_header.h | 5 + src/rtos/mqx.c | 16 +- src/rtos/rtos.c | 84 +- src/rtos/rtos.h | 14 +- src/rtos/rtos_chibios_stackings.c | 4 +- src/rtos/rtos_chibios_stackings.h | 10 +- src/rtos/rtos_ecos_stackings.c | 4 +- src/rtos/rtos_ecos_stackings.h | 10 +- src/rtos/rtos_embkernel_stackings.c | 4 +- src/rtos/rtos_embkernel_stackings.h | 10 +- src/rtos/rtos_mqx_stackings.c | 3 +- src/rtos/rtos_mqx_stackings.h | 10 +- src/rtos/rtos_standard_stackings.c | 63 +- src/rtos/rtos_standard_stackings.h | 12 +- src/server/Makefile.am | 32 +- src/server/gdb_server.c | 301 +- src/server/gdb_server.h | 15 +- src/server/server.c | 112 +- src/server/server.h | 10 +- src/server/server_stubs.c | 4 +- src/server/tcl_server.c | 6 +- src/server/tcl_server.h | 10 +- src/server/telnet_server.c | 38 +- src/server/telnet_server.h | 10 +- src/svf/Makefile.am | 10 +- src/svf/svf.c | 8 +- src/svf/svf.h | 10 +- src/target/Makefile.am | 349 +- src/target/adi_v5_jtag.c | 620 +- src/target/adi_v5_swd.c | 97 +- src/target/algorithm.c | 4 +- src/target/algorithm.h | 12 +- src/target/arm.h | 46 +- src/target/arm11.c | 97 +- src/target/arm11.h | 10 +- src/target/arm11_dbgtap.c | 14 +- src/target/arm11_dbgtap.h | 10 +- src/target/arm720t.c | 14 +- src/target/arm720t.h | 10 +- src/target/arm7_9_common.c | 56 +- src/target/arm7_9_common.h | 26 +- src/target/arm7tdmi.c | 7 +- src/target/arm7tdmi.h | 10 +- src/target/arm920t.c | 18 +- src/target/arm920t.h | 14 +- src/target/arm926ejs.c | 20 +- src/target/arm926ejs.h | 12 +- src/target/arm946e.c | 8 +- src/target/arm946e.h | 10 +- src/target/arm966e.c | 4 +- src/target/arm966e.h | 10 +- src/target/arm9tdmi.c | 6 +- src/target/arm9tdmi.h | 10 +- src/target/arm_adi_v5.c | 905 +- src/target/arm_adi_v5.h | 63 +- src/target/arm_disassembler.c | 6 +- src/target/arm_disassembler.h | 10 +- src/target/arm_dpm.c | 97 +- src/target/arm_dpm.h | 82 +- src/target/arm_jtag.c | 4 +- src/target/arm_jtag.h | 10 +- src/target/arm_opcodes.h | 11 +- src/target/arm_semihosting.c | 543 +- src/target/arm_semihosting.h | 11 +- src/target/arm_simulator.c | 4 +- src/target/arm_simulator.h | 10 +- src/target/armv4_5.c | 177 +- src/target/armv4_5.h | 10 +- src/target/armv4_5_cache.c | 4 +- src/target/armv4_5_cache.h | 10 +- src/target/armv4_5_mmu.c | 4 +- src/target/armv4_5_mmu.h | 15 +- src/target/armv7a.c | 35 +- src/target/armv7a.h | 26 +- src/target/armv7a_cache.c | 3 + src/target/armv7a_cache.h | 9 +- src/target/armv7a_cache_l2x.c | 49 +- src/target/armv7a_cache_l2x.h | 11 +- src/target/armv7m.c | 98 +- src/target/armv7m.h | 22 +- src/target/armv7m_trace.c | 3 + src/target/armv7m_trace.h | 9 +- src/target/avr32_ap7k.c | 18 +- src/target/avr32_ap7k.h | 10 +- src/target/avr32_jtag.c | 4 +- src/target/avr32_jtag.h | 10 +- src/target/avr32_mem.c | 4 +- src/target/avr32_mem.h | 10 +- src/target/avr32_regs.c | 4 +- src/target/avr32_regs.h | 10 +- src/target/avrt.c | 12 +- src/target/avrt.h | 10 +- src/target/breakpoints.c | 49 +- src/target/breakpoints.h | 31 +- src/target/cortex_a.c | 446 +- src/target/cortex_a.h | 12 +- src/target/cortex_m.c | 153 +- src/target/cortex_m.h | 12 +- src/target/dsp563xx.c | 26 +- src/target/dsp563xx.h | 10 +- src/target/dsp563xx_once.c | 4 +- src/target/dsp563xx_once.h | 10 +- src/target/dsp5680xx.c | 22 +- src/target/dsp5680xx.h | 10 +- src/target/embeddedice.c | 4 +- src/target/embeddedice.h | 10 +- src/target/etb.c | 4 +- src/target/etb.h | 10 +- src/target/etm.c | 44 +- src/target/etm.h | 10 +- src/target/etm_dummy.c | 4 +- src/target/etm_dummy.h | 10 +- src/target/fa526.c | 4 +- src/target/feroceon.c | 15 +- src/target/hla_target.c | 26 +- src/target/image.c | 50 +- src/target/image.h | 20 +- src/target/lakemont.c | 42 +- src/target/lakemont.h | 17 +- src/target/mips32.c | 186 +- src/target/mips32.h | 349 +- src/target/mips32_dmaacc.c | 4 +- src/target/mips32_dmaacc.h | 10 +- src/target/mips32_pracc.c | 681 +- src/target/mips32_pracc.h | 40 +- src/target/mips_ejtag.c | 188 +- src/target/mips_ejtag.h | 25 +- src/target/mips_m4k.c | 229 +- src/target/mips_m4k.h | 21 +- src/target/nds32.c | 31 +- src/target/nds32.h | 24 +- src/target/nds32_aice.c | 8 +- src/target/nds32_aice.h | 15 +- src/target/nds32_cmd.c | 8 +- src/target/nds32_cmd.h | 11 +- src/target/nds32_disassembler.c | 4 +- src/target/nds32_disassembler.h | 10 +- src/target/nds32_edm.h | 11 +- src/target/nds32_insn.h | 11 +- src/target/nds32_reg.c | 4 +- src/target/nds32_reg.h | 11 +- src/target/nds32_tlb.c | 12 +- src/target/nds32_tlb.h | 19 +- src/target/nds32_v2.c | 30 +- src/target/nds32_v2.h | 12 +- src/target/nds32_v3.c | 12 +- src/target/nds32_v3.h | 11 +- src/target/nds32_v3_common.c | 26 +- src/target/nds32_v3_common.h | 25 +- src/target/nds32_v3m.c | 12 +- src/target/nds32_v3m.h | 12 +- src/target/oocd_trace.c | 4 +- src/target/oocd_trace.h | 10 +- src/target/openrisc/Makefile.am | 30 +- src/target/openrisc/jsp_server.c | 4 +- src/target/openrisc/jsp_server.h | 6 +- src/target/openrisc/or1k.c | 36 +- src/target/openrisc/or1k.h | 9 +- src/target/openrisc/or1k_du.h | 10 +- src/target/openrisc/or1k_du_adv.c | 3 + src/target/openrisc/or1k_tap.h | 9 +- src/target/openrisc/or1k_tap_mohor.c | 3 + src/target/openrisc/or1k_tap_vjtag.c | 3 + src/target/openrisc/or1k_tap_xilinx_bscan.c | 3 + src/target/quark_x10xx.c | 6 +- src/target/register.c | 4 +- src/target/register.h | 25 +- src/target/smp.c | 7 +- src/target/smp.h | 8 +- src/target/startup.tcl | 14 +- src/target/target.c | 11012 ++++++++-------- src/target/target.h | 72 +- src/target/target_request.c | 4 +- src/target/target_request.h | 10 +- src/target/target_type.h | 46 +- src/target/testee.c | 4 +- src/target/trace.c | 4 +- src/target/trace.h | 10 +- src/target/x86_32_common.c | 98 +- src/target/x86_32_common.h | 27 +- src/target/xscale.c | 56 +- src/target/xscale.h | 10 +- src/transport/Makefile.am | 15 +- src/transport/transport.c | 3 +- src/transport/transport.h | 9 +- src/xsvf/Makefile.am | 10 +- src/xsvf/xsvf.c | 4 +- src/xsvf/xsvf.h | 10 +- 451 files changed, 17313 insertions(+), 12885 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 26e02d085..07981aa67 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,60 +1,41 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libopenocd.la +bin_PROGRAMS += %D%/openocd -SUBDIRS = \ - jtag \ - helper \ - target \ - transport \ - flash \ - svf \ - xsvf \ - pld \ - server \ - rtos +%C%_openocd_SOURCES = \ + %D%/main.c -noinst_LTLIBRARIES = libopenocd.la -bin_PROGRAMS = openocd +%C%_libopenocd_la_SOURCES = \ + %D%/hello.c %D%/hello.h \ + %D%/openocd.c %D%/openocd.h -MAINFILE = main.c +%C%_openocd_LDADD = %D%/libopenocd.la -openocd_SOURCES = $(MAINFILE) -openocd_LDADD = libopenocd.la +%C%_openocd_LDADD += $(MINGWLDADD) if INTERNAL_JIMTCL -openocd_LDADD += $(top_builddir)/jimtcl/libjim.a +%C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a else -openocd_LDADD += -ljim +%C%_openocd_LDADD += -ljim endif -if ULINK -openocd_LDADD += -lm -endif - -libopenocd_la_SOURCES = \ - hello.c \ - openocd.c - -noinst_HEADERS = \ - hello.h \ - openocd.h - -libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\" +%C%_libopenocd_la_CPPFLAGS = # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" if RELEASE -libopenocd_la_CPPFLAGS += -DRELSTR=\"\" -libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" +%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"\" +%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" else -libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" -libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" +%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" +%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" +%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" endif # add default CPPFLAGS -libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) +%C%_libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) # the library search path. -libopenocd_la_LDFLAGS = $(all_libraries) +%C%_libopenocd_la_LDFLAGS = $(all_libraries) if IS_MINGW MINGWLDADD = -lws2_32 @@ -62,55 +43,43 @@ else MINGWLDADD = endif -libopenocd_la_LIBADD = \ - $(top_builddir)/src/xsvf/libxsvf.la \ - $(top_builddir)/src/svf/libsvf.la \ - $(top_builddir)/src/pld/libpld.la \ - $(top_builddir)/src/jtag/libjtag.la \ - $(top_builddir)/src/transport/libtransport.la \ - $(top_builddir)/src/flash/libflash.la \ - $(top_builddir)/src/target/libtarget.la \ - $(top_builddir)/src/server/libserver.la \ - $(top_builddir)/src/rtos/librtos.la \ - $(top_builddir)/src/helper/libhelper.la \ - $(LIBFTDI_LIBS) $(MINGWLDADD) \ - $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) - -STARTUP_TCL_SRCS = \ - $(srcdir)/helper/startup.tcl \ - $(srcdir)/jtag/startup.tcl \ - $(srcdir)/target/startup.tcl \ - $(srcdir)/flash/startup.tcl \ - $(srcdir)/server/startup.tcl +%C%_libopenocd_la_LIBADD = \ + %D%/xsvf/libxsvf.la \ + %D%/svf/libsvf.la \ + %D%/pld/libpld.la \ + %D%/jtag/libjtag.la \ + %D%/transport/libtransport.la \ + %D%/flash/libflash.la \ + %D%/target/libtarget.la \ + %D%/server/libserver.la \ + %D%/rtos/librtos.la \ + %D%/helper/libhelper.la -EXTRA_DIST = $(STARTUP_TCL_SRCS) +BIN2C = $(srcdir)/%D%/helper/bin2char.sh -BUILT_SOURCES = startup_tcl.inc +STARTUP_TCL_SRCS = +EXTRA_DIST += $(STARTUP_TCL_SRCS) -startup.tcl: $(STARTUP_TCL_SRCS) - cat $^ > $@ - -BIN2C = $(top_srcdir)/src/helper/bin2char.sh +BUILT_SOURCES += %D%/startup_tcl.inc # Convert .tcl to c-array -startup_tcl.inc: startup.tcl $(BIN2C) - $(BIN2C) < $< > $@ || { rm -f $@; false; } +%D%/startup_tcl.inc: $(STARTUP_TCL_SRCS) + cat $^ | $(BIN2C) > $@ || { rm -f $@; false; } # add generated files to make clean list -CLEANFILES = startup.tcl startup_tcl.inc +CLEANFILES += %D%/startup_tcl.inc # we do not want generated file in the dist -dist-hook: - rm -f $(distdir)/startup_tcl.inc - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in - -# The "quick" target builds executables & reinstalls the executables -# Primary use: developer types to quicken the edit/compile/debug -# cycle. by not requiring a "full build and full install". Note the -# assumption is: You are only rebuilding the EXE.... and everything -# else is/was previously installed. -# -# use at your own risk -quick: all install-binPROGRAMS - +#dist-hook: +# rm -f $(distdir)/%D%/startup_tcl.inc + +include %D%/helper/Makefile.am +include %D%/jtag/Makefile.am +include %D%/transport/Makefile.am +include %D%/xsvf/Makefile.am +include %D%/svf/Makefile.am +include %D%/target/Makefile.am +include %D%/rtos/Makefile.am +include %D%/server/Makefile.am +include %D%/flash/Makefile.am +include %D%/pld/Makefile.am diff --git a/src/flash/Makefile.am b/src/flash/Makefile.am index ece401837..a1b46f853 100644 --- a/src/flash/Makefile.am +++ b/src/flash/Makefile.am @@ -1,23 +1,13 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libflash.la +%C%_libflash_la_SOURCES = \ + %D%/common.c %D%/common.h \ + %D%/mflash.c %D%/mflash.h -SUBDIRS = \ - nor \ - nand +%C%_libflash_la_LIBADD = \ + %D%/nor/libocdflashnor.la \ + %D%/nand/libocdflashnand.la -METASOURCES = AUTO -noinst_LTLIBRARIES = libflash.la -libflash_la_SOURCES = \ - common.c \ - mflash.c +STARTUP_TCL_SRCS += %D%/startup.tcl -libflash_la_LIBADD = \ - $(top_builddir)/src/flash/nor/libocdflashnor.la \ - $(top_builddir)/src/flash/nand/libocdflashnand.la - -noinst_HEADERS = \ - common.h \ - mflash.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +include %D%/nor/Makefile.am +include %D%/nand/Makefile.am diff --git a/src/flash/common.c b/src/flash/common.c index 878667b80..3e2551192 100644 --- a/src/flash/common.c +++ b/src/flash/common.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/common.h b/src/flash/common.h index 6e32c5520..4244f1360 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_COMMON_H -#define FLASH_COMMON_H +#ifndef OPENOCD_FLASH_COMMON_H +#define OPENOCD_FLASH_COMMON_H #include @@ -46,5 +44,6 @@ bool flash_driver_name_matches(const char *name, const char *expected); #define ERROR_FLASH_SECTOR_NOT_ERASED (-906) #define ERROR_FLASH_BANK_NOT_PROBED (-907) #define ERROR_FLASH_OPER_UNSUPPORTED (-908) +#define ERROR_FLASH_PROTECTED (-909) -#endif /* FLASH_COMMON_H */ +#endif /* OPENOCD_FLASH_COMMON_H */ diff --git a/src/flash/mflash.c b/src/flash/mflash.c index 6f4a988ec..b69995542 100644 --- a/src/flash/mflash.c +++ b/src/flash/mflash.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -749,7 +747,7 @@ COMMAND_HANDLER(mg_write_cmd) { uint32_t address, cnt, res, i; uint8_t *buffer; - struct fileio fileio; + struct fileio *fileio; int ret; if (CMD_ARGC != 3) @@ -764,12 +762,12 @@ COMMAND_HANDLER(mg_write_cmd) size_t filesize; buffer = malloc(MG_FILEIO_CHUNK); if (!buffer) { - fileio_close(&fileio); + fileio_close(fileio); return ERROR_FAIL; } - int retval = fileio_size(&fileio, &filesize); + int retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) { - fileio_close(&fileio); + fileio_close(fileio); free(buffer); return retval; } @@ -782,7 +780,7 @@ COMMAND_HANDLER(mg_write_cmd) size_t buf_cnt; for (i = 0; i < cnt; i++) { - ret = fileio_read(&fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt); + ret = fileio_read(fileio, MG_FILEIO_CHUNK, buffer, &buf_cnt); if (ret != ERROR_OK) goto mg_write_cmd_err; ret = mg_mflash_write(address, buffer, MG_FILEIO_CHUNK); @@ -792,7 +790,7 @@ COMMAND_HANDLER(mg_write_cmd) } if (res) { - ret = fileio_read(&fileio, res, buffer, &buf_cnt); + ret = fileio_read(fileio, res, buffer, &buf_cnt); if (ret != ERROR_OK) goto mg_write_cmd_err; ret = mg_mflash_write(address, buffer, res); @@ -807,13 +805,13 @@ COMMAND_HANDLER(mg_write_cmd) } free(buffer); - fileio_close(&fileio); + fileio_close(fileio); return ERROR_OK; mg_write_cmd_err: free(buffer); - fileio_close(&fileio); + fileio_close(fileio); return ret; } @@ -822,7 +820,7 @@ COMMAND_HANDLER(mg_dump_cmd) { uint32_t address, size, cnt, res, i; uint8_t *buffer; - struct fileio fileio; + struct fileio *fileio; int ret; if (CMD_ARGC != 4) @@ -837,7 +835,7 @@ COMMAND_HANDLER(mg_dump_cmd) buffer = malloc(MG_FILEIO_CHUNK); if (!buffer) { - fileio_close(&fileio); + fileio_close(fileio); return ERROR_FAIL; } @@ -852,7 +850,7 @@ COMMAND_HANDLER(mg_dump_cmd) ret = mg_mflash_read(address, buffer, MG_FILEIO_CHUNK); if (ret != ERROR_OK) goto mg_dump_cmd_err; - ret = fileio_write(&fileio, MG_FILEIO_CHUNK, buffer, &size_written); + ret = fileio_write(fileio, MG_FILEIO_CHUNK, buffer, &size_written); if (ret != ERROR_OK) goto mg_dump_cmd_err; address += MG_FILEIO_CHUNK; @@ -862,7 +860,7 @@ COMMAND_HANDLER(mg_dump_cmd) ret = mg_mflash_read(address, buffer, res); if (ret != ERROR_OK) goto mg_dump_cmd_err; - ret = fileio_write(&fileio, res, buffer, &size_written); + ret = fileio_write(fileio, res, buffer, &size_written); if (ret != ERROR_OK) goto mg_dump_cmd_err; } @@ -875,13 +873,13 @@ COMMAND_HANDLER(mg_dump_cmd) } free(buffer); - fileio_close(&fileio); + fileio_close(fileio); return ERROR_OK; mg_dump_cmd_err: free(buffer); - fileio_close(&fileio); + fileio_close(fileio); return ret; } diff --git a/src/flash/mflash.h b/src/flash/mflash.h index 6f46c7bde..18da40361 100644 --- a/src/flash/mflash.h +++ b/src/flash/mflash.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _MFLASH_H -#define _MFLASH_H +#ifndef OPENOCD_FLASH_MFLASH_H +#define OPENOCD_FLASH_MFLASH_H struct command_context; @@ -288,4 +286,4 @@ typedef enum _mg_opmode { mg_op_mode_stg = 0 /* Only Storage */ } mg_opmode; -#endif +#endif /* OPENOCD_FLASH_MFLASH_H */ diff --git a/src/flash/nand/Makefile.am b/src/flash/nand/Makefile.am index 2ddd096ae..abe90f8bb 100644 --- a/src/flash/nand/Makefile.am +++ b/src/flash/nand/Makefile.am @@ -1,46 +1,43 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdflashnand.la -noinst_LTLIBRARIES = libocdflashnand.la - -libocdflashnand_la_SOURCES = \ - ecc.c \ - ecc_kw.c \ - core.c \ - fileio.c \ - tcl.c \ - arm_io.c \ +%C%_libocdflashnand_la_SOURCES = \ + %D%/ecc.c \ + %D%/ecc_kw.c \ + %D%/core.c \ + %D%/fileio.c \ + %D%/tcl.c \ + %D%/arm_io.c \ $(NAND_DRIVERS) \ - driver.c + %D%/driver.c \ + $(NANDHEADERS) NAND_DRIVERS = \ - nonce.c \ - davinci.c \ - lpc3180.c \ - lpc32xx.c \ - mxc.c \ - mx3.c \ - orion.c \ - s3c24xx.c \ - s3c2410.c \ - s3c2412.c \ - s3c2440.c \ - s3c2443.c \ - s3c6400.c \ - at91sam9.c \ - nuc910.c - -noinst_HEADERS = \ - arm_io.h \ - core.h \ - driver.h \ - fileio.h \ - imp.h \ - lpc3180.h \ - lpc32xx.h \ - mxc.h \ - mx3.h \ - s3c24xx.h \ - s3c24xx_regs.h \ - nuc910.h + %D%/nonce.c \ + %D%/davinci.c \ + %D%/lpc3180.c \ + %D%/lpc32xx.c \ + %D%/mxc.c \ + %D%/mx3.c \ + %D%/orion.c \ + %D%/s3c24xx.c \ + %D%/s3c2410.c \ + %D%/s3c2412.c \ + %D%/s3c2440.c \ + %D%/s3c2443.c \ + %D%/s3c6400.c \ + %D%/at91sam9.c \ + %D%/nuc910.c -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +NANDHEADERS = \ + %D%/arm_io.h \ + %D%/core.h \ + %D%/driver.h \ + %D%/fileio.h \ + %D%/imp.h \ + %D%/lpc3180.h \ + %D%/lpc32xx.h \ + %D%/mxc.h \ + %D%/mx3.h \ + %D%/s3c24xx.h \ + %D%/s3c24xx_regs.h \ + %D%/nuc910.h diff --git a/src/flash/nand/arm_io.c b/src/flash/nand/arm_io.c index d54958adc..e319f9585 100644 --- a/src/flash/nand/arm_io.c +++ b/src/flash/nand/arm_io.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/arm_io.h b/src/flash/nand/arm_io.h index 0ee79a793..8bb311458 100644 --- a/src/flash/nand/arm_io.h +++ b/src/flash/nand/arm_io.h @@ -12,12 +12,10 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ -#ifndef __ARM_NANDIO_H -#define __ARM_NANDIO_H +#ifndef OPENOCD_FLASH_NAND_ARM_IO_H +#define OPENOCD_FLASH_NAND_ARM_IO_H /** * Available operational states the arm_nand_data struct can be in. @@ -54,4 +52,4 @@ struct arm_nand_data { int arm_nandwrite(struct arm_nand_data *nand, uint8_t *data, int size); int arm_nandread(struct arm_nand_data *nand, uint8_t *data, uint32_t size); -#endif /* __ARM_NANDIO_H */ +#endif /* OPENOCD_FLASH_NAND_ARM_IO_H */ diff --git a/src/flash/nand/at91sam9.c b/src/flash/nand/at91sam9.c index 3f4e5e277..0af12b20c 100644 --- a/src/flash/nand/at91sam9.c +++ b/src/flash/nand/at91sam9.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/core.c b/src/flash/nand/core.c index 815c7661f..7428d2253 100644 --- a/src/flash/nand/core.c +++ b/src/flash/nand/core.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/core.h b/src/flash/nand/core.h index 308859bd4..5bf9fb3d1 100644 --- a/src/flash/nand/core.h +++ b/src/flash/nand/core.h @@ -18,13 +18,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NAND_CORE_H -#define FLASH_NAND_CORE_H +#ifndef OPENOCD_FLASH_NAND_CORE_H +#define OPENOCD_FLASH_NAND_CORE_H #include @@ -68,7 +66,7 @@ struct nand_device { int address_cycles; int page_size; int erase_size; - int use_raw; + bool use_raw; int num_blocks; struct nand_block *blocks; struct nand_device *next; @@ -231,4 +229,4 @@ COMMAND_HELPER(nand_command_get_device, unsigned name_index, #define ERROR_NAND_ERROR_CORRECTION_FAILED (-1105) #define ERROR_NAND_NO_BUFFER (-1106) -#endif /* FLASH_NAND_CORE_H */ +#endif /* OPENOCD_FLASH_NAND_CORE_H */ diff --git a/src/flash/nand/davinci.c b/src/flash/nand/davinci.c index c88046d6b..17e6f680d 100644 --- a/src/flash/nand/davinci.c +++ b/src/flash/nand/davinci.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/driver.c b/src/flash/nand/driver.c index 49e13c00a..f7665603f 100644 --- a/src/flash/nand/driver.c +++ b/src/flash/nand/driver.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/driver.h b/src/flash/nand/driver.h index 62bae06ec..2182a7727 100644 --- a/src/flash/nand/driver.h +++ b/src/flash/nand/driver.h @@ -15,13 +15,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NAND_DRIVER_H -#define FLASH_NAND_DRIVER_H +#ifndef OPENOCD_FLASH_NAND_DRIVER_H +#define OPENOCD_FLASH_NAND_DRIVER_H struct nand_device; @@ -102,4 +100,4 @@ typedef int (*nand_driver_walker_t)(struct nand_flash_controller *c, void *); */ int nand_driver_walk(nand_driver_walker_t f, void *x); -#endif /* FLASH_NAND_DRIVER_H */ +#endif /* OPENOCD_FLASH_NAND_DRIVER_H */ diff --git a/src/flash/nand/ecc.c b/src/flash/nand/ecc.c index fba7b1c60..25b2eb10e 100644 --- a/src/flash/nand/ecc.c +++ b/src/flash/nand/ecc.c @@ -21,9 +21,8 @@ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * You should have received a copy of the GNU General Public License along - * with this file; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * As a special exception, if other files instantiate templates or use * macros or inline functions from these files, or you compile these diff --git a/src/flash/nand/ecc_kw.c b/src/flash/nand/ecc_kw.c index 1c3cc70ab..fb3481d00 100644 --- a/src/flash/nand/ecc_kw.c +++ b/src/flash/nand/ecc_kw.c @@ -14,6 +14,9 @@ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/fileio.c b/src/flash/nand/fileio.c index d84ef4f94..64c32c0a8 100644 --- a/src/flash/nand/fileio.c +++ b/src/flash/nand/fileio.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -99,7 +97,7 @@ int nand_fileio_start(struct command_context *cmd_ctx, int nand_fileio_cleanup(struct nand_fileio_state *state) { if (state->file_opened) - fileio_close(&state->fileio); + fileio_close(state->fileio); if (state->oob) { free(state->oob); @@ -134,7 +132,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, if (NULL == nand->device) { command_print(CMD_CTX, "#%s: not probed", CMD_ARGV[0]); - return ERROR_OK; + return ERROR_NAND_DEVICE_NOT_PROBED; } COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], state->address); @@ -169,7 +167,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, if (!need_size) { size_t filesize; - retval = fileio_size(&state->fileio, &filesize); + retval = fileio_size(state->fileio, &filesize); if (retval != ERROR_OK) return retval; state->size = filesize; @@ -190,7 +188,7 @@ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s) size_t one_read; if (NULL != s->page) { - fileio_read(&s->fileio, s->page_size, s->page, &one_read); + fileio_read(s->fileio, s->page_size, s->page, &one_read); if (one_read < s->page_size) memset(s->page + one_read, 0xff, s->page_size - one_read); total_read += one_read; @@ -219,7 +217,7 @@ int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s) ecc += 10; } } else if (NULL != s->oob) { - fileio_read(&s->fileio, s->oob_size, s->oob, &one_read); + fileio_read(s->fileio, s->oob_size, s->oob, &one_read); if (one_read < s->oob_size) memset(s->oob + one_read, 0xff, s->oob_size - one_read); total_read += one_read; diff --git a/src/flash/nand/fileio.h b/src/flash/nand/fileio.h index c92c644fb..af6c7666e 100644 --- a/src/flash/nand/fileio.h +++ b/src/flash/nand/fileio.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NAND_FILEIO_H -#define FLASH_NAND_FILEIO_H +#ifndef OPENOCD_FLASH_NAND_FILEIO_H +#define OPENOCD_FLASH_NAND_FILEIO_H #include #include @@ -37,7 +35,7 @@ struct nand_fileio_state { const int *eccpos; bool file_opened; - struct fileio fileio; + struct fileio *fileio; struct duration bench; }; @@ -55,4 +53,4 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s); -#endif /* FLASH_NAND_FILEIO_H */ +#endif /* OPENOCD_FLASH_NAND_FILEIO_H */ diff --git a/src/flash/nand/imp.h b/src/flash/nand/imp.h index dde17cb8d..c8a4ed9c5 100644 --- a/src/flash/nand/imp.h +++ b/src/flash/nand/imp.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NAND_IMP_H -#define FLASH_NAND_IMP_H +#ifndef OPENOCD_FLASH_NAND_IMP_H +#define OPENOCD_FLASH_NAND_IMP_H #include "core.h" #include "driver.h" @@ -37,4 +35,4 @@ int nand_probe(struct nand_device *nand); int nand_erase(struct nand_device *nand, int first_block, int last_block); int nand_build_bbt(struct nand_device *nand, int first, int last); -#endif /* FLASH_NAND_IMP_H */ +#endif /* OPENOCD_FLASH_NAND_IMP_H */ diff --git a/src/flash/nand/lpc3180.c b/src/flash/nand/lpc3180.c index ff02ffaa6..d15fdce38 100644 --- a/src/flash/nand/lpc3180.c +++ b/src/flash/nand/lpc3180.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/lpc3180.h b/src/flash/nand/lpc3180.h index 4d162fc8c..c02ee5b27 100644 --- a/src/flash/nand/lpc3180.h +++ b/src/flash/nand/lpc3180.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef LPC3180_NAND_CONTROLLER_H -#define LPC3180_NAND_CONTROLLER_H +#ifndef OPENOCD_FLASH_NAND_LPC3180_H +#define OPENOCD_FLASH_NAND_LPC3180_H enum lpc3180_selected_controller { LPC3180_NO_CONTROLLER, @@ -36,4 +34,4 @@ struct lpc3180_nand_controller { uint32_t sw_wp_upper_bound; }; -#endif /*LPC3180_NAND_CONTROLLER_H */ +#endif /* OPENOCD_FLASH_NAND_LPC3180_H */ diff --git a/src/flash/nand/lpc32xx.c b/src/flash/nand/lpc32xx.c index c310f9040..1ed16dfd0 100644 --- a/src/flash/nand/lpc32xx.c +++ b/src/flash/nand/lpc32xx.c @@ -21,9 +21,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/lpc32xx.h b/src/flash/nand/lpc32xx.h index 2b1c1a89e..90b20b247 100644 --- a/src/flash/nand/lpc32xx.h +++ b/src/flash/nand/lpc32xx.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef LPC32xx_NAND_CONTROLLER_H -#define LPC32xx_NAND_CONTROLLER_H +#ifndef OPENOCD_FLASH_NAND_LPC32XX_H +#define OPENOCD_FLASH_NAND_LPC32XX_H enum lpc32xx_selected_controller { LPC32xx_NO_CONTROLLER, @@ -35,4 +33,4 @@ struct lpc32xx_nand_controller { uint32_t sw_wp_upper_bound; }; -#endif /*LPC32xx_NAND_CONTROLLER_H */ +#endif /* OPENOCD_FLASH_NAND_LPC32XX_H */ diff --git a/src/flash/nand/mx3.c b/src/flash/nand/mx3.c index 51fa680fd..b61e47535 100644 --- a/src/flash/nand/mx3.c +++ b/src/flash/nand/mx3.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/mx3.h b/src/flash/nand/mx3.h index 60ec2938c..00664d866 100644 --- a/src/flash/nand/mx3.h +++ b/src/flash/nand/mx3.h @@ -14,11 +14,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_FLASH_NAND_MX3_H +#define OPENOCD_FLASH_NAND_MX3_H + /* * Freescale iMX3* OpenOCD NAND Flash controller support. * @@ -107,3 +108,5 @@ struct mx3_nf_controller { enum mx_nf_finalize_action fin; struct mx3_nf_flags flags; }; + +#endif /* OPENOCD_FLASH_NAND_MX3_H */ diff --git a/src/flash/nand/mxc.c b/src/flash/nand/mxc.c index b91460ef2..5e59b9a6c 100644 --- a/src/flash/nand/mxc.c +++ b/src/flash/nand/mxc.c @@ -20,9 +20,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/mxc.h b/src/flash/nand/mxc.h index 866e0e323..a1887288b 100644 --- a/src/flash/nand/mxc.h +++ b/src/flash/nand/mxc.h @@ -1,4 +1,3 @@ - /*************************************************************************** * Copyright (C) 2009 by Alexei Babich * * Rezonans plc., Chelyabinsk, Russia * @@ -18,11 +17,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_FLASH_NAND_MXC_H +#define OPENOCD_FLASH_NAND_MXC_H + /* * Freescale iMX OpenOCD NAND Flash controller support. * based on Freescale iMX2* and iMX3* OpenOCD NAND Flash controller support. @@ -164,3 +164,5 @@ struct mxc_nf_controller { enum mxc_nf_finalize_action fin; struct mxc_nf_flags flags; }; + +#endif /* OPENOCD_FLASH_NAND_MXC_H */ diff --git a/src/flash/nand/nonce.c b/src/flash/nand/nonce.c index 6b3dbad86..6fda2618e 100644 --- a/src/flash/nand/nonce.c +++ b/src/flash/nand/nonce.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/nuc910.c b/src/flash/nand/nuc910.c index 832eeae41..1a2dd5968 100644 --- a/src/flash/nand/nuc910.c +++ b/src/flash/nand/nuc910.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/nuc910.h b/src/flash/nand/nuc910.h index e0e458f3e..8877cf633 100644 --- a/src/flash/nand/nuc910.h +++ b/src/flash/nand/nuc910.h @@ -13,17 +13,15 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* * NAND controller interface for Nuvoton NUC910 */ -#ifndef NUC910_H -#define NUC910_H +#ifndef OPENOCD_FLASH_NAND_NUC910_H +#define OPENOCD_FLASH_NAND_NUC910_H #define NUC910_FMICSR 0xB000D000 #define NUC910_SMCSR 0xB000D0A0 @@ -56,5 +54,4 @@ /* ECC4 Correction Status (ECC4ST) */ -#endif /* NUC910_H */ - +#endif /* OPENOCD_FLASH_NAND_NUC910_H */ diff --git a/src/flash/nand/orion.c b/src/flash/nand/orion.c index 71f847bf4..69814eca3 100644 --- a/src/flash/nand/orion.c +++ b/src/flash/nand/orion.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c2410.c b/src/flash/nand/s3c2410.c index 2aff7a898..57b51b48c 100644 --- a/src/flash/nand/s3c2410.c +++ b/src/flash/nand/s3c2410.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c2412.c b/src/flash/nand/s3c2412.c index 6cbdc6c05..002378a16 100644 --- a/src/flash/nand/s3c2412.c +++ b/src/flash/nand/s3c2412.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c2440.c b/src/flash/nand/s3c2440.c index b794fabae..44670e6f2 100644 --- a/src/flash/nand/s3c2440.c +++ b/src/flash/nand/s3c2440.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c2443.c b/src/flash/nand/s3c2443.c index 8cd3213f2..ffd3864bf 100644 --- a/src/flash/nand/s3c2443.c +++ b/src/flash/nand/s3c2443.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c24xx.c b/src/flash/nand/s3c24xx.c index b4c15ce49..ae3f13737 100644 --- a/src/flash/nand/s3c24xx.c +++ b/src/flash/nand/s3c24xx.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/flash/nand/s3c24xx.h b/src/flash/nand/s3c24xx.h index c69de2eef..5c7782dab 100644 --- a/src/flash/nand/s3c24xx.h +++ b/src/flash/nand/s3c24xx.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef S3C24xx_NAND_H -#define S3C24xx_NAND_H +#ifndef OPENOCD_FLASH_NAND_S3C24XX_H +#define OPENOCD_FLASH_NAND_S3C24XX_H /* * S3C24XX Series OpenOCD NAND Flash controller support. @@ -77,4 +75,4 @@ int s3c2440_read_block_data(struct nand_device *nand, int s3c2440_write_block_data(struct nand_device *nand, uint8_t *data, int data_size); -#endif /* S3C24xx_NAND_H */ +#endif /* OPENOCD_FLASH_NAND_S3C24XX_H */ diff --git a/src/flash/nand/s3c24xx_regs.h b/src/flash/nand/s3c24xx_regs.h index fc0f96f50..88bc66567 100644 --- a/src/flash/nand/s3c24xx_regs.h +++ b/src/flash/nand/s3c24xx_regs.h @@ -13,17 +13,15 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* * S3C2410 NAND register definitions */ -#ifndef __ASM_ARM_REGS_NAND -#define __ASM_ARM_REGS_NAND +#ifndef OPENOCD_FLASH_NAND_S3C24XX_REGS_H +#define OPENOCD_FLASH_NAND_S3C24XX_REGS_H #define S3C2410_NFREG(x) (x) @@ -128,5 +126,4 @@ #define S3C2412_NFECCERR_MULTIBIT (2) #define S3C2412_NFECCERR_ECCAREA (3) -#endif /* __ASM_ARM_REGS_NAND */ - +#endif /* OPENOCD_FLASH_NAND_S3C24XX_REGS_H */ diff --git a/src/flash/nand/s3c6400.c b/src/flash/nand/s3c6400.c index abbfb2513..7058133bc 100644 --- a/src/flash/nand/s3c6400.c +++ b/src/flash/nand/s3c6400.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c index 750c1f005..d9738c55b 100644 --- a/src/flash/nand/tcl.c +++ b/src/flash/nand/tcl.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -256,7 +254,8 @@ COMMAND_HANDLER(handle_nand_write_command) int bytes_read = nand_fileio_read(nand, &s); if (bytes_read <= 0) { command_print(CMD_CTX, "error while reading file"); - return nand_fileio_cleanup(&s); + nand_fileio_cleanup(&s); + return ERROR_FAIL; } s.size -= bytes_read; @@ -266,7 +265,8 @@ COMMAND_HANDLER(handle_nand_write_command) command_print(CMD_CTX, "failed writing file %s " "to NAND flash %s at offset 0x%8.8" PRIx32, CMD_ARGV[1], CMD_ARGV[0], s.address); - return nand_fileio_cleanup(&s); + nand_fileio_cleanup(&s); + return retval; } s.address += s.page_size; } @@ -360,16 +360,16 @@ COMMAND_HANDLER(handle_nand_dump_command) } if (NULL != s.page) - fileio_write(&s.fileio, s.page_size, s.page, &size_written); + fileio_write(s.fileio, s.page_size, s.page, &size_written); if (NULL != s.oob) - fileio_write(&s.fileio, s.oob_size, s.oob, &size_written); + fileio_write(s.fileio, s.oob_size, s.oob, &size_written); s.size -= nand->page_size; s.address += nand->page_size; } - retval = fileio_size(&s.fileio, &filesize); + retval = fileio_size(s.fileio, &filesize); if (retval != ERROR_OK) return retval; @@ -547,7 +547,7 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name, c->bus_width = 0; c->address_cycles = 0; c->page_size = 0; - c->use_raw = 0; + c->use_raw = false; c->next = NULL; retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c); diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 834e4d47e..c647cbb60 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -1,66 +1,68 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libocdflashnor.la -libocdflashnor_la_SOURCES = \ - core.c \ - tcl.c \ +noinst_LTLIBRARIES += %D%/libocdflashnor.la +%C%_libocdflashnor_la_SOURCES = \ + %D%/core.c \ + %D%/tcl.c \ $(NOR_DRIVERS) \ - drivers.c + %D%/drivers.c \ + $(NORHEADERS) NOR_DRIVERS = \ - aduc702x.c \ - aducm360.c \ - at91sam4.c \ - at91sam4l.c \ - at91samd.c \ - at91sam3.c \ - at91sam7.c \ - atsamv.c \ - avrf.c \ - cfi.c \ - efm32.c \ - em357.c \ - faux.c \ - jtagspi.c \ - lpc2000.c \ - lpc288x.c \ - lpc2900.c \ - lpcspifi.c \ - mdr.c \ - non_cfi.c \ - ocl.c \ - pic32mx.c \ - spi.c \ - stmsmi.c \ - stellaris.c \ - stm32f1x.c \ - stm32f2x.c \ - stm32lx.c \ - stm32l4x.c \ - str7x.c \ - str9x.c \ - str9xpec.c \ - tms470.c \ - virtual.c \ - fm3.c \ - dsp5680xx_flash.c \ - kinetis.c \ - numicro.c \ - nrf51.c \ - mrvlqspi.c \ - psoc4.c \ - sim3x.c \ - xmc4xxx.c \ - niietcm4.c - - -noinst_HEADERS = \ - core.h \ - cfi.h \ - driver.h \ - imp.h \ - non_cfi.h \ - ocl.h \ - spi.h + %D%/aduc702x.c \ + %D%/aducm360.c \ + %D%/ambiqmicro.c \ + %D%/at91sam4.c \ + %D%/at91sam4l.c \ + %D%/at91samd.c \ + %D%/at91sam3.c \ + %D%/at91sam7.c \ + %D%/ath79.c \ + %D%/atsamv.c \ + %D%/avrf.c \ + %D%/cfi.c \ + %D%/dsp5680xx_flash.c \ + %D%/efm32.c \ + %D%/em357.c \ + %D%/faux.c \ + %D%/fespi.c \ + %D%/fm3.c \ + %D%/fm4.c \ + %D%/jtagspi.c \ + %D%/kinetis.c \ + %D%/kinetis_ke.c \ + %D%/lpc2000.c \ + %D%/lpc288x.c \ + %D%/lpc2900.c \ + %D%/lpcspifi.c \ + %D%/mdr.c \ + %D%/mrvlqspi.c \ + %D%/niietcm4.c \ + %D%/non_cfi.c \ + %D%/nrf51.c \ + %D%/numicro.c \ + %D%/ocl.c \ + %D%/pic32mx.c \ + %D%/psoc4.c \ + %D%/sim3x.c \ + %D%/spi.c \ + %D%/stmsmi.c \ + %D%/stellaris.c \ + %D%/stm32f1x.c \ + %D%/stm32f2x.c \ + %D%/stm32lx.c \ + %D%/stm32l4x.c \ + %D%/str7x.c \ + %D%/str9x.c \ + %D%/str9xpec.c \ + %D%/tms470.c \ + %D%/virtual.c \ + %D%/xmc1xxx.c \ + %D%/xmc4xxx.c -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +NORHEADERS = \ + %D%/core.h \ + %D%/cfi.h \ + %D%/driver.h \ + %D%/imp.h \ + %D%/non_cfi.h \ + %D%/ocl.h \ + %D%/spi.h diff --git a/src/flash/nor/aduc702x.c b/src/flash/nor/aduc702x.c index 88522458d..34cc362eb 100644 --- a/src/flash/nor/aduc702x.c +++ b/src/flash/nor/aduc702x.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -373,7 +371,7 @@ static int aduc702x_check_flash_completion(struct target *target, unsigned int t { uint8_t v = 4; - long long endtime = timeval_ms() + timeout_ms; + int64_t endtime = timeval_ms() + timeout_ms; while (1) { target_read_u8(target, ADUC702x_FLASH + ADUC702x_FLASH_FEESTA, &v); if ((v & 4) == 0) diff --git a/src/flash/nor/aducm360.c b/src/flash/nor/aducm360.c index 3e446f539..8681a25af 100644 --- a/src/flash/nor/aducm360.c +++ b/src/flash/nor/aducm360.c @@ -12,6 +12,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ /*************************************************************************** @@ -549,7 +551,7 @@ static int aducm360_check_flash_completion(struct target *target, unsigned int t { uint32_t v = 1; - long long endtime = timeval_ms() + timeout_ms; + int64_t endtime = timeval_ms() + timeout_ms; while (1) { target_read_u32(target, ADUCM360_FLASH_BASE+ADUCM360_FLASH_FEESTA, &v); if ((v & 0x00000001) == 0) diff --git a/src/flash/nor/at91sam3.c b/src/flash/nor/at91sam3.c index 9d119bbf5..1536378df 100644 --- a/src/flash/nor/at91sam3.c +++ b/src/flash/nor/at91sam3.c @@ -8,19 +8,17 @@ * Copyright (C) 2011 by Olivier Schonken (at91sam3x* support) * * * and Jim Norris * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General public License as published by * + * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the * - * GNU General public License for more details. * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * * * - * You should have received a copy of the GNU General public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ****************************************************************************/ /* Some of the the lower level code was based on code supplied by @@ -2177,7 +2175,7 @@ static int EFC_PerformCommand(struct sam3_bank_private *pPrivate, int r; uint32_t v; - long long ms_now, ms_end; + int64_t ms_now, ms_end; /* default */ if (status) @@ -2482,7 +2480,7 @@ static const char *const eproc_names[] = { _unknown, /* 0 */ "arm946es", /* 1 */ "arm7tdmi", /* 2 */ - "cortex-m3", /* 3 */ + "Cortex-M3", /* 3 */ "arm920t", /* 4 */ "arm926ejs", /* 5 */ _unknown, /* 6 */ diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index c40d085a9..ff75b4188 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -9,19 +9,17 @@ * (at91sam3x* & at91sam4 support)* * * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General public License as published by * + * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the * - * GNU General public License for more details. * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * * * - * You should have received a copy of the GNU General public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ****************************************************************************/ /* Some of the the lower level code was based on code supplied by @@ -67,8 +65,9 @@ #define REG_NAME_WIDTH (12) -/* at91sam4s/at91sam4e series (has always one flash bank)*/ +/* at91sam4s/at91sam4e/at91sam4c series (has always one flash bank)*/ #define FLASH_BANK_BASE_S 0x00400000 +#define FLASH_BANK_BASE_C 0x01000000 /* at91sam4sd series (two one flash banks), first bank address */ #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S @@ -77,6 +76,10 @@ /* at91sam4sd32x, second bank address */ #define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2)) +/* at91sam4c32x, first and second bank address */ +#define FLASH_BANK0_BASE_C32 FLASH_BANK_BASE_C +#define FLASH_BANK1_BASE_C32 (FLASH_BANK_BASE_C+(2048*1024/2)) + #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ @@ -260,12 +263,93 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx) /* these are used to *initialize* the "pChip->details" structure. */ static const struct sam4_chip_details all_sam4_details[] = { - - /* Start at91sam4e* series */ - /*atsam4e16e - LQFP144/LFBGA144*/ + /* Start at91sam4c* series */ + /* at91sam4c32e - LQFP144 */ { - .chipid_cidr = 0xA3CC0CE0, - .name = "at91sam4e16e", + .chipid_cidr = 0xA66D0EE0, + .name = "at91sam4c32e", + .total_flash_size = 2024 * 1024, + .total_sram_size = 256 * 1024, + .n_gpnvms = 3, + .n_banks = 2, +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + /* at91sam4c32c - LQFP100 */ + { + .chipid_cidr = 0xA64D0EE0, + .name = "at91sam4c32c", + .total_flash_size = 2024 * 1024, + .total_sram_size = 256 * 1024, + .n_gpnvms = 3, + .n_banks = 2, +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + /* at91sam4c16c - LQFP100 */ + { + .chipid_cidr = 0xA64C0CE0, + .name = "at91sam4c16c", .total_flash_size = 1024 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, @@ -277,9 +361,9 @@ static const struct sam4_chip_details all_sam4_details[] = { .pChip = NULL, .pBank = NULL, .bank_number = 0, - .base_address = FLASH_BANK_BASE_S, + .base_address = FLASH_BANK_BASE_C, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -295,13 +379,11 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - - /* Start at91sam4s* series */ - /*atsam4s16c - LQFP100/BGA100*/ + /* at91sam4c8c - LQFP100 */ { - .chipid_cidr = 0x28AC0CE0, - .name = "at91sam4s16c", - .total_flash_size = 1024 * 1024, + .chipid_cidr = 0xA64C0AE0, + .name = "at91sam4c8c", + .total_flash_size = 512 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, @@ -312,12 +394,12 @@ static const struct sam4_chip_details all_sam4_details[] = { .pChip = NULL, .pBank = NULL, .bank_number = 0, - .base_address = FLASH_BANK_BASE_S, + .base_address = FLASH_BANK_BASE_C, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, - .size_bytes = 1024 * 1024, - .nsectors = 128, + .size_bytes = 512 * 1024, + .nsectors = 64, .sector_size = 8192, .page_size = 512, }, @@ -330,11 +412,11 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s16b - LQFP64/QFN64*/ + /* at91sam4c4c (rev B) - LQFP100 */ { - .chipid_cidr = 0x289C0CE0, - .name = "at91sam4s16b", - .total_flash_size = 1024 * 1024, + .chipid_cidr = 0xA64C0CE5, + .name = "at91sam4c4c", + .total_flash_size = 256 * 1024, .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, @@ -345,12 +427,12 @@ static const struct sam4_chip_details all_sam4_details[] = { .pChip = NULL, .pBank = NULL, .bank_number = 0, - .base_address = FLASH_BANK_BASE_S, + .base_address = FLASH_BANK_BASE_C, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, - .size_bytes = 1024 * 1024, - .nsectors = 128, + .size_bytes = 256 * 1024, + .nsectors = 32, .sector_size = 8192, .page_size = 512, }, @@ -363,12 +445,14 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4sa16b - LQFP64/QFN64*/ + + /* Start at91sam4e* series */ + /*atsam4e16e - LQFP144/LFBGA144*/ { - .chipid_cidr = 0x28970CE0, - .name = "at91sam4sa16b", + .chipid_cidr = 0xA3CC0CE0, + .name = "at91sam4e16e", .total_flash_size = 1024 * 1024, - .total_sram_size = 160 * 1024, + .total_sram_size = 128 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -396,12 +480,14 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s16a - LQFP48/QFN48*/ + + /* Start at91sam4n* series */ + /*atsam4n8a - LQFP48/QFN48*/ { - .chipid_cidr = 0x288C0CE0, - .name = "at91sam4s16a", - .total_flash_size = 1024 * 1024, - .total_sram_size = 128 * 1024, + .chipid_cidr = 0x293B0AE0, + .name = "at91sam4n8a", + .total_flash_size = 512 * 1024, + .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -415,8 +501,8 @@ static const struct sam4_chip_details all_sam4_details[] = { .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, - .size_bytes = 1024 * 1024, - .nsectors = 128, + .size_bytes = 512 * 1024, + .nsectors = 64, .sector_size = 8192, .page_size = 512, }, @@ -429,12 +515,12 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s8c - LQFP100/BGA100*/ + /*atsam4n8b - LQFP64/QFN64*/ { - .chipid_cidr = 0x28AC0AE0, - .name = "at91sam4s8c", + .chipid_cidr = 0x294B0AE0, + .name = "at91sam4n8b", .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -462,12 +548,12 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s8b - LQFP64/BGA64*/ + /*atsam4n8c - LQFP100/TFBGA100/VFBGA100*/ { - .chipid_cidr = 0x289C0AE0, - .name = "at91sam4s8b", + .chipid_cidr = 0x295B0AE0, + .name = "at91sam4n8c", .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .total_sram_size = 64 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -495,12 +581,12 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s8a - LQFP48/BGA48*/ + /*atsam4n16b - LQFP64/QFN64*/ { - .chipid_cidr = 0x288C0AE0, - .name = "at91sam4s8a", - .total_flash_size = 512 * 1024, - .total_sram_size = 128 * 1024, + .chipid_cidr = 0x29460CE0, + .name = "at91sam4n16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 80 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -514,8 +600,8 @@ static const struct sam4_chip_details all_sam4_details[] = { .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, - .size_bytes = 512 * 1024, - .nsectors = 64, + .size_bytes = 1024 * 1024, + .nsectors = 128, .sector_size = 8192, .page_size = 512, }, @@ -528,13 +614,12 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - - /*atsam4s4a - LQFP48/BGA48*/ + /*atsam4n16c - LQFP100/TFBGA100/VFBGA100*/ { - .chipid_cidr = 0x288b09e0, - .name = "at91sam4s4a", - .total_flash_size = 256 * 1024, - .total_sram_size = 64 * 1024, + .chipid_cidr = 0x29560CE0, + .name = "at91sam4n16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 80 * 1024, .n_gpnvms = 2, .n_banks = 1, { @@ -548,8 +633,8 @@ static const struct sam4_chip_details all_sam4_details[] = { .controller_address = 0x400e0a00, .flash_wait_states = 6, /* workaround silicon bug */ .present = 1, - .size_bytes = 256 * 1024, - .nsectors = 32, + .size_bytes = 1024 * 1024, + .nsectors = 128, .sector_size = 8192, .page_size = 512, }, @@ -563,69 +648,550 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /*at91sam4sd32c*/ + /* Start at91sam4s* series */ + /*atsam4s16c - LQFP100/BGA100*/ { - .chipid_cidr = 0x29a70ee0, - .name = "at91sam4sd32c", - .total_flash_size = 2048 * 1024, - .total_sram_size = 160 * 1024, - .n_gpnvms = 3, - .n_banks = 2, - -/* .bank[0] = { */ + .chipid_cidr = 0x28AC0CE0, + .name = "at91sam4s16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, { - { - .probed = 0, - .pChip = NULL, - .pBank = NULL, - .bank_number = 0, - .base_address = FLASH_BANK0_BASE_SD, - .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ - .present = 1, - .size_bytes = 1024 * 1024, - .nsectors = 128, - .sector_size = 8192, - .page_size = 512, - }, +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, -/* .bank[1] = { */ - { - .probed = 0, - .pChip = NULL, - .pBank = NULL, - .bank_number = 1, - .base_address = FLASH_BANK1_BASE_2048K_SD, - .controller_address = 0x400e0c00, - .flash_wait_states = 6, /* workaround silicon bug */ - .present = 1, - .size_bytes = 1024 * 1024, - .nsectors = 128, - .sector_size = 8192, - .page_size = 512, - }, + }, }, }, + /*atsam4s16b - LQFP64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289C0CE0, + .name = "at91sam4s16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, - /*at91sam4sd16c*/ + }, + }, + }, + /*atsam4sa16b - LQFP64/QFN64*/ { - .chipid_cidr = 0x29a70ce0, - .name = "at91sam4sd16c", + .chipid_cidr = 0x28970CE0, + .name = "at91sam4sa16b", .total_flash_size = 1024 * 1024, .total_sram_size = 160 * 1024, - .n_gpnvms = 3, - .n_banks = 2, - -/* .bank[0] = { */ + .n_gpnvms = 2, + .n_banks = 1, { - { - .probed = 0, - .pChip = NULL, - .pBank = NULL, +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /*atsam4s16a - LQFP48/QFN48*/ + { + .chipid_cidr = 0x288C0CE0, + .name = "at91sam4s16a", + .total_flash_size = 1024 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /*atsam4s8c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x28AC0AE0, + .name = "at91sam4s8c", + .total_flash_size = 512 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /*atsam4s8b - LQFP64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289C0AE0, + .name = "at91sam4s8b", + .total_flash_size = 512 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /*atsam4s8a - LQFP48/BGA48*/ + { + .chipid_cidr = 0x288C0AE0, + .name = "at91sam4s8a", + .total_flash_size = 512 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s4c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x28ab09e0, + .name = "at91sam4s4c", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s4b - LQFP64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289b09e0, + .name = "at91sam4s4b", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s4a - LQFP48/QFN48*/ + { + .chipid_cidr = 0x288b09e0, + .name = "at91sam4s4a", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s2c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x28ab07e0, + .name = "at91sam4s2c", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s2b - LQPF64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289b07e0, + .name = "at91sam4s2b", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s2a - LQFP48/QFN48*/ + { + .chipid_cidr = 0x288b07e0, + .name = "at91sam4s2a", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*at91sam4sd32c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x29a70ee0, + .name = "at91sam4sd32c", + .total_flash_size = 2048 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_2048K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd32b - LQFP64/BGA64*/ + { + .chipid_cidr = 0x29970ee0, + .name = "at91sam4sd32b", + .total_flash_size = 2048 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_2048K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd16c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x29a70ce0, + .name = "at91sam4sd16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -641,7 +1207,51 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 1, .base_address = FLASH_BANK1_BASE_1024K_SD, .controller_address = 0x400e0c00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd16b - LQFP64/BGA64*/ + { + .chipid_cidr = 0x29970ce0, + .name = "at91sam4sd16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_1024K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -730,6 +1340,74 @@ static const struct sam4_chip_details all_sam4_details[] = { } }, + /* atsamg55g19 */ + { + .chipid_cidr = 0x24470ae0, + .name = "atsamg55g19", + .total_flash_size = 512 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + + { +/* .bank[0] = */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = 0, + .probed = 0, + .bank_number = 1, + }, + } + }, + + /* atsamg55j19 */ + { + .chipid_cidr = 0x24570ae0, + .name = "atsamg55j19", + .total_flash_size = 512 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + + { +/* .bank[0] = */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = 0, + .probed = 0, + .bank_number = 1, + }, + } + }, + /* terminate */ { .chipid_cidr = 0, @@ -888,7 +1566,7 @@ static int EFC_PerformCommand(struct sam4_bank_private *pPrivate, int r; uint32_t v; - long long ms_now, ms_end; + int64_t ms_now, ms_end; /* default */ if (status) @@ -1237,14 +1915,14 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip, static const char _unknown[] = "unknown"; static const char *const eproc_names[] = { - _unknown, /* 0 */ + "Cortex-M7", /* 0 */ "arm946es", /* 1 */ "arm7tdmi", /* 2 */ - "cortex-m3", /* 3 */ + "Cortex-M3", /* 3 */ "arm920t", /* 4 */ "arm926ejs", /* 5 */ - "cortex-a5", /* 6 */ - "cortex-m4", /* 7 */ + "Cortex-A5", /* 6 */ + "Cortex-M4", /* 7 */ _unknown, /* 8 */ _unknown, /* 9 */ _unknown, /* 10 */ @@ -1265,7 +1943,7 @@ static const char *const nvpsize[] = { "64K bytes", /* 5 */ _unknown, /* 6 */ "128K bytes", /* 7 */ - _unknown, /* 8 */ + "160K bytes", /* 8 */ "256K bytes", /* 9 */ "512K bytes", /* 10 */ _unknown, /* 11 */ @@ -1307,12 +1985,16 @@ static const struct archnames { unsigned value; const char *name; } archnames[] { 0x42, "AT91x42 Series" }, { 0x43, "SAMG51 Series" }, + { 0x44, "SAMG55 Series (49-pin WLCSP)" }, + { 0x45, "SAMG55 Series (64-pin)" }, { 0x47, "SAMG53 Series" }, { 0x55, "AT91x55 Series" }, { 0x60, "AT91SAM7Axx Series" }, { 0x61, "AT91SAM7AQxx Series" }, { 0x63, "AT91x63 Series" }, + { 0x64, "SAM4CxxC (100-pin version)" }, + { 0x66, "SAM4CxxE (144-pin version)" }, { 0x70, "AT91SAM7Sxx Series" }, { 0x71, "AT91SAM7XCxx Series" }, { 0x72, "AT91SAM7SExx Series" }, @@ -1810,15 +2492,17 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command) /* at91sam4s series only has bank 0*/ /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/ case FLASH_BANK_BASE_S: + case FLASH_BANK_BASE_C: bank->driver_priv = &(pChip->details.bank[0]); bank->bank_number = 0; pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pBank = bank; break; - /* Bank 1 of at91sam4sd series */ + /* Bank 1 of at91sam4sd/at91sam4c32 series */ case FLASH_BANK1_BASE_1024K_SD: case FLASH_BANK1_BASE_2048K_SD: + case FLASH_BANK1_BASE_C32: bank->driver_priv = &(pChip->details.bank[1]); bank->bank_number = 1; pChip->details.bank[1].pChip = pChip; diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index fa7cff38c..0a605d5d7 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -647,10 +645,15 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, COMMAND_HANDLER(sam4l_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by SMAP * @@ -659,14 +662,14 @@ COMMAND_HANDLER(sam4l_handle_reset_deassert) * After vectreset SMAP release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing SMAP reset is more important */ } - int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR); + int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR); if (retval2 != ERROR_OK) return retval2; diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index c7334ca53..03f771c87 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -5,19 +5,17 @@ * Copyright (C) 2008 by Gheorghe Guran (atlas) * * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General public License as published by * + * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the * - * GNU General public License for more details. * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * * * - * You should have received a copy of the GNU General public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ****************************************************************************/ /*************************************************************************** @@ -373,10 +371,9 @@ static int at91sam7_read_part_info(struct flash_bank *bank) if (at91sam7_info->cidr != 0) { /* flash already configured, update clock and check for protected sectors */ - struct flash_bank *fb = bank; - struct flash_bank *t_bank = bank; - - while (t_bank) { + for (struct flash_bank *t_bank = bank; t_bank; t_bank = t_bank->next) { + if (t_bank->target != target) + continue; /* re-calculate master clock frequency */ at91sam7_read_clock_info(t_bank); @@ -385,9 +382,6 @@ static int at91sam7_read_part_info(struct flash_bank *bank) /* check protect state */ at91sam7_protect_check(t_bank); - - t_bank = fb->next; - fb = t_bank; } return ERROR_OK; @@ -402,9 +396,10 @@ static int at91sam7_read_part_info(struct flash_bank *bank) if (at91sam7_info->flash_autodetection == 0) { /* banks and sectors are already created, based on data from input file */ - struct flash_bank *fb = bank; - struct flash_bank *t_bank = bank; - while (t_bank) { + for (struct flash_bank *t_bank = bank; t_bank; t_bank = t_bank->next) { + if (t_bank->target != target) + continue; + at91sam7_info = t_bank->driver_priv; at91sam7_info->cidr = cidr; @@ -425,9 +420,6 @@ static int at91sam7_read_part_info(struct flash_bank *bank) /* check protect state */ at91sam7_protect_check(t_bank); - - t_bank = fb->next; - fb = t_bank; } return ERROR_OK; @@ -669,7 +661,7 @@ static int at91sam7_erase_check(struct flash_bank *bank) retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset, bank->sectors[nSector].size, - &blank); + &blank, bank->erased_value); if (retval != ERROR_OK) { fast_check = 0; break; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 2730f71b2..f018e893d 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -38,6 +36,7 @@ #define SAMD_DSU_STATUSA 1 /* DSU status register */ #define SAMD_DSU_DID 0x18 /* Device ID register */ +#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */ #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */ #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */ @@ -73,8 +72,10 @@ #define SAMD_FAMILY_C 0x02 #define SAMD_SERIES_20 0x00 #define SAMD_SERIES_21 0x01 +#define SAMD_SERIES_22 0x02 #define SAMD_SERIES_10 0x02 #define SAMD_SERIES_11 0x03 +#define SAMD_SERIES_09 0x04 /* Device ID macros */ #define SAMD_GET_PROCESSOR(id) (id >> 28) @@ -89,6 +90,13 @@ struct samd_part { uint32_t ram_kb; }; +/* Known SAMD09 parts. DID reset values missing in RM, see + * https://github.com/avrxml/asf/blob/master/sam0/utils/cmsis/samd09/include/ */ +static const struct samd_part samd09_parts[] = { + { 0x0, "SAMD09D14A", 16, 4 }, + { 0x7, "SAMD09C13A", 8, 4 }, +}; + /* Known SAMD10 parts */ static const struct samd_part samd10_parts[] = { { 0x0, "SAMD10D14AMU", 16, 4 }, @@ -151,6 +159,13 @@ static const struct samd_part samd21_parts[] = { { 0xC, "SAMD21E16A", 64, 8 }, { 0xD, "SAMD21E15A", 32, 4 }, { 0xE, "SAMD21E14A", 16, 2 }, + /* Below are B Variants (Table 3-7 from rev I of datasheet) */ + { 0x20, "SAMD21J16B", 64, 8 }, + { 0x21, "SAMD21J15B", 32, 4 }, + { 0x23, "SAMD21G16B", 64, 8 }, + { 0x24, "SAMD21G15B", 32, 4 }, + { 0x26, "SAMD21E16B", 64, 8 }, + { 0x27, "SAMD21E15B", 32, 4 }, }; /* Known SAMR21 parts. */ @@ -187,6 +202,19 @@ static const struct samd_part saml21_parts[] = { { 0x1C, "SAML21E15B", 32, 4 }, }; +/* Known SAML22 parts. */ +static const struct samd_part saml22_parts[] = { + { 0x00, "SAML22N18A", 256, 32 }, + { 0x01, "SAML22N17A", 128, 16 }, + { 0x02, "SAML22N16A", 64, 8 }, + { 0x05, "SAML22J18A", 256, 32 }, + { 0x06, "SAML22J17A", 128, 16 }, + { 0x07, "SAML22J16A", 64, 8 }, + { 0x0A, "SAML22G18A", 256, 32 }, + { 0x0B, "SAML22G17A", 128, 16 }, + { 0x0C, "SAML22G16A", 64, 8 }, +}; + /* Known SAMC20 parts. */ static const struct samd_part samc20_parts[] = { { 0x00, "SAMC20J18A", 256, 32 }, @@ -238,12 +266,16 @@ static const struct samd_family samd_families[] = { samd21_parts, ARRAY_SIZE(samd21_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_21, samr21_parts, ARRAY_SIZE(samr21_parts) }, + { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_09, + samd09_parts, ARRAY_SIZE(samd09_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_10, samd10_parts, ARRAY_SIZE(samd10_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_D, SAMD_SERIES_11, samd11_parts, ARRAY_SIZE(samd11_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_21, saml21_parts, ARRAY_SIZE(saml21_parts) }, + { SAMD_PROCESSOR_M0, SAMD_FAMILY_L, SAMD_SERIES_22, + saml22_parts, ARRAY_SIZE(saml22_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_20, samc20_parts, ARRAY_SIZE(samc20_parts) }, { SAMD_PROCESSOR_M0, SAMD_FAMILY_C, SAMD_SERIES_21, @@ -342,7 +374,7 @@ static int samd_probe(struct flash_bank *bank) part = samd_find_part(id); if (part == NULL) { - LOG_ERROR("Couldn't find part correspoding to DID %08" PRIx32, id); + LOG_ERROR("Couldn't find part corresponding to DID %08" PRIx32, id); return ERROR_FAIL; } @@ -392,39 +424,43 @@ static int samd_probe(struct flash_bank *bank) return ERROR_OK; } -static bool samd_check_error(struct target *target) +static int samd_check_error(struct target *target) { - int ret; - bool error; + int ret, ret2; uint16_t status; ret = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status); if (ret != ERROR_OK) { LOG_ERROR("Can't read NVM status"); - return true; + return ret; } - if (status & 0x001C) { - if (status & (1 << 4)) /* NVME */ - LOG_ERROR("SAMD: NVM Error"); - if (status & (1 << 3)) /* LOCKE */ - LOG_ERROR("SAMD: NVM lock error"); - if (status & (1 << 2)) /* PROGE */ - LOG_ERROR("SAMD: NVM programming error"); + if ((status & 0x001C) == 0) + return ERROR_OK; - error = true; - } else { - error = false; + if (status & (1 << 4)) { /* NVME */ + LOG_ERROR("SAMD: NVM Error"); + ret = ERROR_FLASH_OPERATION_FAILED; + } + + if (status & (1 << 3)) { /* LOCKE */ + LOG_ERROR("SAMD: NVM lock error"); + ret = ERROR_FLASH_PROTECTED; + } + + if (status & (1 << 2)) { /* PROGE */ + LOG_ERROR("SAMD: NVM programming error"); + ret = ERROR_FLASH_OPER_UNSUPPORTED; } /* Clear the error conditions by writing a one to them */ - ret = target_write_u16(target, + ret2 = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status); - if (ret != ERROR_OK) + if (ret2 != ERROR_OK) LOG_ERROR("Can't clear NVM error conditions"); - return error; + return ret; } static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) @@ -443,10 +479,7 @@ static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) return res; /* Check to see if the NVM command resulted in an error condition. */ - if (samd_check_error(target)) - return ERROR_FAIL; - - return ERROR_OK; + return samd_check_error(target); } static int samd_erase_row(struct target *target, uint32_t address) @@ -500,12 +533,19 @@ static int samd_modify_user_row(struct target *target, uint32_t value, uint8_t startb, uint8_t endb) { int res; + uint32_t nvm_ctrlb; + bool manual_wp = true; if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) { LOG_ERROR("Can't modify bits in the requested range"); return ERROR_FAIL; } + /* Check if we need to do manual page write commands */ + res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb); + if (res == ERROR_OK) + manual_wp = (nvm_ctrlb & SAMD_NVM_CTRLB_MANW) != 0; + /* Retrieve the MCU's page size, in bytes. This is also the size of the * entire User Row. */ uint32_t page_size; @@ -528,8 +568,8 @@ static int samd_modify_user_row(struct target *target, uint32_t value, if (!buf) return ERROR_FAIL; - /* Read the user row (comprising one page) by half-words. */ - res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf); + /* Read the user row (comprising one page) by words. */ + res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); if (res != ERROR_OK) goto out_user_row; @@ -548,20 +588,18 @@ static int samd_modify_user_row(struct target *target, uint32_t value, /* Modify */ buf_set_u32(buf, startb, endb - startb + 1, value); - /* Write the page buffer back out to the target. A Flash write will be - * triggered automatically. */ + /* Write the page buffer back out to the target. */ res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); if (res != ERROR_OK) goto out_user_row; - if (samd_check_error(target)) { - res = ERROR_FAIL; - goto out_user_row; + if (manual_wp) { + /* Trigger flash write */ + res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_WAP); + } else { + res = samd_check_error(target); } - /* Success */ - res = ERROR_OK; - out_user_row: free(buf); @@ -601,7 +639,7 @@ static int samd_protect(struct flash_bank *bank, int set, int first, int last) /* We've now applied our changes, however they will be undone by the next * reset unless we also apply them to the LOCK bits in the User Page. The - * LOCK bits start at bit 48, correspoding to Sector 0 and end with bit 63, + * LOCK bits start at bit 48, corresponding to Sector 0 and end with bit 63, * corresponding to Sector 15. A '1' means unlocked and a '0' means * locked. See Table 9-3 in the SAMD20 datasheet for more details. */ @@ -753,18 +791,15 @@ static int samd_write(struct flash_bank *bank, const uint8_t *buffer, * then issue CMD_WP always */ if (manual_wp || pg_offset + 4 * nw < chip->page_size) { res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP); - if (res != ERROR_OK) { - LOG_ERROR("%s: %d", __func__, __LINE__); - goto free_pb; - } - } + } else { + /* Access through AHB is stalled while flash is being programmed */ + usleep(200); - /* Access through AHB is stalled while flash is being programmed */ - usleep(200); + res = samd_check_error(bank->target); + } - if (samd_check_error(bank->target)) { + if (res != ERROR_OK) { LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address); - res = ERROR_FAIL; goto free_pb; } @@ -825,18 +860,23 @@ COMMAND_HANDLER(samd_handle_info_command) COMMAND_HANDLER(samd_handle_chip_erase_command) { struct target *target = get_current_target(CMD_CTX); + int res = ERROR_FAIL; if (target) { /* Enable access to the DSU by disabling the write protect bit */ target_write_u32(target, SAMD_PAC1, (1<<1)); + /* intentionally without error checking - not accessible on secured chip */ + /* Tell the DSU to perform a full chip erase. It takes about 240ms to * perform the erase. */ - target_write_u8(target, SAMD_DSU, (1<<4)); - - command_print(CMD_CTX, "chip erased"); + res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4)); + if (res == ERROR_OK) + command_print(CMD_CTX, "chip erase started"); + else + command_print(CMD_CTX, "write to DSU CTRL failed"); } - return ERROR_OK; + return res; } COMMAND_HANDLER(samd_handle_set_security_command) @@ -987,10 +1027,15 @@ COMMAND_HANDLER(samd_handle_bootloader_command) COMMAND_HANDLER(samd_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by DSU * @@ -999,9 +1044,9 @@ COMMAND_HANDLER(samd_handle_reset_deassert) * After vectreset DSU release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing DSU reset is more important */ } diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c index 08f8bb8ba..73f023896 100644 --- a/src/flash/nor/atsamv.c +++ b/src/flash/nor/atsamv.c @@ -12,15 +12,17 @@ * (atsamv, atsams, and atsame support) * * * * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General public License as published by * + * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS for A PARTICULAR PURPOSE. See the * - * GNU General public License for more details. * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ /* Some of the the lower level code was based on code supplied by @@ -145,7 +147,7 @@ static int samv_efc_perform_command(struct target *target, { int r; uint32_t v; - long long ms_now, ms_end; + int64_t ms_now, ms_end; if (status) *status = 0; @@ -355,12 +357,15 @@ static int samv_probe(struct flash_bank *bank) uint8_t eproc = (device_id >> 5) & 0x7; if (eproc != 0) { - LOG_ERROR("unexpected eproc code: %d was expecting 0 (cortex-m7)", eproc); + LOG_ERROR("unexpected eproc code: %d was expecting 0 (Cortex-M7)", eproc); return ERROR_FAIL; } uint8_t nvm_size_code = (device_id >> 8) & 0xf; switch (nvm_size_code) { + case 10: + bank->size = 512 * 1024; + break; case 12: bank->size = 1024 * 1024; break; diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c index 1984c9ef1..11cc3b2d3 100644 --- a/src/flash/nor/avrf.c +++ b/src/flash/nor/avrf.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -68,6 +66,7 @@ static const struct avrf_type avft_chips_info[] = { * eeprom_page_size, eeprom_page_num */ {"atmega128", 0x9702, 256, 512, 8, 512}, + {"atmega128rfa1", 0xa701, 128, 512, 8, 512}, {"at90can128", 0x9781, 256, 512, 8, 512}, {"at90usb128", 0x9782, 256, 512, 8, 512}, {"atmega164p", 0x940a, 128, 128, 4, 128}, diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index 90d7d83dd..ac0db8271 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -17,9 +17,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -136,6 +134,7 @@ static inline uint32_t flash_address(struct flash_bank *bank, int sector, uint32 static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) { int i; + struct cfi_flash_bank *cfi_info = bank->driver_priv; /* clear whole buffer, to ensure bits that exceed the bus_width * are set to zero @@ -143,7 +142,7 @@ static void cfi_command(struct flash_bank *bank, uint8_t cmd, uint8_t *cmd_buf) for (i = 0; i < CFI_MAX_BUS_WIDTH; i++) cmd_buf[i] = 0; - if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { + if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) { for (i = bank->bus_width; i > 0; i--) *cmd_buf++ = (i & (bank->chip_width - 1)) ? 0x0 : cmd; } else { @@ -167,6 +166,7 @@ static int cfi_send_command(struct flash_bank *bank, uint8_t cmd, uint32_t addre static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { struct target *target = bank->target; + struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH]; int retval; @@ -175,7 +175,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui if (retval != ERROR_OK) return retval; - if (bank->target->endianness == TARGET_LITTLE_ENDIAN) + if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) *val = data[0]; else *val = data[bank->bus_width - 1]; @@ -190,6 +190,7 @@ static int cfi_query_u8(struct flash_bank *bank, int sector, uint32_t offset, ui static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint8_t *val) { struct target *target = bank->target; + struct cfi_flash_bank *cfi_info = bank->driver_priv; uint8_t data[CFI_MAX_BUS_WIDTH]; int i; @@ -199,7 +200,7 @@ static int cfi_get_u8(struct flash_bank *bank, int sector, uint32_t offset, uint if (retval != ERROR_OK) return retval; - if (bank->target->endianness == TARGET_LITTLE_ENDIAN) { + if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) { for (i = 0; i < bank->bus_width / bank->chip_width; i++) data[0] |= data[i]; @@ -236,7 +237,7 @@ static int cfi_query_u16(struct flash_bank *bank, int sector, uint32_t offset, u return retval; } - if (bank->target->endianness == TARGET_LITTLE_ENDIAN) + if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) *val = data[0] | data[bank->bus_width] << 8; else *val = data[bank->bus_width - 1] | data[(2 * bank->bus_width) - 1] << 8; @@ -266,7 +267,7 @@ static int cfi_query_u32(struct flash_bank *bank, int sector, uint32_t offset, u return retval; } - if (bank->target->endianness == TARGET_LITTLE_ENDIAN) + if (cfi_info->endianness == TARGET_LITTLE_ENDIAN) *val = data[0] | data[bank->bus_width] << 8 | data[bank->bus_width * 2] << 16 | data[bank->bus_width * 3] << 24; else @@ -803,6 +804,7 @@ static int cfi_intel_info(struct flash_bank *bank, char *buf, int buf_size) FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command) { struct cfi_flash_bank *cfi_info; + int bus_swap = 0; if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; @@ -832,14 +834,26 @@ FLASH_BANK_COMMAND_HANDLER(cfi_flash_bank_command) cfi_info->x16_as_x8 = 0; cfi_info->jedec_probe = 0; cfi_info->not_cfi = 0; + cfi_info->data_swap = 0; for (unsigned i = 6; i < CMD_ARGC; i++) { if (strcmp(CMD_ARGV[i], "x16_as_x8") == 0) cfi_info->x16_as_x8 = 1; + else if (strcmp(CMD_ARGV[i], "data_swap") == 0) + cfi_info->data_swap = 1; + else if (strcmp(CMD_ARGV[i], "bus_swap") == 0) + bus_swap = 1; else if (strcmp(CMD_ARGV[i], "jedec_probe") == 0) cfi_info->jedec_probe = 1; } + if (bus_swap) + cfi_info->endianness = + bank->target->endianness == TARGET_LITTLE_ENDIAN ? + TARGET_BIG_ENDIAN : TARGET_LITTLE_ENDIAN; + else + cfi_info->endianness = bank->target->endianness; + /* bank wasn't probed yet */ cfi_info->qry[0] = 0xff; @@ -1262,7 +1276,6 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("No working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - ; /* write algorithm code to working area */ retval = target_write_buffer(target, write_algorithm->address, @@ -1284,7 +1297,6 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, goto cleanup; } } - ; /* setup algo registers */ init_reg_param(®_params[0], "r0", 32, PARAM_OUT); @@ -1300,7 +1312,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, busy_pattern_val = cfi_command_val(bank, 0x80); error_pattern_val = cfi_command_val(bank, 0x7e); - LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, + LOG_DEBUG("Using target buffer at " TARGET_ADDR_FMT " and of size 0x%04" PRIx32, source->address, buffer_size); /* Programming main loop */ @@ -1412,50 +1424,50 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t static const uint32_t mips_word_16_code[] = { /* start: */ - MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ - MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ - MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ - MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ - MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ - MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ + MIPS32_LHU(0, 9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ + MIPS32_ADDI(0, 4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ + MIPS32_SH(0, 13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ + MIPS32_SH(0, 15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ + MIPS32_SH(0, 7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ + MIPS32_SH(0, 9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ MIPS32_NOP, /* nop */ /* busy: */ - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ - MIPS32_NOP, /* nop */ - - MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ - MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ - MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ - MIPS32_NOP, /* nop */ - - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_NOP, /* nop */ + + MIPS32_SRL(0, 10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ + MIPS32_AND(0, 11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ + MIPS32_BNE(0, 11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ + MIPS32_NOP, /* nop */ + + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_NOP, /* nop */ - MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ - MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ + MIPS32_XOR(0, 9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ + MIPS32_BEQ(0, 9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ MIPS32_NOP, /* nop */ /* cont: */ - MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ - MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ + MIPS32_ADDI(0, 6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ + MIPS32_BNE(0, 6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ MIPS32_NOP, /* nop */ - MIPS32_LUI(9, 0), /* lui $t1, 0 */ - MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ + MIPS32_LUI(0, 9, 0), /* lui $t1, 0 */ + MIPS32_ORI(0, 9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ - MIPS32_B(4), /* b done ; goto done */ + MIPS32_B(0, 4), /* b done ; goto done */ MIPS32_NOP, /* nop */ /* cont2: */ - MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ - MIPS32_B(NEG16(33)), /* b start ; goto start */ + MIPS32_ADDI(0, 5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ + MIPS32_B(0, NEG16(33)), /* b start ; goto start */ MIPS32_NOP, /* nop */ /* done: */ - MIPS32_SDBBP, /* sdbbp ; break(); */ + MIPS32_SDBBP(0), /* sdbbp ; break(); */ }; mips32_info.common_magic = MIPS32_COMMON_MAGIC; @@ -1527,18 +1539,17 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } - ; - init_reg_param(®_params[0], "a0", 32, PARAM_OUT); - init_reg_param(®_params[1], "a1", 32, PARAM_OUT); - init_reg_param(®_params[2], "a2", 32, PARAM_OUT); - init_reg_param(®_params[3], "a3", 32, PARAM_OUT); - init_reg_param(®_params[4], "t0", 32, PARAM_OUT); - init_reg_param(®_params[5], "t1", 32, PARAM_IN); - init_reg_param(®_params[6], "t4", 32, PARAM_OUT); - init_reg_param(®_params[7], "t5", 32, PARAM_OUT); - init_reg_param(®_params[8], "t6", 32, PARAM_OUT); - init_reg_param(®_params[9], "t7", 32, PARAM_OUT); + init_reg_param(®_params[0], "r4", 32, PARAM_OUT); + init_reg_param(®_params[1], "r5", 32, PARAM_OUT); + init_reg_param(®_params[2], "r6", 32, PARAM_OUT); + init_reg_param(®_params[3], "r7", 32, PARAM_OUT); + init_reg_param(®_params[4], "r8", 32, PARAM_OUT); + init_reg_param(®_params[5], "r9", 32, PARAM_IN); + init_reg_param(®_params[6], "r12", 32, PARAM_OUT); + init_reg_param(®_params[7], "r13", 32, PARAM_OUT); + init_reg_param(®_params[8], "r14", 32, PARAM_OUT); + init_reg_param(®_params[9], "r15", 32, PARAM_OUT); while (count > 0) { uint32_t thisrun_count = (count > buffer_size) ? buffer_size : count; @@ -1907,7 +1918,6 @@ static int cfi_spansion_write_block(struct flash_bank *bank, const uint8_t *buff return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } } - ; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); @@ -1989,7 +1999,9 @@ static int cfi_intel_write_word(struct flash_bank *bank, uint8_t *word, uint32_t uint8_t status; retval = cfi_intel_wait_status_busy(bank, cfi_info->word_write_timeout, &status); - if (retval != 0x80) { + if (retval != ERROR_OK) + return retval; + if (status != 0x80) { retval = cfi_send_command(bank, 0xff, flash_address(bank, 0, 0x0)); if (retval != ERROR_OK) return retval; @@ -2322,6 +2334,8 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of int blk_count; /* number of bus_width bytes for block copy */ uint8_t current_word[CFI_MAX_BUS_WIDTH * 4]; /* word (bus_width size) currently being *programmed */ + uint8_t *swapped_buffer = NULL; + const uint8_t *real_buffer = NULL; int i; int retval; @@ -2348,8 +2362,14 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of return retval; /* replace only bytes that must be written */ - for (i = align; (i < bank->bus_width) && (count > 0); i++, count--) - current_word[i] = *buffer++; + for (i = align; + (i < bank->bus_width) && (count > 0); + i++, count--) + if (cfi_info->data_swap) + /* data bytes are swapped (reverse endianness) */ + current_word[bank->bus_width - i] = *buffer++; + else + current_word[i] = *buffer++; retval = cfi_write_word(bank, current_word, write_p); if (retval != ERROR_OK) @@ -2357,6 +2377,22 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of write_p += bank->bus_width; } + if (cfi_info->data_swap && count) { + swapped_buffer = malloc(count & ~(bank->bus_width - 1)); + switch (bank->bus_width) { + case 2: + buf_bswap16(swapped_buffer, buffer, + count & ~(bank->bus_width - 1)); + break; + case 4: + buf_bswap32(swapped_buffer, buffer, + count & ~(bank->bus_width - 1)); + break; + } + real_buffer = buffer; + buffer = swapped_buffer; + } + /* handle blocks of bus_size aligned bytes */ blk_count = count & ~(bank->bus_width - 1); /* round down, leave tail bytes */ switch (cfi_info->pri_id) { @@ -2426,6 +2462,11 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of return retval; } + if (swapped_buffer) { + buffer = real_buffer + (buffer - swapped_buffer); + free(swapped_buffer); + } + /* return to read array mode, so we can read from flash again for padding */ retval = cfi_reset(bank); if (retval != ERROR_OK) @@ -2442,7 +2483,11 @@ static int cfi_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t of /* replace only bytes that must be written */ for (i = 0; (i < bank->bus_width) && (count > 0); i++, count--) - current_word[i] = *buffer++; + if (cfi_info->data_swap) + /* data bytes are swapped (reverse endianness) */ + current_word[bank->bus_width - i] = *buffer++; + else + current_word[i] = *buffer++; retval = cfi_write_word(bank, current_word, write_p); if (retval != ERROR_OK) diff --git a/src/flash/nor/cfi.h b/src/flash/nor/cfi.h index d92fcc0b1..ed858a9de 100644 --- a/src/flash/nor/cfi.h +++ b/src/flash/nor/cfi.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef CFI_H -#define CFI_H +#ifndef OPENOCD_FLASH_NOR_CFI_H +#define OPENOCD_FLASH_NOR_CFI_H #define CFI_STATUS_POLL_MASK_DQ5_DQ6_DQ7 0xE0 /* DQ5..DQ7 */ #define CFI_STATUS_POLL_MASK_DQ6_DQ7 0xC0 /* DQ6..DQ7 */ @@ -30,6 +28,9 @@ struct cfi_flash_bank { int not_cfi; int probed; + enum target_endianness endianness; + int data_swap; + uint16_t manufacturer; uint16_t device_id; @@ -159,4 +160,4 @@ struct cfi_fixup { #define CFI_MFR_ANY 0xffff #define CFI_ID_ANY 0xffff -#endif /* CFI_H */ +#endif /* OPENOCD_FLASH_NOR_CFI_H */ diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 4410d5c6a..ab69a328b 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -52,10 +50,17 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last) int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) { int retval; + int num_blocks; + + if (bank->num_prot_blocks) + num_blocks = bank->num_prot_blocks; + else + num_blocks = bank->num_sectors; + /* callers may not supply illegal parameters ... */ - if (first < 0 || first > last || last >= bank->num_sectors) { - LOG_ERROR("illegal sector range"); + if (first < 0 || first > last || last >= num_blocks) { + LOG_ERROR("illegal protection block range"); return ERROR_FAIL; } @@ -71,11 +76,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) * the target could have reset, power cycled, been hot plugged, * the application could have run, etc. * - * Drivers only receive valid sector range. + * Drivers only receive valid protection block range. */ retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) - LOG_ERROR("failed setting protection for areas %d to %d", first, last); + LOG_ERROR("failed setting protection for blocks %d to %d", first, last); return retval; } @@ -290,7 +295,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank) goto done; for (nBytes = 0; nBytes < chunk; nBytes++) { - if (buffer[nBytes] != 0xFF) { + if (buffer[nBytes] != bank->erased_value) { bank->sectors[i].is_erased = 0; break; } @@ -321,12 +326,12 @@ int default_flash_blank_check(struct flash_bank *bank) uint32_t address = bank->base + bank->sectors[i].offset; uint32_t size = bank->sectors[i].size; - retval = target_blank_check_memory(target, address, size, &blank); + retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value); if (retval != ERROR_OK) { fast_check = 0; break; } - if (blank == 0xFF) + if (blank == bank->erased_value) bank->sectors[i].is_erased = 1; else bank->sectors[i].is_erased = 0; @@ -345,8 +350,9 @@ int default_flash_blank_check(struct flash_bank *bank) * and address. Maps an address range to a set of sectors, and issues * the callback() on that set ... e.g. to erase or unprotect its members. * - * (Note a current bad assumption: that protection operates on the same - * size sectors as erase operations use.) + * Parameter iterate_protect_blocks switches iteration of protect block + * instead of erase sectors. If there is no protect blocks array, sectors + * are used in iteration, so compatibility for old flash drivers is retained. * * The "pad_reason" parameter is a kind of boolean: when it's NULL, the * range must fit those sectors exactly. This is clearly safe; it can't @@ -357,13 +363,16 @@ int default_flash_blank_check(struct flash_bank *bank) */ static int flash_iterate_address_range_inner(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, + bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; + struct flash_sector *block_array; uint32_t last_addr = addr + length; /* first address AFTER end */ int first = -1; int last = -1; int i; + int num_blocks; int retval = get_flash_bank_by_addr(target, addr, true, &c); if (retval != ERROR_OK) @@ -390,13 +399,21 @@ static int flash_iterate_address_range_inner(struct target *target, return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } - /** @todo: handle erasures that cross into adjacent banks */ - addr -= c->base; last_addr -= c->base; - for (i = 0; i < c->num_sectors; i++) { - struct flash_sector *f = c->sectors + i; + if (iterate_protect_blocks && c->prot_blocks && c->num_prot_blocks) { + block_array = c->prot_blocks; + num_blocks = c->num_prot_blocks; + } else { + block_array = c->sectors; + num_blocks = c->num_sectors; + iterate_protect_blocks = false; + } + + + for (i = 0; i < num_blocks; i++) { + struct flash_sector *f = &block_array[i]; uint32_t end = f->offset + f->size; /* start only on a sector boundary */ @@ -474,6 +491,7 @@ static int flash_iterate_address_range_inner(struct target *target, */ static int flash_iterate_address_range(struct target *target, char *pad_reason, uint32_t addr, uint32_t length, + bool iterate_protect_blocks, int (*callback)(struct flash_bank *bank, int first, int last)) { struct flash_bank *c; @@ -493,6 +511,7 @@ static int flash_iterate_address_range(struct target *target, } retval = flash_iterate_address_range_inner(target, pad_reason, addr, cur_length, + iterate_protect_blocks, callback); if (retval != ERROR_OK) break; @@ -508,7 +527,7 @@ int flash_erase_address_range(struct target *target, bool pad, uint32_t addr, uint32_t length) { return flash_iterate_address_range(target, pad ? "erase" : NULL, - addr, length, &flash_driver_erase); + addr, length, false, &flash_driver_erase); } static int flash_driver_unprotect(struct flash_bank *bank, int first, int last) @@ -523,7 +542,7 @@ int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t le * and doesn't restore it. */ return flash_iterate_address_range(target, "unprotect", - addr, length, &flash_driver_unprotect); + addr, length, true, &flash_driver_unprotect); } static int compare_section(const void *a, const void *b) @@ -764,3 +783,22 @@ int flash_write(struct target *target, struct image *image, { return flash_write_unlock(target, image, written, erase, false); } + +struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks) +{ + int i; + + struct flash_sector *array = calloc(num_blocks, sizeof(struct flash_sector)); + if (array == NULL) + return NULL; + + for (i = 0; i < num_blocks; i++) { + array[i].offset = offset; + array[i].size = size; + array[i].is_erased = -1; + array[i].is_protected = -1; + offset += size; + } + + return array; +} diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index 726dd957e..338363e2a 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NOR_CORE_H -#define FLASH_NOR_CORE_H +#ifndef OPENOCD_FLASH_NOR_CORE_H +#define OPENOCD_FLASH_NOR_CORE_H #include @@ -48,6 +46,8 @@ struct flash_sector { /** * Indication of erasure status: 0 = not erased, 1 = erased, * other = unknown. Set by @c flash_driver_s::erase_check. + * + * Flag is not used in protection block */ int is_erased; /** @@ -58,6 +58,9 @@ struct flash_sector { * This information must be considered stale immediately. * A million things could make it stale: power cycle, * reset of target, code running on target, etc. + * + * If a flash_bank uses an extra array of protection blocks, + * protection flag is not valid in sector array */ int is_protected; }; @@ -87,6 +90,9 @@ struct flash_bank { int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ + /** Erased value. Defaults to 0xFF. */ + uint8_t erased_value; + /** Default padded value used, normally this matches the flash * erased value. Defaults to 0xFF. */ uint8_t default_padded_value; @@ -97,9 +103,19 @@ struct flash_bank { * some non-zero value during "probe()" or "auto_probe()". */ int num_sectors; - /** Array of sectors, allocated and initilized by the flash driver */ + /** Array of sectors, allocated and initialized by the flash driver */ struct flash_sector *sectors; + /** + * The number of protection blocks in this bank. This value + * is set intially to 0 and sectors are used as protection blocks. + * Driver probe can set protection blocks array to work with + * protection granularity different than sector size. + */ + int num_prot_blocks; + /** Array of protection blocks, allocated and initilized by the flash driver */ + struct flash_sector *prot_blocks; + struct flash_bank *next; /**< The next flash bank on this chip */ }; @@ -207,5 +223,13 @@ struct flash_bank *get_flash_bank_by_num_noprobe(int num); */ int get_flash_bank_by_addr(struct target *target, uint32_t addr, bool check, struct flash_bank **result_bank); +/** + * Allocate and fill an array of sectors or protection blocks. + * @param offset Offset of first block. + * @param size Size of each block. + * @param num_blocks Number of blocks in array. + * @returns A struct flash_sector pointer or NULL when allocation failed. + */ +struct flash_sector *alloc_block_array(uint32_t offset, uint32_t size, int num_blocks); -#endif /* FLASH_NOR_CORE_H */ +#endif /* OPENOCD_FLASH_NOR_CORE_H */ diff --git a/src/flash/nor/driver.h b/src/flash/nor/driver.h index 8f2e1cc23..0ae4d8e20 100644 --- a/src/flash/nor/driver.h +++ b/src/flash/nor/driver.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NOR_DRIVER_H -#define FLASH_NOR_DRIVER_H +#ifndef OPENOCD_FLASH_NOR_DRIVER_H +#define OPENOCD_FLASH_NOR_DRIVER_H struct flash_bank; @@ -223,4 +221,4 @@ struct flash_driver { */ struct flash_driver *flash_driver_find_by_name(const char *name); -#endif /* FLASH_NOR_DRIVER_H */ +#endif /* OPENOCD_FLASH_NOR_DRIVER_H */ diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 48d584ee3..9702e591f 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -22,96 +20,112 @@ #endif #include "imp.h" -extern struct flash_driver lpc2000_flash; -extern struct flash_driver lpc288x_flash; -extern struct flash_driver lpc2900_flash; -extern struct flash_driver lpcspifi_flash; -extern struct flash_driver cfi_flash; +extern struct flash_driver aduc702x_flash; +extern struct flash_driver aducm360_flash; +extern struct flash_driver ambiqmicro_flash; extern struct flash_driver at91sam3_flash; extern struct flash_driver at91sam4_flash; extern struct flash_driver at91sam4l_flash; -extern struct flash_driver at91samd_flash; extern struct flash_driver at91sam7_flash; +extern struct flash_driver at91samd_flash; +extern struct flash_driver ath79_flash; extern struct flash_driver atsamv_flash; -extern struct flash_driver str7x_flash; -extern struct flash_driver str9x_flash; -extern struct flash_driver aduc702x_flash; -extern struct flash_driver aducm360_flash; -extern struct flash_driver stellaris_flash; -extern struct flash_driver str9xpec_flash; -extern struct flash_driver stm32f1x_flash; -extern struct flash_driver stm32f2x_flash; -extern struct flash_driver stm32lx_flash; -extern struct flash_driver stm32l4x_flash; -extern struct flash_driver tms470_flash; -extern struct flash_driver ocl_flash; -extern struct flash_driver pic32mx_flash; extern struct flash_driver avr_flash; -extern struct flash_driver faux_flash; -extern struct flash_driver virtual_flash; -extern struct flash_driver stmsmi_flash; -extern struct flash_driver em357_flash; +extern struct flash_driver cfi_flash; extern struct flash_driver dsp5680xx_flash; +extern struct flash_driver efm32_flash; +extern struct flash_driver em357_flash; +extern struct flash_driver faux_flash; extern struct flash_driver fm3_flash; +extern struct flash_driver fm4_flash; +#if BUILD_RISCV == 1 +extern struct flash_driver fespi_flash; +#endif +extern struct flash_driver jtagspi_flash; extern struct flash_driver kinetis_flash; -extern struct flash_driver efm32_flash; +extern struct flash_driver kinetis_ke_flash; +extern struct flash_driver lpc2000_flash; +extern struct flash_driver lpc288x_flash; +extern struct flash_driver lpc2900_flash; +extern struct flash_driver lpcspifi_flash; extern struct flash_driver mdr_flash; -extern struct flash_driver numicro_flash; -extern struct flash_driver nrf51_flash; extern struct flash_driver mrvlqspi_flash; +extern struct flash_driver niietcm4_flash; +extern struct flash_driver nrf51_flash; +extern struct flash_driver numicro_flash; +extern struct flash_driver ocl_flash; +extern struct flash_driver pic32mx_flash; extern struct flash_driver psoc4_flash; extern struct flash_driver sim3x_flash; -extern struct flash_driver jtagspi_flash; +extern struct flash_driver stellaris_flash; +extern struct flash_driver stm32f1x_flash; +extern struct flash_driver stm32f2x_flash; +extern struct flash_driver stm32lx_flash; +extern struct flash_driver stm32l4x_flash; +extern struct flash_driver stmsmi_flash; +extern struct flash_driver str7x_flash; +extern struct flash_driver str9x_flash; +extern struct flash_driver str9xpec_flash; +extern struct flash_driver tms470_flash; +extern struct flash_driver virtual_flash; +extern struct flash_driver xmc1xxx_flash; extern struct flash_driver xmc4xxx_flash; -extern struct flash_driver niietcm4_flash; /** * The list of built-in flash drivers. * @todo Make this dynamically extendable with loadable modules. */ static struct flash_driver *flash_drivers[] = { - &lpc2000_flash, - &lpc288x_flash, - &lpc2900_flash, - &lpcspifi_flash, - &cfi_flash, - &at91sam7_flash, + &aduc702x_flash, + &aducm360_flash, + &ambiqmicro_flash, &at91sam3_flash, &at91sam4_flash, &at91sam4l_flash, + &at91sam7_flash, &at91samd_flash, + &ath79_flash, &atsamv_flash, - &str7x_flash, - &str9x_flash, - &aduc702x_flash, - &aducm360_flash, - &stellaris_flash, - &str9xpec_flash, - &stm32f1x_flash, - &stm32f2x_flash, - &stm32lx_flash, - &stm32l4x_flash, - &tms470_flash, - &ocl_flash, - &pic32mx_flash, &avr_flash, - &faux_flash, - &virtual_flash, - &stmsmi_flash, + &cfi_flash, + &dsp5680xx_flash, + &efm32_flash, &em357_flash, + &faux_flash, &fm3_flash, - &dsp5680xx_flash, + &fm4_flash, +#if BUILD_RISCV == 1 + &fespi_flash, +#endif + &jtagspi_flash, &kinetis_flash, - &efm32_flash, + &kinetis_ke_flash, + &lpc2000_flash, + &lpc288x_flash, + &lpc2900_flash, + &lpcspifi_flash, &mdr_flash, - &numicro_flash, - &nrf51_flash, &mrvlqspi_flash, + &niietcm4_flash, + &nrf51_flash, + &numicro_flash, + &ocl_flash, + &pic32mx_flash, &psoc4_flash, &sim3x_flash, - &jtagspi_flash, + &stellaris_flash, + &stm32f1x_flash, + &stm32f2x_flash, + &stm32lx_flash, + &stm32l4x_flash, + &stmsmi_flash, + &str7x_flash, + &str9x_flash, + &str9xpec_flash, + &tms470_flash, + &virtual_flash, + &xmc1xxx_flash, &xmc4xxx_flash, - &niietcm4_flash, NULL, }; diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index 693ff487e..38649ff04 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -18,9 +18,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index d268bea46..81c1a379c 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -25,9 +25,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -146,11 +144,11 @@ static int efm32x_read_info(struct flash_bank *bank, return ret; if (((cpuid >> 4) & 0xfff) == 0xc23) { - /* Cortex M3 device */ + /* Cortex-M3 device */ } else if (((cpuid >> 4) & 0xfff) == 0xc24) { - /* Cortex M4 device(WONDER GECKO) */ + /* Cortex-M4 device (WONDER GECKO) */ } else if (((cpuid >> 4) & 0xfff) == 0xc60) { - /* Cortex M0plus device */ + /* Cortex-M0+ device */ } else { LOG_ERROR("Target is not Cortex-Mx Device"); return ERROR_FAIL; @@ -458,10 +456,10 @@ static int efm32x_read_lock_data(struct flash_bank *bank) uint32_t *ptr = NULL; int ret = 0; - assert(!(bank->num_sectors & 0x1f)); + assert(bank->num_sectors > 0); - data_size = bank->num_sectors / 8; /* number of data bytes */ - data_size /= 4; /* ...and data dwords */ + /* calculate the number of 32-bit words to read (one lock bit per sector) */ + data_size = (bank->num_sectors + 31) / 32; ptr = efm32x_info->lb_page; @@ -668,7 +666,7 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } ret = target_write_buffer(target, write_algorithm->address, sizeof(efm32x_flash_write_code), efm32x_flash_write_code); @@ -687,7 +685,7 @@ static int efm32x_write_block(struct flash_bank *bank, const uint8_t *buf, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (word-32bit) */ @@ -997,7 +995,50 @@ static int get_efm32x_info(struct flash_bank *bank, char *buf, int buf_size) return efm32x_decode_info(&info, buf, buf_size); } +COMMAND_HANDLER(efm32x_handle_debuglock_command) +{ + struct target *target = NULL; + + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + struct efm32x_flash_bank *efm32x_info = bank->driver_priv; + + target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + uint32_t *ptr; + ptr = efm32x_info->lb_page + 127; + *ptr = 0; + + retval = efm32x_write_lock_data(bank); + if (ERROR_OK != retval) { + LOG_ERROR("Failed to write LB page"); + return retval; + } + + command_print(CMD_CTX, "efm32x debug interface locked, reset the device to apply"); + + return ERROR_OK; +} + static const struct command_registration efm32x_exec_command_handlers[] = { + { + .name = "debuglock", + .handler = efm32x_handle_debuglock_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Lock the debug interface of the device.", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c index 70a5431ac..a11743b55 100644 --- a/src/flash/nor/em357.c +++ b/src/flash/nor/em357.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -502,7 +500,6 @@ static int em357_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - ; retval = target_write_buffer(target, write_algorithm->address, sizeof(em357_flash_write_code), em357_flash_write_code); @@ -705,6 +702,11 @@ static int em357_probe(struct flash_bank *bank) num_pages = 128; page_size = 2048; break; + case 0x80000: + /* 512k -- 256 2k pages */ + num_pages = 256; + page_size = 2048; + break; default: LOG_WARNING("No size specified for em357 flash driver, assuming 192k!"); num_pages = 96; diff --git a/src/flash/nor/faux.c b/src/flash/nor/faux.c index 1fd1da216..203eb6fff 100644 --- a/src/flash/nor/faux.c +++ b/src/flash/nor/faux.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -50,7 +48,7 @@ FLASH_BANK_COMMAND_HANDLER(faux_flash_bank_command) return ERROR_FAIL; } info->memory = malloc(bank->size); - if (info == NULL) { + if (info->memory == NULL) { free(info); LOG_ERROR("no memory for flash bank info"); return ERROR_FAIL; diff --git a/src/flash/nor/fm3.c b/src/flash/nor/fm3.c index d3d143f60..6269a6536 100644 --- a/src/flash/nor/fm3.c +++ b/src/flash/nor/fm3.c @@ -17,9 +17,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nor/imp.h b/src/flash/nor/imp.h index 31d098408..87475a39c 100644 --- a/src/flash/nor/imp.h +++ b/src/flash/nor/imp.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FLASH_NOR_IMP_H -#define FLASH_NOR_IMP_H +#ifndef OPENOCD_FLASH_NOR_IMP_H +#define OPENOCD_FLASH_NOR_IMP_H /* this is an internal header */ #include "core.h" @@ -48,4 +46,4 @@ int flash_driver_read(struct flash_bank *bank, int flash_write_unlock(struct target *target, struct image *image, uint32_t *written, int erase, bool unlock); -#endif /* FLASH_NOR_IMP_H */ +#endif /* OPENOCD_FLASH_NOR_IMP_H */ diff --git a/src/flash/nor/jtagspi.c b/src/flash/nor/jtagspi.c index 1e623a71b..a995fc756 100644 --- a/src/flash/nor/jtagspi.c +++ b/src/flash/nor/jtagspi.c @@ -11,6 +11,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -208,14 +210,14 @@ static void jtagspi_read_status(struct flash_bank *bank, uint32_t *status) static int jtagspi_wait(struct flash_bank *bank, int timeout_ms) { uint32_t status; - long long t0 = timeval_ms(); - long long dt; + int64_t t0 = timeval_ms(); + int64_t dt; do { dt = timeval_ms() - t0; jtagspi_read_status(bank, &status); if ((status & SPIFLASH_BSY_BIT) == 0) { - LOG_DEBUG("waited %lld ms", dt); + LOG_DEBUG("waited %" PRId64 " ms", dt); return ERROR_OK; } alive_sleep(1); @@ -242,14 +244,14 @@ static int jtagspi_bulk_erase(struct flash_bank *bank) { struct jtagspi_flash_bank *info = bank->driver_priv; int retval; - long long t0 = timeval_ms(); + int64_t t0 = timeval_ms(); retval = jtagspi_write_enable(bank); if (retval != ERROR_OK) return retval; jtagspi_cmd(bank, info->dev->chip_erase_cmd, NULL, NULL, 0); retval = jtagspi_wait(bank, bank->num_sectors*JTAGSPI_MAX_TIMEOUT); - LOG_INFO("took %lld ms", timeval_ms() - t0); + LOG_INFO("took %" PRId64 " ms", timeval_ms() - t0); return retval; } @@ -257,14 +259,14 @@ static int jtagspi_sector_erase(struct flash_bank *bank, int sector) { struct jtagspi_flash_bank *info = bank->driver_priv; int retval; - long long t0 = timeval_ms(); + int64_t t0 = timeval_ms(); retval = jtagspi_write_enable(bank); if (retval != ERROR_OK) return retval; jtagspi_cmd(bank, info->dev->erase_cmd, &bank->sectors[sector].offset, NULL, 0); retval = jtagspi_wait(bank, JTAGSPI_MAX_TIMEOUT); - LOG_INFO("sector %d took %lld ms", sector, timeval_ms() - t0); + LOG_INFO("sector %d took %" PRId64 " ms", sector, timeval_ms() - t0); return retval; } diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index d618cfdd2..7e9bbdef4 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -11,6 +11,9 @@ * Copyright (C) 2013 Nemui Trinomius * * nemuisan_kawausogasuki@live.jp * * * + * Copyright (C) 2015 Tomas Vanek * + * vanekt@fbl.cz * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -22,9 +25,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -34,6 +35,7 @@ #include "jtag/interface.h" #include "imp.h" #include +#include #include #include #include @@ -78,16 +80,34 @@ */ /* Addressess */ +#define FCF_ADDRESS 0x00000400 +#define FCF_FPROT 0x8 +#define FCF_FSEC 0xc +#define FCF_FOPT 0xd +#define FCF_FDPROT 0xf +#define FCF_SIZE 0x10 + #define FLEXRAM 0x14000000 + +#define FMC_PFB01CR 0x4001f004 #define FTFx_FSTAT 0x40020000 #define FTFx_FCNFG 0x40020001 #define FTFx_FCCOB3 0x40020004 #define FTFx_FPROT3 0x40020010 +#define FTFx_FDPROT 0x40020017 #define SIM_SDID 0x40048024 #define SIM_SOPT1 0x40047000 #define SIM_FCFG1 0x4004804c #define SIM_FCFG2 0x40048050 #define WDOG_STCTRH 0x40052000 +#define SMC_PMCTRL 0x4007E001 +#define SMC_PMSTAT 0x4007E003 +#define MCM_PLACR 0xF000300C + +/* Values */ +#define PM_STAT_RUN 0x01 +#define PM_STAT_VLPR 0x04 +#define PM_CTRL_RUNM_RUN 0x00 /* Commands */ #define FTFx_CMD_BLOCKSTAT 0x00 @@ -95,8 +115,9 @@ #define FTFx_CMD_LWORDPROG 0x06 #define FTFx_CMD_SECTERASE 0x09 #define FTFx_CMD_SECTWRITE 0x0b -#define FTFx_CMD_SETFLEXRAM 0x81 #define FTFx_CMD_MASSERASE 0x44 +#define FTFx_CMD_PGMPART 0x80 +#define FTFx_CMD_SETFLEXRAM 0x81 /* The older Kinetis K series uses the following SDID layout : * Bit 31-16 : 0 @@ -186,12 +207,16 @@ #define KINETIS_SDID_FAMILYID_K4X 0x40000000 #define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000 +#define KINETIS_SDID_FAMILYID_K8X 0x80000000 struct kinetis_flash_bank { - unsigned bank_ordinal; + bool probed; uint32_t sector_size; uint32_t max_flash_prog_size; uint32_t protection_size; + uint32_t prog_base; /* base address for FTFx operations */ + /* same as bank->base for pflash, differs for FlexNVM */ + uint32_t protection_block; /* number of first protection block in this bank */ uint32_t sim_sdid; uint32_t sim_fcfg1; @@ -208,9 +233,13 @@ struct kinetis_flash_bank { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, FS_PROGRAM_PHRASE = 4, /* Unsupported */ + FS_INVALIDATE_CACHE_K = 8, + FS_INVALIDATE_CACHE_L = 0x10, } flash_support; }; +#define MDM_AP 1 + #define MDM_REG_STAT 0x00 #define MDM_REG_CTRL 0x04 #define MDM_REG_ID 0xfc @@ -229,23 +258,34 @@ struct kinetis_flash_bank { #define MDM_STAT_CORE_SLEEPDEEP (1<<17) #define MDM_STAT_CORESLEEPING (1<<18) -#define MEM_CTRL_FMEIP (1<<0) -#define MEM_CTRL_DBG_DIS (1<<1) -#define MEM_CTRL_DBG_REQ (1<<2) -#define MEM_CTRL_SYS_RES_REQ (1<<3) -#define MEM_CTRL_CORE_HOLD_RES (1<<4) -#define MEM_CTRL_VLLSX_DBG_REQ (1<<5) -#define MEM_CTRL_VLLSX_DBG_ACK (1<<6) -#define MEM_CTRL_VLLSX_STAT_ACK (1<<7) +#define MDM_CTRL_FMEIP (1<<0) +#define MDM_CTRL_DBG_DIS (1<<1) +#define MDM_CTRL_DBG_REQ (1<<2) +#define MDM_CTRL_SYS_RES_REQ (1<<3) +#define MDM_CTRL_CORE_HOLD_RES (1<<4) +#define MDM_CTRL_VLLSX_DBG_REQ (1<<5) +#define MDM_CTRL_VLLSX_DBG_ACK (1<<6) +#define MDM_CTRL_VLLSX_STAT_ACK (1<<7) + +#define MDM_ACCESS_TIMEOUT 500 /* msec */ + + +static bool allow_fcf_writes; +static uint8_t fcf_fopt = 0xff; + + +struct flash_driver kinetis_flash; +static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count); +static int kinetis_auto_probe(struct flash_bank *bank); -#define MDM_ACCESS_TIMEOUT 3000 /* iterations */ static int kinetis_mdm_write_register(struct adiv5_dap *dap, unsigned reg, uint32_t value) { int retval; LOG_DEBUG("MDM_REG[0x%02x] <- %08" PRIX32, reg, value); - retval = dap_queue_ap_write(dap_ap(dap, 1), reg, value); + retval = dap_queue_ap_write(dap_ap(dap, MDM_AP), reg, value); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a write request"); return retval; @@ -265,7 +305,7 @@ static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32 { int retval; - retval = dap_queue_ap_read(dap_ap(dap, 1), reg, result); + retval = dap_queue_ap_read(dap_ap(dap, MDM_AP), reg, result); if (retval != ERROR_OK) { LOG_DEBUG("MDM: failed to queue a read request"); return retval; @@ -281,11 +321,12 @@ static int kinetis_mdm_read_register(struct adiv5_dap *dap, unsigned reg, uint32 return ERROR_OK; } -static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32_t mask, uint32_t value) +static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, + uint32_t mask, uint32_t value, uint32_t timeout_ms) { uint32_t val; int retval; - int timeout = MDM_ACCESS_TIMEOUT; + int64_t ms_timeout = timeval_ms() + timeout_ms; do { retval = kinetis_mdm_read_register(dap, reg, &val); @@ -293,17 +334,121 @@ static int kinetis_mdm_poll_register(struct adiv5_dap *dap, unsigned reg, uint32 return retval; alive_sleep(1); - } while (timeout--); + } while (timeval_ms() < ms_timeout); LOG_DEBUG("MDM: polling timed out"); return ERROR_FAIL; } +/* + * This command can be used to break a watchdog reset loop when + * connecting to an unsecured target. Unlike other commands, halt will + * automatically retry as it does not know how far into the boot process + * it is when the command is called. + */ +COMMAND_HANDLER(kinetis_mdm_halt) +{ + struct target *target = get_current_target(CMD_CTX); + struct cortex_m_common *cortex_m = target_to_cm(target); + struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; + int retval; + int tries = 0; + uint32_t stat; + int64_t ms_timeout = timeval_ms() + MDM_ACCESS_TIMEOUT; + + if (!dap) { + LOG_ERROR("Cannot perform halt with a high-level adapter"); + return ERROR_FAIL; + } + + while (true) { + tries++; + + kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_CORE_HOLD_RES); + + alive_sleep(1); + + retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &stat); + if (retval != ERROR_OK) { + LOG_DEBUG("MDM: failed to read MDM_REG_STAT"); + continue; + } + + /* Repeat setting MDM_CTRL_CORE_HOLD_RES until system is out of + * reset with flash ready and without security + */ + if ((stat & (MDM_STAT_FREADY | MDM_STAT_SYSSEC | MDM_STAT_SYSRES)) + == (MDM_STAT_FREADY | MDM_STAT_SYSRES)) + break; + + if (timeval_ms() >= ms_timeout) { + LOG_ERROR("MDM: halt timed out"); + return ERROR_FAIL; + } + } + + LOG_DEBUG("MDM: halt succeded after %d attempts.", tries); + + target_poll(target); + /* enable polling in case kinetis_check_flash_security_status disabled it */ + jtag_poll_set_enabled(true); + + alive_sleep(100); + + target->reset_halt = true; + target->type->assert_reset(target); + + retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: failed to clear MDM_REG_CTRL"); + return retval; + } + + target->type->deassert_reset(target); + + return ERROR_OK; +} + +COMMAND_HANDLER(kinetis_mdm_reset) +{ + struct target *target = get_current_target(CMD_CTX); + struct cortex_m_common *cortex_m = target_to_cm(target); + struct adiv5_dap *dap = cortex_m->armv7m.arm.dap; + int retval; + + if (!dap) { + LOG_ERROR("Cannot perform reset with a high-level adapter"); + return ERROR_FAIL; + } + + retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: failed to write MDM_REG_CTRL"); + return retval; + } + + retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, MDM_STAT_SYSRES, 0, 500); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: failed to assert reset"); + return retval; + } + + retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: failed to clear MDM_REG_CTRL"); + return retval; + } + + return ERROR_OK; +} + /* * This function implements the procedure to mass erase the flash via * SWD/JTAG on Kinetis K and L series of devices as it is described in * AN4835 "Production Flash Programming Best Practices for Kinetis K- - * and L-series MCUs" Section 4.2.1 + * and L-series MCUs" Section 4.2.1. To prevent a watchdog reset loop, + * the core remains halted after this function completes as suggested + * by the application note. */ COMMAND_HANDLER(kinetis_mdm_mass_erase) { @@ -326,70 +471,123 @@ COMMAND_HANDLER(kinetis_mdm_mass_erase) * establishing communication... */ - /* assert SRST */ - if (jtag_get_reset_config() & RESET_HAS_SRST) + /* assert SRST if configured */ + bool has_srst = jtag_get_reset_config() & RESET_HAS_SRST; + if (has_srst) adapter_assert_reset(); - else - LOG_WARNING("Attempting mass erase without hardware reset. This is not reliable; " - "it's recommended you connect SRST and use ``reset_config srst_only''."); - retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MEM_CTRL_SYS_RES_REQ); - if (retval != ERROR_OK) - return retval; + retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ); + if (retval != ERROR_OK && !has_srst) { + LOG_ERROR("MDM: failed to assert reset"); + goto deassert_reset_and_exit; + } /* - * ... Read the MDM-AP status register until the Flash Ready bit sets... + * ... Read the MDM-AP status register repeatedly and wait for + * stable conditions suitable for mass erase: + * - mass erase is enabled + * - flash is ready + * - reset is finished + * + * Mass erase is started as soon as all conditions are met in 32 + * subsequent status reads. + * + * In case of not stable conditions (RESET/WDOG loop in secured device) + * the user is asked for manual pressing of RESET button + * as a last resort. */ - retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, - MDM_STAT_FREADY | MDM_STAT_SYSRES, - MDM_STAT_FREADY); - if (retval != ERROR_OK) { - LOG_ERROR("MDM : flash ready timeout"); - return retval; - } + int cnt_mass_erase_disabled = 0; + int cnt_ready = 0; + int64_t ms_start = timeval_ms(); + bool man_reset_requested = false; + + do { + uint32_t stat = 0; + int64_t ms_elapsed = timeval_ms() - ms_start; + + if (!man_reset_requested && ms_elapsed > 100) { + LOG_INFO("MDM: Press RESET button now if possible."); + man_reset_requested = true; + } + + if (ms_elapsed > 3000) { + LOG_ERROR("MDM: waiting for mass erase conditions timed out."); + LOG_INFO("Mass erase of a secured MCU is not possible without hardware reset."); + LOG_INFO("Connect SRST, use 'reset_config srst_only' and retry."); + goto deassert_reset_and_exit; + } + retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &stat); + if (retval != ERROR_OK) { + cnt_ready = 0; + continue; + } + + if (!(stat & MDM_STAT_FMEEN)) { + cnt_ready = 0; + cnt_mass_erase_disabled++; + if (cnt_mass_erase_disabled > 10) { + LOG_ERROR("MDM: mass erase is disabled"); + goto deassert_reset_and_exit; + } + continue; + } + + if ((stat & (MDM_STAT_FREADY | MDM_STAT_SYSRES)) == MDM_STAT_FREADY) + cnt_ready++; + else + cnt_ready = 0; + + } while (cnt_ready < 32); /* * ... Write the MDM-AP control register to set the Flash Mass * Erase in Progress bit. This will start the mass erase * process... */ - retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, - MEM_CTRL_SYS_RES_REQ | MEM_CTRL_FMEIP); - if (retval != ERROR_OK) - return retval; - - /* As a sanity check make sure that device started mass erase procedure */ - retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, - MDM_STAT_FMEACK, MDM_STAT_FMEACK); - if (retval != ERROR_OK) - return retval; + retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, MDM_CTRL_SYS_RES_REQ | MDM_CTRL_FMEIP); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: failed to start mass erase"); + goto deassert_reset_and_exit; + } /* * ... Read the MDM-AP control register until the Flash Mass * Erase in Progress bit clears... + * Data sheed defines erase time <3.6 sec/512kB flash block. + * The biggest device has 4 pflash blocks => timeout 16 sec. */ - retval = kinetis_mdm_poll_register(dap, MDM_REG_CTRL, - MEM_CTRL_FMEIP, - 0); - if (retval != ERROR_OK) - return retval; + retval = kinetis_mdm_poll_register(dap, MDM_REG_CTRL, MDM_CTRL_FMEIP, 0, 16000); + if (retval != ERROR_OK) { + LOG_ERROR("MDM: mass erase timeout"); + goto deassert_reset_and_exit; + } + + target_poll(target); + /* enable polling in case kinetis_check_flash_security_status disabled it */ + jtag_poll_set_enabled(true); + + alive_sleep(100); + + target->reset_halt = true; + target->type->assert_reset(target); /* * ... Negate the RESET signal or clear the System Reset Request - * bit in the MDM-AP control register... + * bit in the MDM-AP control register. */ retval = kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0); if (retval != ERROR_OK) - return retval; + LOG_ERROR("MDM: failed to clear MDM_REG_CTRL"); - if (jtag_get_reset_config() & RESET_HAS_SRST) { - /* halt MCU otherwise it loops in hard fault - WDOG reset cycle */ - target->reset_halt = true; - target->type->assert_reset(target); - target->type->deassert_reset(target); - } + target->type->deassert_reset(target); - return ERROR_OK; + return retval; + +deassert_reset_and_exit: + kinetis_mdm_write_register(dap, MDM_REG_CTRL, 0); + if (has_srst) + adapter_deassert_reset(); + return retval; } static const uint32_t kinetis_known_mdm_ids[] = { @@ -414,6 +612,9 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) return ERROR_OK; } + if (!dap->ops) + return ERROR_OK; /* too early to check, in JTAG mode ops may not be initialised */ + uint32_t val; int retval; @@ -424,9 +625,12 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) retval = kinetis_mdm_read_register(dap, MDM_REG_ID, &val); if (retval != ERROR_OK) { LOG_ERROR("MDM: failed to read ID register"); - goto fail; + return ERROR_OK; } + if (val == 0) + return ERROR_OK; /* dap not yet initialised */ + bool found = false; for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) { if (val == kinetis_known_mdm_ids[i]) { @@ -438,17 +642,6 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) if (!found) LOG_WARNING("MDM: unknown ID %08" PRIX32, val); - /* - * ... Read the MDM-AP status register until the Flash Ready bit sets... - */ - retval = kinetis_mdm_poll_register(dap, MDM_REG_STAT, - MDM_STAT_FREADY, - MDM_STAT_FREADY); - if (retval != ERROR_OK) { - LOG_ERROR("MDM: flash ready timeout"); - goto fail; - } - /* * ... Read the System Security bit to determine if security is enabled. * If System Security = 0, then proceed. If System Security = 1, then @@ -459,33 +652,40 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val); if (retval != ERROR_OK) { LOG_ERROR("MDM: failed to read MDM_REG_STAT"); - goto fail; + return ERROR_OK; } - if ((val & (MDM_STAT_SYSSEC | MDM_STAT_CORE_HALTED)) == MDM_STAT_SYSSEC) { - LOG_WARNING("MDM: Secured MCU state detected however it may be a false alarm"); - LOG_WARNING("MDM: Halting target to detect secured state reliably"); + /* + * System Security bit is also active for short time during reset. + * If a MCU has blank flash and runs in RESET/WDOG loop, + * System Security bit is active most of time! + * We should observe Flash Ready bit and read status several times + * to avoid false detection of secured MCU + */ + int secured_score = 0, flash_not_ready_score = 0; - retval = target_halt(target); - if (retval == ERROR_OK) - retval = target_wait_state(target, TARGET_HALTED, 100); + if ((val & (MDM_STAT_SYSSEC | MDM_STAT_FREADY)) != MDM_STAT_FREADY) { + uint32_t stats[32]; + int i; - if (retval != ERROR_OK) { - LOG_WARNING("MDM: Target not halted, trying reset halt"); - target->reset_halt = true; - target->type->assert_reset(target); - target->type->deassert_reset(target); + for (i = 0; i < 32; i++) { + stats[i] = MDM_STAT_FREADY; + dap_queue_ap_read(dap_ap(dap, MDM_AP), MDM_REG_STAT, &stats[i]); } - - /* re-read status */ - retval = kinetis_mdm_read_register(dap, MDM_REG_STAT, &val); + retval = dap_run(dap); if (retval != ERROR_OK) { - LOG_ERROR("MDM: failed to read MDM_REG_STAT"); - goto fail; + LOG_DEBUG("MDM: dap_run failed when validating secured state"); + return ERROR_OK; + } + for (i = 0; i < 32; i++) { + if (stats[i] & MDM_STAT_SYSSEC) + secured_score++; + if (!(stats[i] & MDM_STAT_FREADY)) + flash_not_ready_score++; } } - if (val & MDM_STAT_SYSSEC) { + if (flash_not_ready_score <= 8 && secured_score > 24) { jtag_poll_set_enabled(false); LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********"); @@ -497,17 +697,22 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) LOG_WARNING("**** command, power cycle the MCU and restart OpenOCD. ****"); LOG_WARNING("**** ****"); LOG_WARNING("*********** ATTENTION! ATTENTION! ATTENTION! ATTENTION! **********"); + + } else if (flash_not_ready_score > 24) { + jtag_poll_set_enabled(false); + LOG_WARNING("**** Your Kinetis MCU is probably locked-up in RESET/WDOG loop. ****"); + LOG_WARNING("**** Common reason is a blank flash (at least a reset vector). ****"); + LOG_WARNING("**** Issue 'kinetis mdm halt' command or if SRST is connected ****"); + LOG_WARNING("**** and configured, use 'reset halt' ****"); + LOG_WARNING("**** If MCU cannot be halted, it is likely secured and running ****"); + LOG_WARNING("**** in RESET/WDOG loop. Issue 'kinetis mdm mass_erase' ****"); + } else { LOG_INFO("MDM: Chip is unsecured. Continuing."); jtag_poll_set_enabled(true); } return ERROR_OK; - -fail: - LOG_ERROR("MDM: Failed to check security status of the MCU. Cannot proceed further"); - jtag_poll_set_enabled(false); - return retval; } FLASH_BANK_COMMAND_HANDLER(kinetis_flash_bank_command) @@ -537,30 +742,11 @@ int kinetis_disable_wdog(struct target *target, uint32_t sim_sdid) int retval; static const uint8_t kinetis_unlock_wdog_code[] = { - /* WDOG_UNLOCK = 0xC520 */ - 0x4f, 0xf4, 0x00, 0x53, /* mov.w r3, #8192 ; 0x2000 */ - 0xc4, 0xf2, 0x05, 0x03, /* movt r3, #16389 ; 0x4005 */ - 0x4c, 0xf2, 0x20, 0x52, /* movw r2, #50464 ; 0xc520 */ - 0xda, 0x81, /* strh r2, [r3, #14] */ - - /* WDOG_UNLOCK = 0xD928 */ - 0x4f, 0xf4, 0x00, 0x53, /* mov.w r3, #8192 ; 0x2000 */ - 0xc4, 0xf2, 0x05, 0x03, /* movt r3, #16389 ; 0x4005 */ - 0x4d, 0xf6, 0x28, 0x12, /* movw r2, #55592 ; 0xd928 */ - 0xda, 0x81, /* strh r2, [r3, #14] */ - - /* WDOG_SCR = 0x1d2 */ - 0x4f, 0xf4, 0x00, 0x53, /* mov.w r3, #8192 ; 0x2000 */ - 0xc4, 0xf2, 0x05, 0x03, /* movt r3, #16389 ; 0x4005 */ - 0x4f, 0xf4, 0xe9, 0x72, /* mov.w r2, #466 ; 0x1d2 */ - 0x1a, 0x80, /* strh r2, [r3, #0] */ - - /* END */ - 0x00, 0xBE, /* bkpt #0 */ +#include "../../../contrib/loaders/watchdog/armv7m_kinetis_wdog.inc" }; /* Decide whether the connected device needs watchdog disabling. - * Disable for all Kx devices, i.e., return if it is a KLx */ + * Disable for all Kx and KVx devices, return if it is a KLx */ if ((sim_sdid & KINETIS_SDID_SERIESID_MASK) == KINETIS_SDID_SERIESID_KL) return ERROR_OK; @@ -632,67 +818,57 @@ COMMAND_HANDLER(kinetis_disable_wdog_handler) } +static int kinetis_ftfx_decode_error(uint8_t fstat) +{ + if (fstat & 0x20) { + LOG_ERROR("Flash operation failed, illegal command"); + return ERROR_FLASH_OPER_UNSUPPORTED; + + } else if (fstat & 0x10) + LOG_ERROR("Flash operation failed, protection violated"); + + else if (fstat & 0x40) + LOG_ERROR("Flash operation failed, read collision"); + + else if (fstat & 0x80) + return ERROR_OK; + + else + LOG_ERROR("Flash operation timed out"); + + return ERROR_FLASH_OPERATION_FAILED; +} + + +static int kinetis_ftfx_prepare(struct target *target) +{ + int result, i; + uint8_t fstat; + + /* wait until busy */ + for (i = 0; i < 50; i++) { + result = target_read_u8(target, FTFx_FSTAT, &fstat); + if (result != ERROR_OK) + return result; + + if (fstat & 0x80) + break; + } + + if ((fstat & 0x80) == 0) { + LOG_ERROR("Flash controller is busy"); + return ERROR_FLASH_OPERATION_FAILED; + } + if (fstat != 0x80) { + /* reset error flags */ + result = target_write_u8(target, FTFx_FSTAT, 0x70); + } + return result; +} + /* Kinetis Program-LongWord Microcodes */ static const uint8_t kinetis_flash_write_code[] = { - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ - - /* .L1: */ - /* for(register uint32_t i=0;ibase + offset; - struct reg_param reg_params[3]; + struct kinetis_flash_bank *kinfo = bank->driver_priv; + uint32_t address = kinfo->prog_base + offset; + uint32_t end_address; + struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; - int retval = ERROR_OK; - - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ + int retval; + uint8_t fstat; /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size/2)) buffer_size = (target->working_area_size/2); - LOG_INFO("Kinetis: FLASH Write ..."); - - /* check code alignment */ - if (offset & 0x1) { - LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset); - return ERROR_FLASH_DST_BREAKS_ALIGNMENT; - } - /* allocate working area with flash programming code */ if (target_alloc_working_area(target, sizeof(kinetis_flash_write_code), &write_algorithm) != ERROR_OK) { @@ -758,35 +918,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */ - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */ - init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* address */ + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* word count */ + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); - /* write code buffer and use Flash programming code within kinetis */ - /* Set breakpoint to 0 with time-out of 1000 ms */ - while (wcount > 0) { - uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; + buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[1].value, 0, 32, wcount); + buf_set_u32(reg_params[2].value, 0, 32, source->address); + buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); + buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT); - retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); - if (retval != ERROR_OK) - break; + retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, + 0, NULL, + 5, reg_params, + source->address, source->size, + write_algorithm->address, 0, + &armv7m_info); - buf_set_u32(reg_params[0].value, 0, 32, source->address); - buf_set_u32(reg_params[1].value, 0, 32, address); - buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + if (retval == ERROR_FLASH_OPERATION_FAILED) { + end_address = buf_get_u32(reg_params[0].value, 0, 32); - retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - write_algorithm->address, 0, 100000, &armv7m_info); - if (retval != ERROR_OK) { - LOG_ERROR("Error executing kinetis Flash programming algorithm"); - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } + LOG_ERROR("Error writing flash at %08" PRIx32, end_address); - buffer += thisrun_count * 4; - address += thisrun_count * 4; - wcount -= thisrun_count; - } + retval = target_read_u8(target, FTFx_FSTAT, &fstat); + if (retval == ERROR_OK) { + retval = kinetis_ftfx_decode_error(fstat); + + /* reset error flags */ + target_write_u8(target, FTFx_FSTAT, 0x70); + } + } else if (retval != ERROR_OK) + LOG_ERROR("Error executing kinetis Flash programming algorithm"); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); @@ -794,74 +958,137 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); return retval; } static int kinetis_protect(struct flash_bank *bank, int set, int first, int last) { - LOG_WARNING("kinetis_protect not supported yet"); - /* FIXME: TODO */ + int i; - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; + if (allow_fcf_writes) { + LOG_ERROR("Protection setting is possible with 'kinetis fcf_source protection' only!"); + return ERROR_FAIL; + } + + if (!bank->prot_blocks || bank->num_prot_blocks == 0) { + LOG_ERROR("No protection possible for current bank!"); + return ERROR_FLASH_BANK_INVALID; } - return ERROR_FLASH_BANK_INVALID; + for (i = first; i < bank->num_prot_blocks && i <= last; i++) + bank->prot_blocks[i].is_protected = set; + + LOG_INFO("Protection bits will be written at the next FCF sector erase or write."); + LOG_INFO("Do not issue 'flash info' command until protection is written,"); + LOG_INFO("doing so would re-read protection status from MCU."); + + return ERROR_OK; } static int kinetis_protect_check(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } + int result; + int i, b; + uint32_t fprot; if (kinfo->flash_class == FC_PFLASH) { - int result; - uint8_t buffer[4]; - uint32_t fprot, psec; - int i, b; /* read protection register */ - result = target_read_memory(bank->target, FTFx_FPROT3, 1, 4, buffer); + result = target_read_u32(bank->target, FTFx_FPROT3, &fprot); + if (result != ERROR_OK) + return result; + + /* Every bit protects 1/32 of the full flash (not necessarily just this bank) */ + + } else if (kinfo->flash_class == FC_FLEX_NVM) { + uint8_t fdprot; + /* read protection register */ + result = target_read_u8(bank->target, FTFx_FDPROT, &fdprot); if (result != ERROR_OK) return result; - fprot = target_buffer_get_u32(bank->target, buffer); + fprot = fdprot; - /* - * Every bit protects 1/32 of the full flash (not necessarily - * just this bank), but we enforce the bank ordinals for - * PFlash to start at zero. - */ - b = kinfo->bank_ordinal * (bank->size / kinfo->protection_size); - for (psec = 0, i = 0; i < bank->num_sectors; i++) { - if ((fprot >> b) & 1) - bank->sectors[i].is_protected = 0; - else - bank->sectors[i].is_protected = 1; + } else { + LOG_ERROR("Protection checks for FlexRAM not supported"); + return ERROR_FLASH_BANK_INVALID; + } + + b = kinfo->protection_block; + for (i = 0; i < bank->num_prot_blocks; i++) { + if ((fprot >> b) & 1) + bank->prot_blocks[i].is_protected = 0; + else + bank->prot_blocks[i].is_protected = 1; + + b++; + } + + return ERROR_OK; +} + + +static int kinetis_fill_fcf(struct flash_bank *bank, uint8_t *fcf) +{ + uint32_t fprot = 0xffffffff; + uint8_t fsec = 0xfe; /* set MCU unsecure */ + uint8_t fdprot = 0xff; + int i; + uint32_t pflash_bit; + uint8_t dflash_bit; + struct flash_bank *bank_iter; + struct kinetis_flash_bank *kinfo; + + memset(fcf, 0xff, FCF_SIZE); + + pflash_bit = 1; + dflash_bit = 1; + + /* iterate over all kinetis banks */ + /* current bank is bank 0, it contains FCF */ + for (bank_iter = bank; bank_iter; bank_iter = bank_iter->next) { + if (bank_iter->driver != &kinetis_flash + || bank_iter->target != bank->target) + continue; + + kinetis_auto_probe(bank_iter); + + kinfo = bank->driver_priv; + if (!kinfo) + continue; + + if (kinfo->flash_class == FC_PFLASH) { + for (i = 0; i < bank_iter->num_prot_blocks; i++) { + if (bank_iter->prot_blocks[i].is_protected == 1) + fprot &= ~pflash_bit; + + pflash_bit <<= 1; + } - psec += bank->sectors[i].size; + } else if (kinfo->flash_class == FC_FLEX_NVM) { + for (i = 0; i < bank_iter->num_prot_blocks; i++) { + if (bank_iter->prot_blocks[i].is_protected == 1) + fdprot &= ~dflash_bit; - if (psec >= kinfo->protection_size) { - psec = 0; - b++; + dflash_bit <<= 1; } + } - } else { - LOG_ERROR("Protection checks for FlexNVM not yet supported"); - return ERROR_FLASH_BANK_INVALID; } + target_buffer_set_u32(bank->target, fcf + FCF_FPROT, fprot); + fcf[FCF_FSEC] = fsec; + fcf[FCF_FOPT] = fcf_fopt; + fcf[FCF_FDPROT] = fdprot; return ERROR_OK; } -static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t faddr, +static int kinetis_ftfx_command(struct target *target, uint8_t fcmd, uint32_t faddr, uint8_t fccob4, uint8_t fccob5, uint8_t fccob6, uint8_t fccob7, uint8_t fccob8, uint8_t fccob9, uint8_t fccoba, uint8_t fccobb, uint8_t *ftfx_fstat) @@ -869,98 +1096,116 @@ static int kinetis_ftfx_command(struct flash_bank *bank, uint8_t fcmd, uint32_t uint8_t command[12] = {faddr & 0xff, (faddr >> 8) & 0xff, (faddr >> 16) & 0xff, fcmd, fccob7, fccob6, fccob5, fccob4, fccobb, fccoba, fccob9, fccob8}; - int result, i; - uint8_t buffer; - - /* wait for done */ - for (i = 0; i < 50; i++) { - result = - target_read_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); - - if (result != ERROR_OK) - return result; - - if (buffer & 0x80) - break; - - buffer = 0x00; - } - - if (buffer != 0x80) { - /* reset error flags */ - buffer = 0x30; - result = - target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); - if (result != ERROR_OK) - return result; - } - - result = target_write_memory(bank->target, FTFx_FCCOB3, 4, 3, command); + int result; + uint8_t fstat; + int64_t ms_timeout = timeval_ms() + 250; + result = target_write_memory(target, FTFx_FCCOB3, 4, 3, command); if (result != ERROR_OK) return result; /* start command */ - buffer = 0x80; - result = target_write_memory(bank->target, FTFx_FSTAT, 1, 1, &buffer); + result = target_write_u8(target, FTFx_FSTAT, 0x80); if (result != ERROR_OK) return result; /* wait for done */ - for (i = 0; i < 240; i++) { /* Need longtime for "Mass Erase" Command Nemui Changed */ - result = - target_read_memory(bank->target, FTFx_FSTAT, 1, 1, ftfx_fstat); + do { + result = target_read_u8(target, FTFx_FSTAT, &fstat); if (result != ERROR_OK) return result; - if (*ftfx_fstat & 0x80) + if (fstat & 0x80) break; - } - if ((*ftfx_fstat & 0xf0) != 0x80) { - LOG_ERROR - ("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X", - *ftfx_fstat, command[3], command[2], command[1], command[0], + } while (timeval_ms() < ms_timeout); + + if (ftfx_fstat) + *ftfx_fstat = fstat; + + if ((fstat & 0xf0) != 0x80) { + LOG_DEBUG("ftfx command failed FSTAT: %02X FCCOB: %02X%02X%02X%02X %02X%02X%02X%02X %02X%02X%02X%02X", + fstat, command[3], command[2], command[1], command[0], command[7], command[6], command[5], command[4], command[11], command[10], command[9], command[8]); - return ERROR_FLASH_OPERATION_FAILED; + + return kinetis_ftfx_decode_error(fstat); } return ERROR_OK; } -COMMAND_HANDLER(kinetis_securing_test) -{ - int result; - uint8_t ftfx_fstat; - struct target *target = get_current_target(CMD_CTX); - struct flash_bank *bank = NULL; - - result = get_flash_bank_by_addr(target, 0x00000000, true, &bank); - if (result != ERROR_OK) - return result; - assert(bank != NULL); +static int kinetis_check_run_mode(struct target *target) +{ + int result, i; + uint8_t pmctrl, pmstat; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - return kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + 0x00000400, - 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); -} + result = target_read_u8(target, SMC_PMSTAT, &pmstat); + if (result != ERROR_OK) + return result; -static int kinetis_erase(struct flash_bank *bank, int first, int last) -{ - int result, i; + if (pmstat == PM_STAT_RUN) + return ERROR_OK; - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; + if (pmstat == PM_STAT_VLPR) { + /* It is safe to switch from VLPR to RUN mode without changing clock */ + LOG_INFO("Switching from VLPR to RUN mode."); + pmctrl = PM_CTRL_RUNM_RUN; + result = target_write_u8(target, SMC_PMCTRL, pmctrl); + if (result != ERROR_OK) + return result; + + for (i = 100; i; i--) { + result = target_read_u8(target, SMC_PMSTAT, &pmstat); + if (result != ERROR_OK) + return result; + + if (pmstat == PM_STAT_RUN) + return ERROR_OK; + } } + LOG_ERROR("Flash operation not possible in current run mode: SMC_PMSTAT: 0x%x", pmstat); + LOG_ERROR("Issue a 'reset init' command."); + return ERROR_TARGET_NOT_HALTED; +} + + +static void kinetis_invalidate_flash_cache(struct flash_bank *bank) +{ + struct kinetis_flash_bank *kinfo = bank->driver_priv; + + if (kinfo->flash_support & FS_INVALIDATE_CACHE_K) + target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0); + + else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L) + target_write_u8(bank->target, MCM_PLACR + 1, 0x04); + + return; +} + + +static int kinetis_erase(struct flash_bank *bank, int first, int last) +{ + int result, i; + struct kinetis_flash_bank *kinfo = bank->driver_priv; + + result = kinetis_check_run_mode(bank->target); + if (result != ERROR_OK) + return result; + + /* reset error flags */ + result = kinetis_ftfx_prepare(bank->target); + if (result != ERROR_OK) + return result; + if ((first > bank->num_sectors) || (last > bank->num_sectors)) return ERROR_FLASH_OPERATION_FAILED; @@ -970,10 +1215,9 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) * block. Should be quicker. */ for (i = first; i <= last; i++) { - uint8_t ftfx_fstat; /* set command and sector address */ - result = kinetis_ftfx_command(bank, FTFx_CMD_SECTERASE, bank->base + bank->sectors[i].offset, - 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); + result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTERASE, kinfo->prog_base + bank->sectors[i].offset, + 0, 0, 0, 0, 0, 0, 0, 0, NULL); if (result != ERROR_OK) { LOG_WARNING("erase sector %d failed", i); @@ -981,147 +1225,177 @@ static int kinetis_erase(struct flash_bank *bank, int first, int last) } bank->sectors[i].is_erased = 1; - } - if (first == 0) { - LOG_WARNING - ("flash configuration field erased, please reset the device"); + if (bank->base == 0 + && bank->sectors[i].offset <= FCF_ADDRESS + && bank->sectors[i].offset + bank->sectors[i].size > FCF_ADDRESS + FCF_SIZE) { + if (allow_fcf_writes) { + LOG_WARNING("Flash Configuration Field erased, DO NOT reset or power off the device"); + LOG_WARNING("until correct FCF is programmed or MCU gets security lock."); + } else { + uint8_t fcf_buffer[FCF_SIZE]; + + kinetis_fill_fcf(bank, fcf_buffer); + result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE); + if (result != ERROR_OK) + LOG_WARNING("Flash Configuration Field write failed"); + bank->sectors[i].is_erased = 0; + } + } } + kinetis_invalidate_flash_cache(bank); + return ERROR_OK; } -static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, - uint32_t offset, uint32_t count) +static int kinetis_make_ram_ready(struct target *target) { - unsigned int i, result, fallback = 0; - uint8_t buf[8]; - uint32_t wc; - struct kinetis_flash_bank *kinfo = bank->driver_priv; - uint8_t *new_buffer = NULL; + int result; + uint8_t ftfx_fcnfg; - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } + /* check if ram ready */ + result = target_read_u8(target, FTFx_FCNFG, &ftfx_fcnfg); + if (result != ERROR_OK) + return result; - if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { - /* fallback to longword write */ - fallback = 1; - LOG_WARNING("This device supports Program Longword execution only."); - LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset); + if (ftfx_fcnfg & (1 << 1)) + return ERROR_OK; /* ram ready */ - } else if (kinfo->flash_class == FC_FLEX_NVM) { + /* make flex ram available */ + result = kinetis_ftfx_command(target, FTFx_CMD_SETFLEXRAM, 0x00ff0000, + 0, 0, 0, 0, 0, 0, 0, 0, NULL); + if (result != ERROR_OK) + return ERROR_FLASH_OPERATION_FAILED; + + /* check again */ + result = target_read_u8(target, FTFx_FCNFG, &ftfx_fcnfg); + if (result != ERROR_OK) + return result; + + if (ftfx_fcnfg & (1 << 1)) + return ERROR_OK; /* ram ready */ + + return ERROR_FLASH_OPERATION_FAILED; +} + + +static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + int result = ERROR_OK; + struct kinetis_flash_bank *kinfo = bank->driver_priv; + uint8_t *buffer_aligned = NULL; + /* + * Kinetis uses different terms for the granularity of + * sector writes, e.g. "phrase" or "128 bits". We use + * the generic term "chunk". The largest possible + * Kinetis "chunk" is 16 bytes (128 bits). + */ + uint32_t prog_section_chunk_bytes = kinfo->sector_size >> 8; + uint32_t prog_size_bytes = kinfo->max_flash_prog_size; + + while (count > 0) { + uint32_t size = prog_size_bytes - offset % prog_size_bytes; + uint32_t align_begin = offset % prog_section_chunk_bytes; + uint32_t align_end; + uint32_t size_aligned; + uint16_t chunk_count; uint8_t ftfx_fstat; - LOG_DEBUG("flash write into FlexNVM @%08" PRIX32, offset); + if (size > count) + size = count; - /* make flex ram available */ - result = kinetis_ftfx_command(bank, FTFx_CMD_SETFLEXRAM, 0x00ff0000, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); + align_end = (align_begin + size) % prog_section_chunk_bytes; + if (align_end) + align_end = prog_section_chunk_bytes - align_end; - if (result != ERROR_OK) - return ERROR_FLASH_OPERATION_FAILED; + size_aligned = align_begin + size + align_end; + chunk_count = size_aligned / prog_section_chunk_bytes; - /* check if ram ready */ - result = target_read_memory(bank->target, FTFx_FCNFG, 1, 1, buf); + if (size != size_aligned) { + /* aligned section: the first, the last or the only */ + if (!buffer_aligned) + buffer_aligned = malloc(prog_size_bytes); - if (result != ERROR_OK) - return result; + memset(buffer_aligned, 0xff, size_aligned); + memcpy(buffer_aligned + align_begin, buffer, size); - if (!(buf[0] & (1 << 1))) { - /* fallback to longword write */ - fallback = 1; + result = target_write_memory(bank->target, FLEXRAM, + 4, size_aligned / 4, buffer_aligned); - LOG_WARNING("ram not ready, fallback to slow longword write (FCNFG: %02X)", buf[0]); - } - } else { - LOG_DEBUG("flash write into PFLASH @08%" PRIX32, offset); - } + LOG_DEBUG("section @ %08" PRIx32 " aligned begin %" PRIu32 ", end %" PRIu32, + bank->base + offset, align_begin, align_end); + } else + result = target_write_memory(bank->target, FLEXRAM, + 4, size_aligned / 4, buffer); + LOG_DEBUG("write section @ %08" PRIx32 " with length %" PRIu32 " bytes", + bank->base + offset, size); - /* program section command */ - if (fallback == 0) { - /* - * Kinetis uses different terms for the granularity of - * sector writes, e.g. "phrase" or "128 bits". We use - * the generic term "chunk". The largest possible - * Kinetis "chunk" is 16 bytes (128 bits). - */ - unsigned prog_section_chunk_bytes = kinfo->sector_size >> 8; - unsigned prog_size_bytes = kinfo->max_flash_prog_size; - for (i = 0; i < count; i += prog_size_bytes) { - uint8_t residual_buffer[16]; - uint8_t ftfx_fstat; - uint32_t section_count = prog_size_bytes / prog_section_chunk_bytes; - uint32_t residual_wc = 0; - - /* - * Assume the word count covers an entire - * sector. - */ - wc = prog_size_bytes / 4; - - /* - * If bytes to be programmed are less than the - * full sector, then determine the number of - * full-words to program, and put together the - * residual buffer so that a full "section" - * may always be programmed. - */ - if ((count - i) < prog_size_bytes) { - /* number of bytes to program beyond full section */ - unsigned residual_bc = (count-i) % prog_section_chunk_bytes; - - /* number of complete words to copy directly from buffer */ - wc = (count - i - residual_bc) / 4; - - /* number of total sections to write, including residual */ - section_count = DIV_ROUND_UP((count-i), prog_section_chunk_bytes); - - /* any residual bytes delivers a whole residual section */ - residual_wc = (residual_bc ? prog_section_chunk_bytes : 0)/4; - - /* clear residual buffer then populate residual bytes */ - (void) memset(residual_buffer, 0xff, prog_section_chunk_bytes); - (void) memcpy(residual_buffer, &buffer[i+4*wc], residual_bc); - } + if (result != ERROR_OK) { + LOG_ERROR("target_write_memory failed"); + break; + } - LOG_DEBUG("write section @ %08" PRIX32 " with length %" PRIu32 " bytes", - offset + i, (uint32_t)wc*4); + /* execute section-write command */ + result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTWRITE, + kinfo->prog_base + offset - align_begin, + chunk_count>>8, chunk_count, 0, 0, + 0, 0, 0, 0, &ftfx_fstat); - /* write data to flexram as whole-words */ - result = target_write_memory(bank->target, FLEXRAM, 4, wc, - buffer + i); + if (result != ERROR_OK) { + LOG_ERROR("Error writing section at %08" PRIx32, bank->base + offset); + break; + } - if (result != ERROR_OK) { - LOG_ERROR("target_write_memory failed"); - return result; - } + if (ftfx_fstat & 0x01) + LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); - /* write the residual words to the flexram */ - if (residual_wc) { - result = target_write_memory(bank->target, - FLEXRAM+4*wc, - 4, residual_wc, - residual_buffer); + buffer += size; + offset += size; + count -= size; + } - if (result != ERROR_OK) { - LOG_ERROR("target_write_memory failed"); - return result; - } - } + free(buffer_aligned); + return result; +} - /* execute section-write command */ - result = kinetis_ftfx_command(bank, FTFx_CMD_SECTWRITE, bank->base + offset + i, - section_count>>8, section_count, 0, 0, - 0, 0, 0, 0, &ftfx_fstat); - if (result != ERROR_OK) - return ERROR_FLASH_OPERATION_FAILED; +static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + int result, fallback = 0; + struct kinetis_flash_bank *kinfo = bank->driver_priv; + + if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { + /* fallback to longword write */ + fallback = 1; + LOG_INFO("This device supports Program Longword execution only."); + } else { + result = kinetis_make_ram_ready(bank->target); + if (result != ERROR_OK) { + fallback = 1; + LOG_WARNING("FlexRAM not ready, fallback to slow longword write."); } } - /* program longword command, not supported in "SF3" devices */ + + LOG_DEBUG("flash write @08%" PRIx32, bank->base + offset); + + if (fallback == 0) { + /* program section command */ + kinetis_write_sections(bank, buffer, offset, count); + } else if (kinfo->flash_support & FS_PROGRAM_LONGWORD) { + /* program longword command, not supported in FTFE */ + uint8_t *new_buffer = NULL; + + /* check word alignment */ + if (offset & 0x3) { + LOG_ERROR("offset 0x%" PRIx32 " breaks the required alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + if (count & 0x3) { uint32_t old_count = count; count = (old_count | 3) + 1; @@ -1133,7 +1407,7 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, } LOG_INFO("odd number of bytes to write (%" PRIu32 "), extending to %" PRIu32 " " "and padding with 0xff", old_count, count); - memset(new_buffer, 0xff, count); + memset(new_buffer + old_count, 0xff, count - old_count); buffer = memcpy(new_buffer, buffer, old_count); } @@ -1142,49 +1416,125 @@ static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, kinetis_disable_wdog(bank->target, kinfo->sim_sdid); /* try using a block write */ - int retval = kinetis_write_block(bank, buffer, offset, words_remaining); + result = kinetis_write_block(bank, buffer, offset, words_remaining); - if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + if (result == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { /* if block write failed (no sufficient working area), * we use normal (slow) single word accesses */ LOG_WARNING("couldn't use block writes, falling back to single " "memory accesses"); - for (i = 0; i < count; i += 4) { + while (words_remaining) { uint8_t ftfx_fstat; - LOG_DEBUG("write longword @ %08" PRIX32, (uint32_t)(offset + i)); + LOG_DEBUG("write longword @ %08" PRIx32, (uint32_t)(bank->base + offset)); - uint8_t padding[4] = {0xff, 0xff, 0xff, 0xff}; - memcpy(padding, buffer + i, MIN(4, count-i)); - - result = kinetis_ftfx_command(bank, FTFx_CMD_LWORDPROG, bank->base + offset + i, - padding[3], padding[2], padding[1], padding[0], + result = kinetis_ftfx_command(bank->target, FTFx_CMD_LWORDPROG, kinfo->prog_base + offset, + buffer[3], buffer[2], buffer[1], buffer[0], 0, 0, 0, 0, &ftfx_fstat); - if (result != ERROR_OK) - return ERROR_FLASH_OPERATION_FAILED; + if (result != ERROR_OK) { + LOG_ERROR("Error writing longword at %08" PRIx32, bank->base + offset); + break; + } + + if (ftfx_fstat & 0x01) + LOG_ERROR("Flash write error at %08" PRIx32, bank->base + offset); + + buffer += 4; + offset += 4; + words_remaining--; } } + free(new_buffer); } else { LOG_ERROR("Flash write strategy not implemented"); return ERROR_FLASH_OPERATION_FAILED; } - return ERROR_OK; + kinetis_invalidate_flash_cache(bank); + return result; } -static int kinetis_read_part_info(struct flash_bank *bank) + +static int kinetis_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + int result; + bool set_fcf = false; + int sect = 0; + + result = kinetis_check_run_mode(bank->target); + if (result != ERROR_OK) + return result; + + /* reset error flags */ + result = kinetis_ftfx_prepare(bank->target); + if (result != ERROR_OK) + return result; + + if (bank->base == 0 && !allow_fcf_writes) { + if (bank->sectors[1].offset <= FCF_ADDRESS) + sect = 1; /* 1kb sector, FCF in 2nd sector */ + + if (offset < bank->sectors[sect].offset + bank->sectors[sect].size + && offset + count > bank->sectors[sect].offset) + set_fcf = true; /* write to any part of sector with FCF */ + } + + if (set_fcf) { + uint8_t fcf_buffer[FCF_SIZE]; + uint8_t fcf_current[FCF_SIZE]; + + kinetis_fill_fcf(bank, fcf_buffer); + + if (offset < FCF_ADDRESS) { + /* write part preceding FCF */ + result = kinetis_write_inner(bank, buffer, offset, FCF_ADDRESS - offset); + if (result != ERROR_OK) + return result; + } + + result = target_read_memory(bank->target, FCF_ADDRESS, 4, FCF_SIZE / 4, fcf_current); + if (result == ERROR_OK && memcmp(fcf_current, fcf_buffer, FCF_SIZE) == 0) + set_fcf = false; + + if (set_fcf) { + /* write FCF if differs from flash - eliminate multiple writes */ + result = kinetis_write_inner(bank, fcf_buffer, FCF_ADDRESS, FCF_SIZE); + if (result != ERROR_OK) + return result; + } + + LOG_WARNING("Flash Configuration Field written."); + LOG_WARNING("Reset or power off the device to make settings effective."); + + if (offset + count > FCF_ADDRESS + FCF_SIZE) { + uint32_t delta = FCF_ADDRESS + FCF_SIZE - offset; + /* write part after FCF */ + result = kinetis_write_inner(bank, buffer + delta, FCF_ADDRESS + FCF_SIZE, count - delta); + } + return result; + + } else + /* no FCF fiddling, normal write */ + return kinetis_write_inner(bank, buffer, offset, count); +} + + +static int kinetis_probe(struct flash_bank *bank) { int result, i; - uint32_t offset = 0; - uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg2_pflsh; - uint32_t nvm_size = 0, pf_size = 0, ee_size = 0; + uint8_t fcfg1_nvmsize, fcfg1_pfsize, fcfg1_eesize, fcfg1_depart; + uint8_t fcfg2_maxaddr0, fcfg2_pflsh, fcfg2_maxaddr1; + uint32_t nvm_size = 0, pf_size = 0, df_size = 0, ee_size = 0; unsigned num_blocks = 0, num_pflash_blocks = 0, num_nvm_blocks = 0, first_nvm_bank = 0, - reassign = 0, pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0; + pflash_sector_size_bytes = 0, nvm_sector_size_bytes = 0; struct target *target = bank->target; struct kinetis_flash_bank *kinfo = bank->driver_priv; + kinfo->probed = false; + result = target_read_u32(target, SIM_SDID, &kinfo->sim_sdid); if (result != ERROR_OK) return result; @@ -1200,7 +1550,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1213,7 +1563,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: @@ -1229,7 +1579,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 2<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: @@ -1238,7 +1588,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) kinfo->max_flash_prog_size = 1<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: @@ -1248,7 +1598,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) pflash_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; default: LOG_ERROR("Unsupported K-family FAMID"); @@ -1262,7 +1612,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) /* K02FN64, K02FN128: FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { @@ -1277,7 +1627,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) /* MK24FN1M */ pflash_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; } @@ -1286,8 +1636,8 @@ static int kinetis_read_part_info(struct flash_bank *bank) || (kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K22FN512) { /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; - num_blocks = 2; /* 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD; + /* autodetect 1 or 2 blocks */ + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); @@ -1298,12 +1648,12 @@ static int kinetis_read_part_info(struct flash_bank *bank) if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; @@ -1317,7 +1667,7 @@ static int kinetis_read_part_info(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: @@ -1328,19 +1678,71 @@ static int kinetis_read_part_info(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; + + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2: + /* K80FN256, K81FN256, K82FN256 */ + pflash_sector_size_bytes = 4<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + break; + default: LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); } break; + case KINETIS_SDID_SERIESID_KL: /* KL-series */ pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; - num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + /* autodetect 1 or 2 blocks */ + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + break; + + case KINETIS_SDID_SERIESID_KV: + /* KV-series */ + switch (kinfo->sim_sdid & (KINETIS_SDID_FAMILYID_MASK | KINETIS_SDID_SUBFAMID_MASK)) { + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX0: + /* KV10: FTFA, 1kB sectors */ + pflash_sector_size_bytes = 1<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + break; + + case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1: + /* KV11: FTFA, 2kB sectors */ + pflash_sector_size_bytes = 2<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; + break; + + case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: + /* KV30: FTFA, 2kB sectors, 1 block */ + case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX1: + /* KV31: FTFA, 2kB sectors, 2 blocks */ + pflash_sector_size_bytes = 2<<10; + /* autodetect 1 or 2 blocks */ + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + break; + + case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: + case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX4: + case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX6: + /* KV4x: FTFA, 4kB sectors */ + pflash_sector_size_bytes = 4<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + break; + + default: + LOG_ERROR("Unsupported KV FAMILYID SUBFAMID"); + } break; + default: LOG_ERROR("Unsupported K-series"); } @@ -1358,7 +1760,6 @@ static int kinetis_read_part_info(struct flash_bank *bank) result = target_read_u32(target, SIM_FCFG2, &kinfo->sim_fcfg2); if (result != ERROR_OK) return result; - fcfg2_pflsh = (kinfo->sim_fcfg2 >> 23) & 0x01; LOG_DEBUG("SDID: 0x%08" PRIX32 " FCFG1: 0x%08" PRIX32 " FCFG2: 0x%08" PRIX32, kinfo->sim_sdid, kinfo->sim_fcfg1, kinfo->sim_fcfg2); @@ -1366,11 +1767,27 @@ static int kinetis_read_part_info(struct flash_bank *bank) fcfg1_nvmsize = (uint8_t)((kinfo->sim_fcfg1 >> 28) & 0x0f); fcfg1_pfsize = (uint8_t)((kinfo->sim_fcfg1 >> 24) & 0x0f); fcfg1_eesize = (uint8_t)((kinfo->sim_fcfg1 >> 16) & 0x0f); + fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); + + fcfg2_pflsh = (uint8_t)((kinfo->sim_fcfg2 >> 23) & 0x01); + fcfg2_maxaddr0 = (uint8_t)((kinfo->sim_fcfg2 >> 24) & 0x7f); + fcfg2_maxaddr1 = (uint8_t)((kinfo->sim_fcfg2 >> 16) & 0x7f); + + if (num_blocks == 0) + num_blocks = fcfg2_maxaddr1 ? 2 : 1; + else if (fcfg2_maxaddr1 == 0 && num_blocks >= 2) { + num_blocks = 1; + LOG_WARNING("MAXADDR1 is zero, number of flash banks adjusted to 1"); + } else if (fcfg2_maxaddr1 != 0 && num_blocks == 1) { + num_blocks = 2; + LOG_WARNING("MAXADDR1 is non zero, number of flash banks adjusted to 2"); + } /* when the PFLSH bit is set, there is no FlexNVM/FlexRAM */ if (!fcfg2_pflsh) { switch (fcfg1_nvmsize) { case 0x03: + case 0x05: case 0x07: case 0x09: case 0x0b: @@ -1405,6 +1822,30 @@ static int kinetis_read_part_info(struct flash_bank *bank) ee_size = 0; break; } + + switch (fcfg1_depart) { + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + case 0x06: + df_size = nvm_size - (4096 << fcfg1_depart); + break; + case 0x08: + df_size = 0; + break; + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + df_size = 4096 << (fcfg1_depart & 0x7); + break; + default: + df_size = nvm_size; + break; + } } switch (fcfg1_pfsize) { @@ -1417,12 +1858,22 @@ static int kinetis_read_part_info(struct flash_bank *bank) pf_size = 1 << (14 + (fcfg1_pfsize >> 1)); break; case 0x0f: - if (pflash_sector_size_bytes >= 4<<10) - pf_size = 1024<<10; - else if (fcfg2_pflsh) - pf_size = 512<<10; + /* a peculiar case: Freescale states different sizes for 0xf + * K02P64M100SFARM 128 KB ... duplicate of code 0x7 + * K22P121M120SF8RM 256 KB ... duplicate of code 0x9 + * K22P121M120SF7RM 512 KB ... duplicate of code 0xb + * K22P100M120SF5RM 1024 KB ... duplicate of code 0xd + * K26P169M180SF5RM 2048 KB ... the only unique value + * fcfg2_maxaddr0 seems to be the only clue to pf_size + * Checking fcfg2_maxaddr0 later in this routine is pointless then + */ + if (fcfg2_pflsh) + pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks; else - pf_size = 256<<10; + pf_size = ((uint32_t)fcfg2_maxaddr0 << 13) * num_blocks / 2; + if (pf_size != 2048<<10) + LOG_WARNING("SIM_FCFG1 PFSIZE = 0xf: please check if pflash is %u KB", pf_size>>10); + break; default: pf_size = 0; @@ -1439,101 +1890,57 @@ static int kinetis_read_part_info(struct flash_bank *bank) LOG_DEBUG("%d blocks total: %d PFlash, %d FlexNVM", num_blocks, num_pflash_blocks, num_nvm_blocks); - /* - * If the flash class is already assigned, verify the - * parameters. - */ - if (kinfo->flash_class != FC_AUTO) { - if (kinfo->bank_ordinal != (unsigned) bank->bank_number) { - LOG_WARNING("Flash ordinal/bank number mismatch"); - reassign = 1; - } else { - switch (kinfo->flash_class) { - case FC_PFLASH: - if (kinfo->bank_ordinal >= first_nvm_bank) { - LOG_WARNING("Class mismatch, bank %d is not PFlash", bank->bank_number); - reassign = 1; - } else if (bank->size != (pf_size / num_pflash_blocks)) { - LOG_WARNING("PFlash size mismatch"); - reassign = 1; - } else if (bank->base != - (0x00000000 + bank->size * kinfo->bank_ordinal)) { - LOG_WARNING("PFlash address range mismatch"); - reassign = 1; - } else if (kinfo->sector_size != pflash_sector_size_bytes) { - LOG_WARNING("PFlash sector size mismatch"); - reassign = 1; - } else { - LOG_DEBUG("PFlash bank %d already configured okay", - kinfo->bank_ordinal); - } - break; - case FC_FLEX_NVM: - if ((kinfo->bank_ordinal >= num_blocks) || - (kinfo->bank_ordinal < first_nvm_bank)) { - LOG_WARNING("Class mismatch, bank %d is not FlexNVM", bank->bank_number); - reassign = 1; - } else if (bank->size != (nvm_size / num_nvm_blocks)) { - LOG_WARNING("FlexNVM size mismatch"); - reassign = 1; - } else if (bank->base != - (0x10000000 + bank->size * kinfo->bank_ordinal)) { - LOG_WARNING("FlexNVM address range mismatch"); - reassign = 1; - } else if (kinfo->sector_size != nvm_sector_size_bytes) { - LOG_WARNING("FlexNVM sector size mismatch"); - reassign = 1; - } else { - LOG_DEBUG("FlexNVM bank %d already configured okay", - kinfo->bank_ordinal); - } - break; - case FC_FLEX_RAM: - if (kinfo->bank_ordinal != num_blocks) { - LOG_WARNING("Class mismatch, bank %d is not FlexRAM", bank->bank_number); - reassign = 1; - } else if (bank->size != ee_size) { - LOG_WARNING("FlexRAM size mismatch"); - reassign = 1; - } else if (bank->base != FLEXRAM) { - LOG_WARNING("FlexRAM address mismatch"); - reassign = 1; - } else if (kinfo->sector_size != nvm_sector_size_bytes) { - LOG_WARNING("FlexRAM sector size mismatch"); - reassign = 1; - } else { - LOG_DEBUG("FlexRAM bank %d already configured okay", kinfo->bank_ordinal); - } - break; - - default: - LOG_WARNING("Unknown or inconsistent flash class"); - reassign = 1; - break; - } - } - } else { - LOG_INFO("Probing flash info for bank %d", bank->bank_number); - reassign = 1; - } - - if (!reassign) - return ERROR_OK; + LOG_INFO("Probing flash info for bank %d", bank->bank_number); if ((unsigned)bank->bank_number < num_pflash_blocks) { /* pflash, banks start at address zero */ kinfo->flash_class = FC_PFLASH; bank->size = (pf_size / num_pflash_blocks); bank->base = 0x00000000 + bank->size * bank->bank_number; + kinfo->prog_base = bank->base; kinfo->sector_size = pflash_sector_size_bytes; - kinfo->protection_size = pf_size / 32; + /* pflash is divided into 32 protection areas for + * parts with more than 32K of PFlash. For parts with + * less the protection unit is set to 1024 bytes */ + kinfo->protection_size = MAX(pf_size / 32, 1024); + bank->num_prot_blocks = 32 / num_pflash_blocks; + kinfo->protection_block = bank->num_prot_blocks * bank->bank_number; + } else if ((unsigned)bank->bank_number < num_blocks) { /* nvm, banks start at address 0x10000000 */ + unsigned nvm_ord = bank->bank_number - first_nvm_bank; + uint32_t limit; + kinfo->flash_class = FC_FLEX_NVM; bank->size = (nvm_size / num_nvm_blocks); - bank->base = 0x10000000 + bank->size * (bank->bank_number - first_nvm_bank); + bank->base = 0x10000000 + bank->size * nvm_ord; + kinfo->prog_base = 0x00800000 + bank->size * nvm_ord; kinfo->sector_size = nvm_sector_size_bytes; - kinfo->protection_size = 0; /* FIXME: TODO: depends on DEPART bits, chip */ + if (df_size == 0) { + kinfo->protection_size = 0; + } else { + for (i = df_size; ~i & 1; i >>= 1) + ; + if (i == 1) + kinfo->protection_size = df_size / 8; /* data flash size = 2^^n */ + else + kinfo->protection_size = nvm_size / 8; /* TODO: verify on SF1, not documented in RM */ + } + bank->num_prot_blocks = 8 / num_nvm_blocks; + kinfo->protection_block = bank->num_prot_blocks * nvm_ord; + + /* EEPROM backup part of FlexNVM is not accessible, use df_size as a limit */ + if (df_size > bank->size * nvm_ord) + limit = df_size - bank->size * nvm_ord; + else + limit = 0; + + if (bank->size > limit) { + bank->size = limit; + LOG_DEBUG("FlexNVM bank %d limited to 0x%08" PRIx32 " due to active EEPROM backup", + bank->bank_number, limit); + } + } else if ((unsigned)bank->bank_number == num_blocks) { LOG_ERROR("FlexRAM support not yet implemented"); return ERROR_FLASH_OPER_UNSUPPORTED; @@ -1543,10 +1950,28 @@ static int kinetis_read_part_info(struct flash_bank *bank) return ERROR_FLASH_BANK_INVALID; } + if (bank->bank_number == 0 && ((uint32_t)fcfg2_maxaddr0 << 13) != bank->size) + LOG_WARNING("MAXADDR0 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr0); + if (fcfg2_pflsh) { + if (bank->bank_number == 1 && ((uint32_t)fcfg2_maxaddr1 << 13) != bank->size) + LOG_WARNING("MAXADDR1 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr1); + } else { + if ((unsigned)bank->bank_number == first_nvm_bank + && ((uint32_t)fcfg2_maxaddr1 << 13) != df_size) + LOG_WARNING("FlexNVM MAXADDR1 0x%02" PRIx8 " check failed," + " please report to OpenOCD mailing list", fcfg2_maxaddr1); + } + if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; } + if (bank->prot_blocks) { + free(bank->prot_blocks); + bank->prot_blocks = NULL; + } if (kinfo->sector_size == 0) { LOG_ERROR("Unknown sector size for bank %d", bank->bank_number); @@ -1560,35 +1985,31 @@ static int kinetis_read_part_info(struct flash_bank *bank) } bank->num_sectors = bank->size / kinfo->sector_size; - assert(bank->num_sectors > 0); - bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); - for (i = 0; i < bank->num_sectors; i++) { - bank->sectors[i].offset = offset; - bank->sectors[i].size = kinfo->sector_size; - offset += kinfo->sector_size; - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = 1; - } + if (bank->num_sectors > 0) { + /* FlexNVM bank can be used for EEPROM backup therefore zero sized */ + bank->sectors = alloc_block_array(0, kinfo->sector_size, bank->num_sectors); + if (!bank->sectors) + return ERROR_FAIL; - return ERROR_OK; -} + bank->prot_blocks = alloc_block_array(0, kinfo->protection_size, bank->num_prot_blocks); + if (!bank->prot_blocks) + return ERROR_FAIL; -static int kinetis_probe(struct flash_bank *bank) -{ - if (bank->target->state != TARGET_HALTED) { - LOG_WARNING("Cannot communicate... target not halted."); - return ERROR_TARGET_NOT_HALTED; + } else { + bank->num_prot_blocks = 0; } - return kinetis_read_part_info(bank); + kinfo->probed = true; + + return ERROR_OK; } static int kinetis_auto_probe(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; - if (kinfo->sim_sdid) + if (kinfo && kinfo->probed) return ERROR_OK; return kinetis_probe(bank); @@ -1613,28 +2034,45 @@ static int kinetis_info(struct flash_bank *bank, char *buf, int buf_size) static int kinetis_blank_check(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; + int result; - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } + /* suprisingly blank check does not work in VLPR and HSRUN modes */ + result = kinetis_check_run_mode(bank->target); + if (result != ERROR_OK) + return result; - if (kinfo->flash_class == FC_PFLASH) { - int result; + /* reset error flags */ + result = kinetis_ftfx_prepare(bank->target); + if (result != ERROR_OK) + return result; + + if (kinfo->flash_class == FC_PFLASH || kinfo->flash_class == FC_FLEX_NVM) { + bool block_dirty = false; uint8_t ftfx_fstat; - /* check if whole bank is blank */ - result = kinetis_ftfx_command(bank, FTFx_CMD_BLOCKSTAT, bank->base, 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); + if (kinfo->flash_class == FC_FLEX_NVM) { + uint8_t fcfg1_depart = (uint8_t)((kinfo->sim_fcfg1 >> 8) & 0x0f); + /* block operation cannot be used on FlexNVM when EEPROM backup partition is set */ + if (fcfg1_depart != 0xf && fcfg1_depart != 0) + block_dirty = true; + } - if (result != ERROR_OK) - return result; + if (!block_dirty) { + /* check if whole bank is blank */ + result = kinetis_ftfx_command(bank->target, FTFx_CMD_BLOCKSTAT, kinfo->prog_base, + 0, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); - if (ftfx_fstat & 0x01) { + if (result != ERROR_OK || (ftfx_fstat & 0x01)) + block_dirty = true; + } + + if (block_dirty) { /* the whole bank is not erased, check sector-by-sector */ int i; for (i = 0; i < bank->num_sectors; i++) { /* normal margin */ - result = kinetis_ftfx_command(bank, FTFx_CMD_SECTSTAT, bank->base + bank->sectors[i].offset, + result = kinetis_ftfx_command(bank->target, FTFx_CMD_SECTSTAT, + kinfo->prog_base + bank->sectors[i].offset, 1, 0, 0, 0, 0, 0, 0, 0, &ftfx_fstat); if (result == ERROR_OK) { @@ -1651,34 +2089,222 @@ static int kinetis_blank_check(struct flash_bank *bank) bank->sectors[i].is_erased = 1; } } else { - LOG_WARNING("kinetis_blank_check not supported yet for FlexNVM"); + LOG_WARNING("kinetis_blank_check not supported yet for FlexRAM"); return ERROR_FLASH_OPERATION_FAILED; } return ERROR_OK; } -static const struct command_registration kinetis_securtiy_command_handlers[] = { + +COMMAND_HANDLER(kinetis_nvm_partition) +{ + int result, i; + unsigned long par, log2 = 0, ee1 = 0, ee2 = 0; + enum { SHOW_INFO, DF_SIZE, EEBKP_SIZE } sz_type = SHOW_INFO; + bool enable; + uint8_t load_flex_ram = 1; + uint8_t ee_size_code = 0x3f; + uint8_t flex_nvm_partition_code = 0; + uint8_t ee_split = 3; + struct target *target = get_current_target(CMD_CTX); + struct flash_bank *bank; + struct kinetis_flash_bank *kinfo; + uint32_t sim_fcfg1; + + if (CMD_ARGC >= 2) { + if (strcmp(CMD_ARGV[0], "dataflash") == 0) + sz_type = DF_SIZE; + else if (strcmp(CMD_ARGV[0], "eebkp") == 0) + sz_type = EEBKP_SIZE; + + par = strtoul(CMD_ARGV[1], NULL, 10); + while (par >> (log2 + 3)) + log2++; + } + switch (sz_type) { + case SHOW_INFO: + result = target_read_u32(target, SIM_FCFG1, &sim_fcfg1); + if (result != ERROR_OK) + return result; + + flex_nvm_partition_code = (uint8_t)((sim_fcfg1 >> 8) & 0x0f); + switch (flex_nvm_partition_code) { + case 0: + command_print(CMD_CTX, "No EEPROM backup, data flash only"); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + command_print(CMD_CTX, "EEPROM backup %d KB", 4 << flex_nvm_partition_code); + break; + case 8: + command_print(CMD_CTX, "No data flash, EEPROM backup only"); + break; + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + case 0xE: + command_print(CMD_CTX, "data flash %d KB", 4 << (flex_nvm_partition_code & 7)); + break; + case 0xf: + command_print(CMD_CTX, "No EEPROM backup, data flash only (DEPART not set)"); + break; + default: + command_print(CMD_CTX, "Unsupported EEPROM backup size code 0x%02" PRIx8, flex_nvm_partition_code); + } + return ERROR_OK; + + case DF_SIZE: + flex_nvm_partition_code = 0x8 | log2; + break; + + case EEBKP_SIZE: + flex_nvm_partition_code = log2; + break; + } + + if (CMD_ARGC == 3) + ee1 = ee2 = strtoul(CMD_ARGV[2], NULL, 10) / 2; + else if (CMD_ARGC >= 4) { + ee1 = strtoul(CMD_ARGV[2], NULL, 10); + ee2 = strtoul(CMD_ARGV[3], NULL, 10); + } + + enable = ee1 + ee2 > 0; + if (enable) { + for (log2 = 2; ; log2++) { + if (ee1 + ee2 == (16u << 10) >> log2) + break; + if (ee1 + ee2 > (16u << 10) >> log2 || log2 >= 9) { + LOG_ERROR("Unsupported EEPROM size"); + return ERROR_FLASH_OPERATION_FAILED; + } + } + + if (ee1 * 3 == ee2) + ee_split = 1; + else if (ee1 * 7 == ee2) + ee_split = 0; + else if (ee1 != ee2) { + LOG_ERROR("Unsupported EEPROM sizes ratio"); + return ERROR_FLASH_OPERATION_FAILED; + } + + ee_size_code = log2 | ee_split << 4; + } + + if (CMD_ARGC >= 5) + COMMAND_PARSE_ON_OFF(CMD_ARGV[4], enable); + if (enable) + load_flex_ram = 0; + + LOG_INFO("DEPART 0x%" PRIx8 ", EEPROM size code 0x%" PRIx8, + flex_nvm_partition_code, ee_size_code); + + result = kinetis_check_run_mode(target); + if (result != ERROR_OK) + return result; + + /* reset error flags */ + result = kinetis_ftfx_prepare(target); + if (result != ERROR_OK) + return result; + + result = kinetis_ftfx_command(target, FTFx_CMD_PGMPART, load_flex_ram, + ee_size_code, flex_nvm_partition_code, 0, 0, + 0, 0, 0, 0, NULL); + if (result != ERROR_OK) + return result; + + command_print(CMD_CTX, "FlexNVM partition set. Please reset MCU."); + + for (i = 1; i < 4; i++) { + bank = get_flash_bank_by_num_noprobe(i); + if (bank == NULL) + break; + + kinfo = bank->driver_priv; + if (kinfo && kinfo->flash_class == FC_FLEX_NVM) + kinfo->probed = false; /* re-probe before next use */ + } + + command_print(CMD_CTX, "FlexNVM banks will be re-probed to set new data flash size."); + return ERROR_OK; +} + +COMMAND_HANDLER(kinetis_fcf_source_handler) +{ + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 1) { + if (strcmp(CMD_ARGV[0], "write") == 0) + allow_fcf_writes = true; + else if (strcmp(CMD_ARGV[0], "protection") == 0) + allow_fcf_writes = false; + else + return ERROR_COMMAND_SYNTAX_ERROR; + } + + if (allow_fcf_writes) { + command_print(CMD_CTX, "Arbitrary Flash Configuration Field writes enabled."); + command_print(CMD_CTX, "Protection info writes to FCF disabled."); + LOG_WARNING("BEWARE: incorrect flash configuration may permanently lock the device."); + } else { + command_print(CMD_CTX, "Protection info writes to Flash Configuration Field enabled."); + command_print(CMD_CTX, "Arbitrary FCF writes disabled. Mode safe from unwanted locking of the device."); + } + + return ERROR_OK; +} + +COMMAND_HANDLER(kinetis_fopt_handler) +{ + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 1) + fcf_fopt = (uint8_t)strtoul(CMD_ARGV[0], NULL, 0); + else + command_print(CMD_CTX, "FCF_FOPT 0x%02" PRIx8, fcf_fopt); + + return ERROR_OK; +} + + +static const struct command_registration kinetis_security_command_handlers[] = { { .name = "check_security", .mode = COMMAND_EXEC, - .help = "", + .help = "Check status of device security lock", .usage = "", .handler = kinetis_check_flash_security_status, }, + { + .name = "halt", + .mode = COMMAND_EXEC, + .help = "Issue a halt via the MDM-AP", + .usage = "", + .handler = kinetis_mdm_halt, + }, { .name = "mass_erase", .mode = COMMAND_EXEC, - .help = "", + .help = "Issue a complete flash erase via the MDM-AP", .usage = "", .handler = kinetis_mdm_mass_erase, }, - { - .name = "test_securing", + { .name = "reset", .mode = COMMAND_EXEC, - .help = "", + .help = "Issue a reset via the MDM-AP", .usage = "", - .handler = kinetis_securing_test, + .handler = kinetis_mdm_reset, }, COMMAND_REGISTRATION_DONE }; @@ -1687,9 +2313,9 @@ static const struct command_registration kinetis_exec_command_handlers[] = { { .name = "mdm", .mode = COMMAND_ANY, - .help = "", + .help = "MDM-AP command group", .usage = "", - .chain = kinetis_securtiy_command_handlers, + .chain = kinetis_security_command_handlers, }, { .name = "disable_wdog", @@ -1698,6 +2324,29 @@ static const struct command_registration kinetis_exec_command_handlers[] = { .usage = "", .handler = kinetis_disable_wdog_handler, }, + { + .name = "nvm_partition", + .mode = COMMAND_EXEC, + .help = "Show/set data flash or EEPROM backup size in kilobytes," + " set two EEPROM sizes in bytes and FlexRAM loading during reset", + .usage = "('info'|'dataflash' size|'eebkp' size) [eesize1 eesize2] ['on'|'off']", + .handler = kinetis_nvm_partition, + }, + { + .name = "fcf_source", + .mode = COMMAND_EXEC, + .help = "Use protection as a source for Flash Configuration Field or allow writing arbitrary values to the FCF" + " Mode 'protection' is safe from unwanted locking of the device.", + .usage = "['protection'|'write']", + .handler = kinetis_fcf_source_handler, + }, + { + .name = "fopt", + .mode = COMMAND_EXEC, + .help = "FCF_FOPT value source in 'kinetis fcf_source protection' mode", + .usage = "[num]", + .handler = kinetis_fopt_handler, + }, COMMAND_REGISTRATION_DONE }; @@ -1705,7 +2354,7 @@ static const struct command_registration kinetis_command_handler[] = { { .name = "kinetis", .mode = COMMAND_ANY, - .help = "kinetis NAND flash controller commands", + .help = "Kinetis flash controller commands", .usage = "", .chain = kinetis_exec_command_handlers, }, diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index cc10a3bb3..9da5da2ca 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -261,6 +259,8 @@ #define IAP_CODE_LEN 0x34 +#define LPC11xx_REG_SECTORS 24 + typedef enum { lpc2000_v1, lpc2000_v2, @@ -556,14 +556,21 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) exit(-1); } lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */ - bank->num_sectors = bank->size / 4096; + unsigned int large_sectors = 0; + unsigned int normal_sectors = bank->size / 4096; + + if (normal_sectors > LPC11xx_REG_SECTORS) { + large_sectors = (normal_sectors - LPC11xx_REG_SECTORS) / 8; + normal_sectors = LPC11xx_REG_SECTORS; + } + + bank->num_sectors = normal_sectors + large_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; - /* all sectors are 4kB-sized */ - bank->sectors[i].size = 4 * 1024; + bank->sectors[i].size = (i < LPC11xx_REG_SECTORS ? 4 : 32) * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; @@ -681,7 +688,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate); if (retval != ERROR_OK) { - LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", + LOG_ERROR("Write memory at address 0x%8.8" TARGET_PRIxADDR " failed (check work_area definition)", (*iap_working_area)->address); target_free_working_area(target, *iap_working_area); } diff --git a/src/flash/nor/lpc288x.c b/src/flash/nor/lpc288x.c index 89f79e321..a4d88de78 100644 --- a/src/flash/nor/lpc288x.c +++ b/src/flash/nor/lpc288x.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /*************************************************************************** diff --git a/src/flash/nor/lpc2900.c b/src/flash/nor/lpc2900.c index 7c3e67580..515a3f7b2 100644 --- a/src/flash/nor/lpc2900.c +++ b/src/flash/nor/lpc2900.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -556,7 +554,7 @@ COMMAND_HANDLER(lpc2900_handle_read_custom_command) target_write_u32(target, FCTR, FCTR_FS_CS | FCTR_FS_WEB); /* Try and open the file */ - struct fileio fileio; + struct fileio *fileio; const char *filename = CMD_ARGV[1]; int ret = fileio_open(&fileio, filename, FILEIO_WRITE, FILEIO_BINARY); if (ret != ERROR_OK) { @@ -565,14 +563,14 @@ COMMAND_HANDLER(lpc2900_handle_read_custom_command) } size_t nwritten; - ret = fileio_write(&fileio, sizeof(customer), customer, &nwritten); + ret = fileio_write(fileio, sizeof(customer), customer, &nwritten); if (ret != ERROR_OK) { LOG_ERROR("Write operation to file %s failed", filename); - fileio_close(&fileio); + fileio_close(fileio); return ret; } - fileio_close(&fileio); + fileio_close(fileio); return ERROR_OK; } @@ -1160,7 +1158,6 @@ static int lpc2900_write(struct flash_bank *bank, const uint8_t *buffer, break; } } - ; if (warea) { struct reg_param reg_params[5]; diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c index 3b383ebd9..943c151e2 100644 --- a/src/flash/nor/lpcspifi.c +++ b/src/flash/nor/lpcspifi.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -58,21 +56,6 @@ struct lpcspifi_flash_bank { const struct flash_device *dev; }; -struct lpcspifi_target { - char *name; - uint32_t tap_idcode; - uint32_t spifi_base; - uint32_t ssp_base; - uint32_t io_base; - uint32_t ioconfig_base; /* base address for the port word pin registers */ -}; - -static const struct lpcspifi_target target_devices[] = { - /* name, tap_idcode, spifi_base, ssp_base, io_base, ioconfig_base */ - { "LPC43xx/18xx", 0x4ba00477, 0x14000000, 0x40083000, 0x400F4000, 0x40086000 }, - { NULL, 0, 0, 0, 0, 0 } -}; - /* flash_bank lpcspifi */ FLASH_BANK_COMMAND_HANDLER(lpcspifi_flash_bank_command) @@ -123,7 +106,7 @@ static int ssp_setcs(struct target *target, uint32_t io_base, unsigned int value * and the controller is idle. */ static int poll_ssp_busy(struct target *target, uint32_t ssp_base, int timeout) { - long long endtime; + int64_t endtime; uint32_t value; int retval; @@ -203,7 +186,7 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank) return retval; } - LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32, + LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR, spifi_init_algorithm->address); /* Write algorithm to working area */ retval = target_write_buffer(target, @@ -342,7 +325,7 @@ static int wait_till_ready(struct flash_bank *bank, int timeout) { uint32_t status; int retval; - long long endtime; + int64_t endtime; endtime = timeval_ms() + timeout; do { @@ -698,7 +681,7 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer, " a working area > %zdB in order to write to SPIFI flash.", sizeof(lpcspifi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(lpcspifi_flash_write_code), @@ -734,7 +717,7 @@ static int lpcspifi_write(struct flash_bank *bank, const uint8_t *buffer, if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; @@ -852,14 +835,9 @@ static int lpcspifi_read_flash_id(struct flash_bank *bank, uint32_t *id) static int lpcspifi_probe(struct flash_bank *bank) { - struct target *target = bank->target; struct lpcspifi_flash_bank *lpcspifi_info = bank->driver_priv; - uint32_t ssp_base; - uint32_t io_base; - uint32_t ioconfig_base; struct flash_sector *sectors; uint32_t id = 0; /* silence uninitialized warning */ - const struct lpcspifi_target *target_device; int retval; /* If we've already probed, we should be fine to skip this time. */ @@ -867,26 +845,11 @@ static int lpcspifi_probe(struct flash_bank *bank) return ERROR_OK; lpcspifi_info->probed = 0; - for (target_device = target_devices ; target_device->name ; ++target_device) - if (target_device->tap_idcode == target->tap->idcode) - break; - if (!target_device->name) { - LOG_ERROR("Device ID 0x%" PRIx32 " is not known as SPIFI capable", - target->tap->idcode); - return ERROR_FAIL; - } - - ssp_base = target_device->ssp_base; - io_base = target_device->io_base; - ioconfig_base = target_device->ioconfig_base; - lpcspifi_info->ssp_base = ssp_base; - lpcspifi_info->io_base = io_base; - lpcspifi_info->ioconfig_base = ioconfig_base; + lpcspifi_info->ssp_base = 0x40083000; + lpcspifi_info->io_base = 0x400F4000; + lpcspifi_info->ioconfig_base = 0x40086000; lpcspifi_info->bank_num = bank->bank_number; - LOG_DEBUG("Valid SPIFI on device %s at address 0x%" PRIx32, - target_device->name, bank->base); - /* read and decode flash ID; returns in SW mode */ retval = lpcspifi_read_flash_id(bank, &id); if (retval != ERROR_OK) diff --git a/src/flash/nor/mdr.c b/src/flash/nor/mdr.c index 98e013aa3..8ceb1bf46 100644 --- a/src/flash/nor/mdr.c +++ b/src/flash/nor/mdr.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -173,7 +171,8 @@ static int mdr_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) goto reset_pg_and_lock; - if ((first == 0) && (last == (bank->num_sectors - 1))) { + if ((first == 0) && (last == (bank->num_sectors - 1)) && + !mdr_info->mem_type) { retval = mdr_mass_erase(bank); goto reset_pg_and_lock; } @@ -255,7 +254,7 @@ static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code); @@ -274,7 +273,7 @@ static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */ @@ -471,6 +470,107 @@ static int mdr_write(struct flash_bank *bank, const uint8_t *buffer, if (new_buffer) free(new_buffer); + /* read some bytes bytes to flush buffer in flash accelerator. + * See errata for 1986VE1T and 1986VE3. Error 0007 */ + if ((retval == ERROR_OK) && (!mdr_info->mem_type)) { + uint32_t tmp; + target_checksum_memory(bank->target, bank->base, 64, &tmp); + } + + return retval; +} + +static int mdr_read(struct flash_bank *bank, uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct mdr_flash_bank *mdr_info = bank->driver_priv; + int retval, retval2; + + if (!mdr_info->mem_type) + return default_flash_read(bank, buffer, offset, count); + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset & 0x3) { + LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + if (count & 0x3) { + LOG_ERROR("count 0x%" PRIx32 " breaks required 4-byte alignment", count); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + uint32_t flash_cmd, cur_per_clock; + + retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock); + if (retval != ERROR_OK) + goto err; + + if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) { + /* Something's very wrong if the RST_CLK module is not clocked */ + LOG_ERROR("Target needs reset before flash operations"); + retval = ERROR_FLASH_OPERATION_FAILED; + goto err; + } + + retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM); + if (retval != ERROR_OK) + goto err; + + retval = target_write_u32(target, FLASH_KEY, KEY); + if (retval != ERROR_OK) + goto err; + + retval = target_read_u32(target, FLASH_CMD, &flash_cmd); + if (retval != ERROR_OK) + goto err_lock; + + /* Switch on register access */ + flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON | FLASH_IFREN; + retval = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + for (uint32_t i = 0; i < count; i += 4) { + retval = target_write_u32(target, FLASH_ADR, offset + i); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + retval = target_write_u32(target, FLASH_CMD, flash_cmd | + FLASH_XE | FLASH_YE | FLASH_SE); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + uint32_t buf; + retval = target_read_u32(target, FLASH_DO, &buf); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + buf_set_u32(buffer, i * 8, 32, buf); + + retval = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval != ERROR_OK) + goto reset_pg_and_lock; + + } + +reset_pg_and_lock: + flash_cmd &= FLASH_DELAY_MASK; + retval2 = target_write_u32(target, FLASH_CMD, flash_cmd); + if (retval == ERROR_OK) + retval = retval2; + +err_lock: + retval2 = target_write_u32(target, FLASH_KEY, 0); + if (retval == ERROR_OK) + retval = retval2; + +err: return retval; } @@ -527,7 +627,7 @@ struct flash_driver mdr_flash = { .erase = mdr_erase, .protect = mdr_protect, .write = mdr_write, - .read = default_flash_read, + .read = mdr_read, .probe = mdr_probe, .auto_probe = mdr_auto_probe, .erase_check = default_flash_blank_check, diff --git a/src/flash/nor/mrvlqspi.c b/src/flash/nor/mrvlqspi.c index 0dfe6f86f..d79917058 100644 --- a/src/flash/nor/mrvlqspi.c +++ b/src/flash/nor/mrvlqspi.c @@ -12,10 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * * + * along with this program. If not, see . * ***************************************************************************/ /* @@ -680,7 +677,7 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, " a working area > %zdB in order to write to SPIFI flash.", sizeof(mrvlqspi_flash_write_code)); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(mrvlqspi_flash_write_code), @@ -714,7 +711,7 @@ static int mrvlqspi_flash_write(struct flash_bank *bank, const uint8_t *buffer, if (target_alloc_working_area(target, fifo_size, &fifo) != ERROR_OK) { target_free_working_area(target, write_algorithm); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c index 78467c5a2..4a849fd26 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -13,8 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -155,7 +154,7 @@ static int niietcm4_opstatus_check(struct flash_bank *bank) { struct target *target = bank->target; int retval; - int timeout = 100; + int timeout = 5000; uint32_t flash_status; retval = target_read_u32(target, FCIS, &flash_status); @@ -192,7 +191,7 @@ static int niietcm4_uopstatus_check(struct flash_bank *bank) { struct target *target = bank->target; int retval; - int timeout = 100; + int timeout = 5000; uint32_t uflash_status; retval = target_read_u32(target, UFCIS, &uflash_status); @@ -231,7 +230,8 @@ static int niietcm4_uopstatus_check(struct flash_bank *bank) static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type) { struct target *target = bank->target; - int i, retval; + int i; + int retval = ERROR_OK; uint32_t uflash_cmd; if (mem_type == INFO_MEM_TYPE) @@ -266,7 +266,8 @@ static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, in static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type) { struct target *target = bank->target; - int i, retval; + int i; + int retval = ERROR_OK; uint32_t uflash_cmd; if (mem_type == INFO_MEM_TYPE) @@ -1048,7 +1049,7 @@ FLASH_BANK_COMMAND_HANDLER(niietcm4_flash_bank_command) { struct niietcm4_flash_bank *niietcm4_info; - if (CMD_ARGC < 7) + if (CMD_ARGC < 6) return ERROR_COMMAND_SYNTAX_ERROR; niietcm4_info = malloc(sizeof(struct niietcm4_flash_bank)); @@ -1299,7 +1300,7 @@ static int niietcm4_write_block(struct flash_bank *bank, const uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(niietcm4_flash_write_code), niietcm4_flash_write_code); @@ -1319,7 +1320,7 @@ static int niietcm4_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* write_cmd base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (128bit) */ @@ -1370,17 +1371,38 @@ static int niietcm4_write(struct flash_bank *bank, const uint8_t *buffer, { struct target *target = bank->target; struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv; + uint8_t *new_buffer = NULL; if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - if (offset & 0x3) { - LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset); + if (offset & 0xF) { + LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-word alignment", offset); return ERROR_FLASH_DST_BREAKS_ALIGNMENT; } + /* If there's an odd number of words, the data has to be padded. Duplicate + * the buffer and use the normal code path with a single block write since + * it's probably cheaper than to special case the last odd write using + * discrete accesses. */ + + int rem = count % 16; + if (rem) { + new_buffer = malloc(count + 16 - rem); + if (new_buffer == NULL) { + LOG_ERROR("Odd number of words to write and no memory for padding buffer"); + return ERROR_FAIL; + } + LOG_INFO("Odd number of words to write, padding with 0xFFFFFFFF"); + buffer = memcpy(new_buffer, buffer, count); + while (rem < 16) { + new_buffer[count++] = 0xff; + rem++; + } + } + int retval; /* try using block write */ @@ -1406,46 +1428,47 @@ static int niietcm4_write(struct flash_bank *bank, const uint8_t *buffer, flash_addr = offset + i; retval = target_write_u32(target, FMA, flash_addr); if (retval != ERROR_OK) - return retval; + goto free_buffer; - /* if there's an odd number of bytes, the data has to be padded */ - uint8_t padding[16] = { 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff}; - memcpy(padding, buffer + i, MIN(16, count-i)); + /* Prepare data (4 words) */ + uint32_t value[4]; + memcpy(&value, buffer + i*16, 4*sizeof(uint32_t)); /* place in reg 16 bytes of data */ - flash_data = (padding[3]<<24) | (padding[2]<<16) | (padding[1]<<8) | padding[0]; + flash_data = value[0]; retval = target_write_u32(target, FMD1, flash_data); if (retval != ERROR_OK) - return retval; - flash_data = (padding[7]<<24) | (padding[6]<<16) | (padding[5]<<8) | padding[4]; + goto free_buffer; + flash_data = value[1]; retval = target_write_u32(target, FMD2, flash_data); if (retval != ERROR_OK) - return retval; - flash_data = (padding[11]<<24) | (padding[10]<<16) | (padding[9]<<8) | padding[8]; + goto free_buffer; + flash_data = value[2]; retval = target_write_u32(target, FMD3, flash_data); if (retval != ERROR_OK) - return retval; - flash_data = (padding[15]<<24) | (padding[14]<<16) | (padding[13]<<8) | padding[12]; + goto free_buffer; + flash_data = value[3]; retval = target_write_u32(target, FMD4, flash_data); if (retval != ERROR_OK) - return retval; + goto free_buffer; /* write start */ retval = target_write_u32(target, FMC, flash_cmd); if (retval != ERROR_OK) - return retval; + goto free_buffer; /* status check */ retval = niietcm4_opstatus_check(bank); if (retval != ERROR_OK) - return retval; + goto free_buffer; } } +free_buffer: + if (new_buffer) + free(new_buffer); + return retval; } @@ -1697,7 +1720,7 @@ static int niietcm4_auto_probe(struct flash_bank *bank) static int get_niietcm4_info(struct flash_bank *bank, char *buf, int buf_size) { struct niietcm4_flash_bank *niietcm4_info = bank->driver_priv; - LOG_INFO("\nNIIET Cortex M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief); + LOG_INFO("\nNIIET Cortex-M4F %s\n%s", niietcm4_info->chip_name, niietcm4_info->chip_brief); snprintf(buf, buf_size, " "); return ERROR_OK; diff --git a/src/flash/nor/non_cfi.c b/src/flash/nor/non_cfi.c index 72f11e553..851c0ae81 100644 --- a/src/flash/nor/non_cfi.c +++ b/src/flash/nor/non_cfi.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -540,7 +538,6 @@ void cfi_fixup_non_cfi(struct flash_bank *bank) pri_ext->SiliconRevision = 0x0; pri_ext->EraseSuspend = 0x0; - pri_ext->EraseSuspend = 0x0; pri_ext->BlkProt = 0x0; pri_ext->TmpBlkUnprotect = 0x0; pri_ext->BlkProtUnprot = 0x0; diff --git a/src/flash/nor/non_cfi.h b/src/flash/nor/non_cfi.h index e23ab7edd..c411cb885 100644 --- a/src/flash/nor/non_cfi.h +++ b/src/flash/nor/non_cfi.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef NON_CFI_H -#define NON_CFI_H +#ifndef OPENOCD_FLASH_NOR_NON_CFI_H +#define OPENOCD_FLASH_NOR_NON_CFI_H struct non_cfi { uint16_t mfr; @@ -35,4 +33,4 @@ struct non_cfi { void cfi_fixup_non_cfi(struct flash_bank *bank); -#endif /* NON_CFI_H */ +#endif /* OPENOCD_FLASH_NOR_NON_CFI_H */ diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c index d8706c849..7b7acf479 100644 --- a/src/flash/nor/nrf51.c +++ b/src/flash/nor/nrf51.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -110,7 +108,6 @@ enum nrf51_nvmc_config_bits { struct nrf51_info { uint32_t code_page_size; - uint32_t code_memory_size; struct { bool probed; @@ -123,6 +120,7 @@ struct nrf51_info { struct nrf51_device_spec { uint16_t hwid; + const char *part; const char *variant; const char *build_code; unsigned int flash_size_kb; @@ -144,30 +142,35 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 1). */ { .hwid = 0x001D, + .part = "51822", .variant = "QFAA", .build_code = "CA/C0", .flash_size_kb = 256, }, { .hwid = 0x0026, + .part = "51822", .variant = "QFAB", .build_code = "AA", .flash_size_kb = 128, }, { .hwid = 0x0027, + .part = "51822", .variant = "QFAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0020, + .part = "51822", .variant = "CEAA", .build_code = "BA", .flash_size_kb = 256, }, { .hwid = 0x002F, + .part = "51822", .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, @@ -176,42 +179,63 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 2). */ { .hwid = 0x002A, + .part = "51822", .variant = "QFAA", .build_code = "FA0", .flash_size_kb = 256, }, { .hwid = 0x0044, + .part = "51822", .variant = "QFAA", .build_code = "GC0", .flash_size_kb = 256, }, { .hwid = 0x003C, + .part = "51822", .variant = "QFAA", .build_code = "G0", .flash_size_kb = 256, }, + { + .hwid = 0x0057, + .part = "51822", + .variant = "QFAA", + .build_code = "G2", + .flash_size_kb = 256, + }, + { + .hwid = 0x0058, + .part = "51822", + .variant = "QFAA", + .build_code = "G3", + .flash_size_kb = 256, + }, { .hwid = 0x004C, + .part = "51822", .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, { .hwid = 0x0040, + .part = "51822", .variant = "CEAA", .build_code = "CA0", .flash_size_kb = 256, }, { .hwid = 0x0047, + .part = "51822", .variant = "CEAA", .build_code = "DA0", .flash_size_kb = 256, }, { .hwid = 0x004D, + .part = "51822", .variant = "CEAA", .build_code = "D00", .flash_size_kb = 256, @@ -220,56 +244,79 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 3). */ { .hwid = 0x0072, + .part = "51822", .variant = "QFAA", .build_code = "H0", .flash_size_kb = 256, }, { .hwid = 0x007B, + .part = "51822", .variant = "QFAB", .build_code = "C0", .flash_size_kb = 128, }, { .hwid = 0x0083, + .part = "51822", .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, + { + .hwid = 0x0084, + .part = "51822", + .variant = "QFAC", + .build_code = "A1", + .flash_size_kb = 256, + }, { .hwid = 0x007D, + .part = "51822", .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0079, + .part = "51822", .variant = "CEAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0087, + .part = "51822", .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, }, + { + .hwid = 0x008F, + .part = "51822", + .variant = "QFAA", + .build_code = "H1", + .flash_size_kb = 256, + }, /* nRF51422 Devices (IC rev 1). */ { .hwid = 0x001E, + .part = "51422", .variant = "QFAA", .build_code = "CA", .flash_size_kb = 256, }, { .hwid = 0x0024, + .part = "51422", .variant = "QFAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0031, + .part = "51422", .variant = "CEAA", .build_code = "A0A", .flash_size_kb = 256, @@ -278,24 +325,28 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51422 Devices (IC rev 2). */ { .hwid = 0x002D, + .part = "51422", .variant = "QFAA", .build_code = "DAA", .flash_size_kb = 256, }, { .hwid = 0x002E, + .part = "51422", .variant = "QFAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0061, + .part = "51422", .variant = "QFAB", .build_code = "A00", .flash_size_kb = 128, }, { .hwid = 0x0050, + .part = "51422", .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, @@ -304,48 +355,49 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51422 Devices (IC rev 3). */ { .hwid = 0x0073, + .part = "51422", .variant = "QFAA", .build_code = "F0", .flash_size_kb = 256, }, { .hwid = 0x007C, + .part = "51422", .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, - { - .hwid = 0x0084, - .variant = "QFAC", - .build_code = "A1", - .flash_size_kb = 256, - }, { .hwid = 0x0085, + .part = "51422", .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, { .hwid = 0x0086, + .part = "51422", .variant = "QFAC", .build_code = "A1", .flash_size_kb = 256, }, { .hwid = 0x007E, + .part = "51422", .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x007A, + .part = "51422", .variant = "CEAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0088, + .part = "51422", .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, @@ -356,6 +408,7 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { in the nRF51 Series Compatibility Matrix V1.0. */ { .hwid = 0x0071, + .part = "51822", .variant = "QFAC", .build_code = "AB", .flash_size_kb = 256, @@ -575,7 +628,7 @@ static int nrf51_protect(struct flash_bank *bank, int set, int first, int last) if ((ppfc & 0xFF) == 0x00) { LOG_ERROR("Code region 0 size was pre-programmed at the factory, can't change flash protection settings"); return ERROR_FAIL; - }; + } res = target_read_u32(chip->target, NRF51_UICR_CLENR0, &clenr0); @@ -617,43 +670,46 @@ static int nrf51_probe(struct flash_bank *bank) * bytes of the CONFIGID register */ const struct nrf51_device_spec *spec = NULL; - for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) + for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) { if (hwid == nrf51_known_devices_table[i].hwid) { spec = &nrf51_known_devices_table[i]; break; } + } if (!chip->bank[0].probed && !chip->bank[1].probed) { if (spec) - LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash", - spec->variant, spec->build_code, spec->flash_size_kb); + LOG_INFO("nRF%s-%s(build code: %s) %ukB Flash", + spec->part, spec->variant, spec->build_code, + spec->flash_size_kb); else LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid); } - if (bank->base == NRF51_FLASH_BASE) { + /* The value stored in NRF51_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */ res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE, - &chip->code_page_size); + &chip->code_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; } - res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, - &chip->code_memory_size); + /* Note the register name is misleading, + * NRF51_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */ + uint32_t num_sectors; + res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, &num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } - if (spec && chip->code_memory_size != spec->flash_size_kb) { - LOG_ERROR("Chip's reported Flash capacity does not match expected one"); - return ERROR_FAIL; - } + bank->num_sectors = num_sectors; + bank->size = num_sectors * chip->code_page_size; + + if (spec && bank->size / 1024 != spec->flash_size_kb) + LOG_WARNING("Chip's reported Flash capacity does not match expected one"); - bank->size = chip->code_memory_size * 1024; - bank->num_sectors = bank->size / chip->code_page_size; bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); if (!bank->sectors) @@ -755,7 +811,7 @@ static int nrf51_erase_page(struct flash_bank *bank, LOG_ERROR("The chip was not pre-programmed with SoftDevice stack and UICR cannot be erased separately. Please issue mass erase before trying to write to this region"); return ERROR_FAIL; - }; + } res = nrf51_nvmc_generic_erase(chip, NRF51_NVMC_ERASEUICR, @@ -1136,7 +1192,7 @@ COMMAND_HANDLER(nrf51_handle_mass_erase_command) LOG_ERROR("Code region 0 size was pre-programmed at the factory, " "mass erase command won't work."); return ERROR_FAIL; - }; + } res = nrf51_erase_all(chip); if (res != ERROR_OK) { @@ -1262,7 +1318,7 @@ static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size) "reset value for XTALFREQ: %"PRIx32"\n" "firmware id: 0x%04"PRIx32, ficr[0].value, - ficr[1].value, + (ficr[1].value * ficr[0].value) / 1024, (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024, ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present", ficr[4].value, diff --git a/src/flash/nor/numicro.c b/src/flash/nor/numicro.c index 8d8ed6ebb..992baa515 100644 --- a/src/flash/nor/numicro.c +++ b/src/flash/nor/numicro.c @@ -20,6 +20,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nor/ocl.c b/src/flash/nor/ocl.c index c547d9a17..4ae565219 100644 --- a/src/flash/nor/ocl.c +++ b/src/flash/nor/ocl.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nor/ocl.h b/src/flash/nor/ocl.h index d056b46d5..3e83f76cf 100644 --- a/src/flash/nor/ocl.h +++ b/src/flash/nor/ocl.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef OCL_H -#define OCL_H +#ifndef OPENOCD_FLASH_NOR_OCL_H +#define OPENOCD_FLASH_NOR_OCL_H /* command/response mask */ #define OCL_CMD_MASK 0xFFFF0000L @@ -38,4 +36,4 @@ #define OCL_CHKS_INIT 0xC100CD0CL -#endif /* OCL_H */ +#endif /* OPENOCD_FLASH_NOR_OCL_H */ diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index 5e82ba63d..1f148fd73 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -52,7 +50,7 @@ /* pic32mx configuration register locations */ -#define PIC32MX_DEVCFG0_1_2 0xBFC00BFC +#define PIC32MX_DEVCFG0_1xx_2xx 0xBFC00BFC #define PIC32MX_DEVCFG0 0xBFC02FFC #define PIC32MX_DEVCFG1 0xBFC02FF8 #define PIC32MX_DEVCFG2 0xBFC02FF4 @@ -93,7 +91,8 @@ #define NVMKEY1 0xAA996655 #define NVMKEY2 0x556699AA -#define MX_1_2 1 /* PIC32mx1xx/2xx */ +#define MX_1xx_2xx 1 /* PIC32mx1xx/2xx */ +#define MX_17x_27x 2 /* PIC32mx17x/27x */ struct pic32mx_flash_bank { int probed; @@ -101,7 +100,7 @@ struct pic32mx_flash_bank { }; /* - * DEVID values as per PIC32MX Flash Programming Specification Rev J + * DEVID values as per PIC32MX Flash Programming Specification Rev N */ static const struct pic32mx_devs_s { @@ -120,6 +119,8 @@ static const struct pic32mx_devs_s { {0x04D06053, "150F128B"}, {0x04D08053, "150F128C"}, {0x04D0A053, "150F128D"}, + {0x06610053, "170F256B"}, + {0x0661A053, "170F256D"}, {0x04A01053, "210F016B"}, {0x04A03053, "210F016C"}, {0x04A05053, "210F016D"}, @@ -132,6 +133,24 @@ static const struct pic32mx_devs_s { {0x04D00053, "250F128B"}, {0x04D02053, "250F128C"}, {0x04D04053, "250F128D"}, + {0x06600053, "270F256B"}, + {0x0660A053, "270F256D"}, + {0x05600053, "330F064H"}, + {0x05601053, "330F064L"}, + {0x05602053, "430F064H"}, + {0x05603053, "430F064L"}, + {0x0570C053, "350F128H"}, + {0x0570D053, "350F128L"}, + {0x0570E053, "450F128H"}, + {0x0570F053, "450F128L"}, + {0x05704053, "350F256H"}, + {0x05705053, "350F256L"}, + {0x05706053, "450F256H"}, + {0x05707053, "450F256L"}, + {0x05808053, "370F512H"}, + {0x05809053, "370F512L"}, + {0x0580A053, "470F512H"}, + {0x0580B053, "470F512L"}, {0x00938053, "360F512L"}, {0x00934053, "360F256L"}, {0x0092D053, "340F128L"}, @@ -260,10 +279,15 @@ static int pic32mx_protect_check(struct flash_bank *bank) return ERROR_TARGET_NOT_HALTED; } - if (pic32mx_info->dev_type == MX_1_2) - config0_address = PIC32MX_DEVCFG0_1_2; - else + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: + config0_address = PIC32MX_DEVCFG0_1xx_2xx; + break; + default: config0_address = PIC32MX_DEVCFG0; + break; + } target_read_u32(target, config0_address, &devcfg0); @@ -276,10 +300,17 @@ static int pic32mx_protect_check(struct flash_bank *bank) num_pages = 0xffff; /* All pages protected */ } else { /* pgm flash */ - if (pic32mx_info->dev_type == MX_1_2) - num_pages = (~devcfg0 >> 10) & 0x3f; - else + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + num_pages = (~devcfg0 >> 10) & 0x7f; + break; + case MX_17x_27x: + num_pages = (~devcfg0 >> 10) & 0x1ff; + break; + default: num_pages = (~devcfg0 >> 12) & 0xff; + break; + } } for (s = 0; s < bank->num_sectors && s < num_pages; s++) @@ -430,23 +461,27 @@ static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } /* Change values for counters and row size, depending on variant */ - if (pic32mx_info->dev_type == MX_1_2) { + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: /* 128 byte row */ pic32mx_flash_write_code[8] = 0x2CD30020; pic32mx_flash_write_code[14] = 0x24840080; pic32mx_flash_write_code[15] = 0x24A50080; pic32mx_flash_write_code[17] = 0x24C6FFE0; row_size = 128; - } else { + break; + default: /* 512 byte row */ pic32mx_flash_write_code[8] = 0x2CD30080; pic32mx_flash_write_code[14] = 0x24840200; pic32mx_flash_write_code[15] = 0x24A50200; pic32mx_flash_write_code[17] = 0x24C6FF80; row_size = 512; + break; } uint8_t code[sizeof(pic32mx_flash_write_code)]; @@ -472,9 +507,9 @@ static int pic32mx_write_block(struct flash_bank *bank, const uint8_t *buffer, mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; - init_reg_param(®_params[0], "a0", 32, PARAM_IN_OUT); - init_reg_param(®_params[1], "a1", 32, PARAM_OUT); - init_reg_param(®_params[2], "a2", 32, PARAM_OUT); + init_reg_param(®_params[0], "r4", 32, PARAM_IN_OUT); + init_reg_param(®_params[1], "r5", 32, PARAM_OUT); + init_reg_param(®_params[2], "r6", 32, PARAM_OUT); int row_offset = offset % row_size; uint8_t *new_buffer = NULL; @@ -682,17 +717,21 @@ static int pic32mx_probe(struct flash_bank *bank) /* Check for PIC32mx1xx/2xx */ for (i = 0; pic32mx_devs[i].name != NULL; i++) { if (pic32mx_devs[i].devid == (device_id & 0x0fffffff)) { - if ((*(pic32mx_devs[i].name) == '1') || (*(pic32mx_devs[i].name) == '2')) - pic32mx_info->dev_type = MX_1_2; + if ((pic32mx_devs[i].name[0] == '1') || (pic32mx_devs[i].name[0] == '2')) + pic32mx_info->dev_type = (pic32mx_devs[i].name[1] == '7') ? MX_17x_27x : MX_1xx_2xx; break; } } - if (pic32mx_info->dev_type == MX_1_2) + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: page_size = 1024; - else + break; + default: page_size = 4096; - + break; + } if (Virt2Phys(bank->base) == PIC32MX_PHYS_BOOT_FLASH) { /* 0x1FC00000: Boot flash size */ @@ -706,20 +745,29 @@ static int pic32mx_probe(struct flash_bank *bank) } #else /* fixed 12k boot bank - see comments above */ - if (pic32mx_info->dev_type == MX_1_2) + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: num_pages = (3 * 1024); - else + break; + default: num_pages = (12 * 1024); + break; + } #endif } else { /* read the flash size from the device */ if (target_read_u32(target, PIC32MX_BMXPFMSZ, &num_pages) != ERROR_OK) { - if (pic32mx_info->dev_type == MX_1_2) { + switch (pic32mx_info->dev_type) { + case MX_1xx_2xx: + case MX_17x_27x: LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 32k flash"); num_pages = (32 * 1024); - } else { + break; + default: LOG_WARNING("PIC32MX flash size failed, probe inaccurate - assuming 512k flash"); num_pages = (512 * 1024); + break; } } } @@ -831,7 +879,6 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) COMMAND_HANDLER(pic32mx_handle_unlock_command) { - uint32_t mchip_cmd; struct target *target = NULL; struct mips_m4k_common *mips_m4k; struct mips_ejtag *ejtag_info; @@ -856,7 +903,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); /* first check status of device */ - mchip_cmd = MCHP_STATUS; + uint8_t mchip_cmd = MCHP_STATUS; mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); if (mchip_cmd & (1 << 7)) { /* device is not locked */ diff --git a/src/flash/nor/psoc4.c b/src/flash/nor/psoc4.c index 72541d5dc..c7c85737c 100644 --- a/src/flash/nor/psoc4.c +++ b/src/flash/nor/psoc4.c @@ -20,6 +20,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -102,12 +105,12 @@ const struct psoc4_chip_details psoc4_devices[] = { /* 4100 series */ { 0x0410, "CY8C4124PVI-432", "SSOP-28", .flash_size_in_kb = 16 }, { 0x0411, "CY8C4124PVI-442", "SSOP-28", .flash_size_in_kb = 16 }, - { 0x0416, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 }, + { 0x041C, "CY8C4124LQI-443", "QFN-40", .flash_size_in_kb = 16 }, { 0x041A, "CY8C4124AXI-443", "TQFP-44", .flash_size_in_kb = 16 }, { 0x041B, "CY8C4125AXI-473", "TQFP-44", .flash_size_in_kb = 32 }, { 0x0412, "CY8C4125PVI-482", "SSOP-28", .flash_size_in_kb = 32 }, { 0x0417, "CY8C4125LQI-483", "QFN-40", .flash_size_in_kb = 32 }, - { 0x041C, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 }, + { 0x0416, "CY8C4125AXI-483", "TQFP-44", .flash_size_in_kb = 32 }, /* CCG1 series */ { 0x0490, "CYPD1103-35FNXI", "CSP-35", .flash_size_in_kb = 32 }, @@ -221,7 +224,7 @@ static int psoc4_sysreq(struct target *target, uint8_t cmd, uint16_t cmd_param, &sysreq_wait_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for sysreq code"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } /* Write the code */ retval = target_write_buffer(target, diff --git a/src/flash/nor/sim3x.c b/src/flash/nor/sim3x.c index df4e19c29..ce9a21ed5 100644 --- a/src/flash/nor/sim3x.c +++ b/src/flash/nor/sim3x.c @@ -14,6 +14,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -748,7 +751,7 @@ static int sim3x_read_info(struct flash_bank *bank) } if (((cpuid >> 4) & 0xfff) != 0xc23) { - LOG_ERROR("Target is not CortexM3"); + LOG_ERROR("Target is not Cortex-M3"); return ERROR_FAIL; } @@ -1009,7 +1012,7 @@ COMMAND_HANDLER(sim3x_lock) return ret; if ((val & CPUID_CHECK_VALUE_MASK) != CPUID_CHECK_VALUE) { - LOG_ERROR("Target is not ARM CortexM3 or is already locked"); + LOG_ERROR("Target is not ARM Cortex-M3 or is already locked"); return ERROR_FAIL; } } else { diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c index fdbdec484..ef7672d14 100644 --- a/src/flash/nor/spi.c +++ b/src/flash/nor/spi.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -49,27 +47,31 @@ const struct flash_device flash_devices[] = { FLASH_ID("sp s25fl004", 0xd8, 0xc7, 0x00120201, 0x100, 0x10000, 0x80000), FLASH_ID("sp s25fl008", 0xd8, 0xc7, 0x00130201, 0x100, 0x10000, 0x100000), FLASH_ID("sp s25fl016", 0xd8, 0xc7, 0x00140201, 0x100, 0x10000, 0x200000), - FLASH_ID("sp s25fl116k", 0xd8, 0xC7, 0x00154001, 0x100, 0x10000, 0x200000), + FLASH_ID("sp s25fl116k", 0xd8, 0xc7, 0x00154001, 0x100, 0x10000, 0x200000), FLASH_ID("sp s25fl032", 0xd8, 0xc7, 0x00150201, 0x100, 0x10000, 0x400000), - FLASH_ID("sp s25fl132k", 0xd8, 0xC7, 0x00164001, 0x100, 0x10000, 0x400000), + FLASH_ID("sp s25fl132k", 0xd8, 0xc7, 0x00164001, 0x100, 0x10000, 0x400000), FLASH_ID("sp s25fl064", 0xd8, 0xc7, 0x00160201, 0x100, 0x10000, 0x800000), - FLASH_ID("sp s25fl164k", 0xd8, 0xC7, 0x00174001, 0x100, 0x10000, 0x800000), - FLASH_ID("sp s25fl128", 0xd8, 0xC7, 0x00182001, 0x100, 0x10000, 0x1000000), - FLASH_ID("sp s25fl256", 0xd8, 0xC7, 0x00190201, 0x100, 0x10000, 0x2000000), + FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000), + FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000), + FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000), FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000), FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000), FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000), FLASH_ID("atmel 25f4096", 0x52, 0x62, 0x0064001f, 0x100, 0x10000, 0x80000), FLASH_ID("atmel 25fs040", 0xd7, 0xc7, 0x0004661f, 0x100, 0x10000, 0x80000), FLASH_ID("mac 25l512", 0xd8, 0xc7, 0x001020c2, 0x010, 0x10000, 0x10000), - FLASH_ID("mac 25l1005", 0xd8, 0xd8, 0x001120c2, 0x010, 0x10000, 0x20000), + FLASH_ID("mac 25l1005", 0xd8, 0xc7, 0x001120c2, 0x010, 0x10000, 0x20000), FLASH_ID("mac 25l2005", 0xd8, 0xc7, 0x001220c2, 0x010, 0x10000, 0x40000), FLASH_ID("mac 25l4005", 0xd8, 0xc7, 0x001320c2, 0x010, 0x10000, 0x80000), FLASH_ID("mac 25l8005", 0xd8, 0xc7, 0x001420c2, 0x010, 0x10000, 0x100000), FLASH_ID("mac 25l1605", 0xd8, 0xc7, 0x001520c2, 0x100, 0x10000, 0x200000), FLASH_ID("mac 25l3205", 0xd8, 0xc7, 0x001620c2, 0x100, 0x10000, 0x400000), FLASH_ID("mac 25l6405", 0xd8, 0xc7, 0x001720c2, 0x100, 0x10000, 0x800000), - FLASH_ID("mcr n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000), + FLASH_ID("micron n25q064", 0xd8, 0xc7, 0x0017ba20, 0x100, 0x10000, 0x800000), + FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000), +#if BUILD_RISCV == 1 + FLASH_ID("issi is25lp128", 0xd8, 0xc7, 0x0018609d, 0x100, 0x10000, 0x1000000), +#endif FLASH_ID("win w25q80bv", 0xd8, 0xc7, 0x001440ef, 0x100, 0x10000, 0x100000), FLASH_ID("win w25q32fv", 0xd8, 0xc7, 0x001640ef, 0x100, 0x10000, 0x400000), FLASH_ID("win w25q32dw", 0xd8, 0xc7, 0x001660ef, 0x100, 0x10000, 0x400000), @@ -79,6 +81,5 @@ const struct flash_device flash_devices[] = { FLASH_ID("gd gd25q16c", 0xd8, 0xc7, 0x001540c8, 0x100, 0x10000, 0x200000), FLASH_ID("gd gd25q32c", 0xd8, 0xc7, 0x001640c8, 0x100, 0x10000, 0x400000), FLASH_ID("gd gd25q128c", 0xd8, 0xc7, 0x001840c8, 0x100, 0x10000, 0x1000000), - FLASH_ID("micron n25q128", 0xd8, 0xc7, 0x0018ba20, 0x100, 0x10000, 0x1000000), FLASH_ID(NULL, 0, 0, 0, 0, 0, 0) }; diff --git a/src/flash/nor/spi.h b/src/flash/nor/spi.h index 6e939b769..a1849983f 100644 --- a/src/flash/nor/spi.h +++ b/src/flash/nor/spi.h @@ -16,11 +16,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_FLASH_NOR_SPI_H +#define OPENOCD_FLASH_NOR_SPI_H + /* data structure to maintain flash ids from different vendors */ struct flash_device { char *name; @@ -56,3 +57,5 @@ extern const struct flash_device flash_devices[]; #define SPIFLASH_PAGE_PROGRAM 0x02 /* Page Program */ #define SPIFLASH_FAST_READ 0x0B /* Fast Read */ #define SPIFLASH_READ 0x03 /* Normal Read */ + +#endif /* OPENOCD_FLASH_NOR_SPI_H */ diff --git a/src/flash/nor/stellaris.c b/src/flash/nor/stellaris.c index 451f19b7b..d28ceee4b 100644 --- a/src/flash/nor/stellaris.c +++ b/src/flash/nor/stellaris.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /*************************************************************************** @@ -602,7 +600,7 @@ static void stellaris_read_clock_info(struct flash_bank *bank) LOG_DEBUG("Stellaris PLLCFG %" PRIx32 "", pllcfg); stellaris_info->rcc = rcc; - stellaris_info->rcc = rcc2; + stellaris_info->rcc2 = rcc2; sysdiv = (rcc >> 23) & 0xF; usesysdiv = (rcc >> 22) & 0x1; @@ -1065,7 +1063,7 @@ static int stellaris_write_block(struct flash_bank *bank, &write_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } /* plus a buffer big enough for this data */ if (wcount * 4 < buffer_size) @@ -1080,7 +1078,7 @@ static int stellaris_write_block(struct flash_bank *bank, } LOG_DEBUG("retry target_alloc_working_area(%s, size=%u)", target_name(target), (unsigned) buffer_size); - }; + } target_write_buffer(target, write_algorithm->address, sizeof(stellaris_write_code), diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 82f112ef7..d44670768 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -620,7 +618,7 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); @@ -639,7 +637,7 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */ init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* count (halfword-16bit) */ diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 89fc75dcf..4d750951c 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -65,9 +63,15 @@ * 1 MiByte STM32F42x/43x part with DB1M Option set: * 4 x 16, 1 x 64, 3 x 128, 4 x 16, 1 x 64, 3 x 128. * - * STM32F7 + * STM32F7[4|5] * 1 MiByte part with 4 x 32, 1 x 128, 3 x 256. * + * STM32F7[6|7] + * 1 MiByte part in single bank mode with 4 x 32, 1 x 128, 3 x 256. + * 1 MiByte part in dual-bank mode two banks with 4 x 16, 1 x 64, 3 x 128 each. + * 2 MiByte part in single-bank mode with 4 x 32, 1 x 128, 7 x 256. + * 2 MiByte part in dual-bank mode two banks with 4 x 16, 1 x 64, 7 x 128 each. + * * Protection size is sector size. * * Tested with STM3220F-EVAL board. @@ -86,6 +90,9 @@ * RM0385 * http://www.st.com/web/en/resource/technical/document/reference_manual/DM00124865.pdf * + * RM0410 + * http://www.st.com/resource/en/reference_manual/dm00224583.pdf + * * STM32F1x series - notice that this code was copy, pasted and knocked * into a stm32f2x driver, so in case something has been converted or * bugs haven't been fixed, here are the original manuals: @@ -103,6 +110,9 @@ #define FLASH_ERASE_TIMEOUT 10000 #define FLASH_WRITE_TIMEOUT 5 +/* Mass erase time can be as high as 32 s in x8 mode. */ +#define FLASH_MASS_ERASE_TIMEOUT 33000 + #define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_KEYR 0x40023c04 @@ -113,11 +123,10 @@ #define STM32_FLASH_OPTCR1 0x40023c18 /* FLASH_CR register bits */ - #define FLASH_PG (1 << 0) #define FLASH_SER (1 << 1) -#define FLASH_MER (1 << 2) -#define FLASH_MER1 (1 << 15) +#define FLASH_MER (1 << 2) /* MER/MER1 for f76x/77x */ +#define FLASH_MER1 (1 << 15) /* MER2 for f76x/77x, confusing ... */ #define FLASH_STRT (1 << 16) #define FLASH_PSIZE_8 (0 << 8) #define FLASH_PSIZE_16 (1 << 8) @@ -129,7 +138,6 @@ #define FLASH_LOCK (1 << 31) /* FLASH_SR register bits */ - #define FLASH_BSY (1 << 16) #define FLASH_PGSERR (1 << 7) /* Programming sequence error */ #define FLASH_PGPERR (1 << 6) /* Programming parallelism error */ @@ -140,22 +148,12 @@ #define FLASH_ERROR (FLASH_PGSERR | FLASH_PGPERR | FLASH_PGAERR | FLASH_WRPERR | FLASH_OPERR) /* STM32_FLASH_OPTCR register bits */ - -#define OPT_LOCK (1 << 0) -#define OPT_START (1 << 1) - -/* STM32_FLASH_OBR bit definitions (reading) */ - -#define OPT_ERROR 0 -#define OPT_READOUT 1 -#define OPT_RDWDGSW 2 -#define OPT_RDRSTSTOP 3 -#define OPT_RDRSTSTDBY 4 -#define OPT_BFB2 5 /* dual flash bank only */ -#define OPT_DB1M 14 /* 1 MiB devices dual flash bank option */ +#define OPTCR_LOCK (1 << 0) +#define OPTCR_START (1 << 1) +#define OPTCR_NDBANK (1 << 29) /* not dual bank mode */ +#define OPTCR_DB1M (1 << 30) /* 1 MiB devices dual flash bank option */ /* register unlock keys */ - #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -165,14 +163,17 @@ struct stm32x_options { uint8_t RDP; - uint8_t user_options; + uint16_t user_options; /* bit 0-7 usual options, bit 8-11 extra options */ uint32_t protection; + uint32_t boot_addr; }; struct stm32x_flash_bank { struct stm32x_options option_bytes; int probed; - bool has_large_mem; /* stm32f42x/stm32f43x family */ + bool has_large_mem; /* F42x/43x/469/479/7xx in dual bank mode */ + bool has_boot_addr; /* F7xx */ + bool has_extra_options; /* F42x/43x/469/479/7xx */ uint32_t user_bank_size; }; @@ -286,7 +287,7 @@ static int stm32x_unlock_option_reg(struct target *target) if (retval != ERROR_OK) return retval; - if ((ctrl & OPT_LOCK) == 0) + if ((ctrl & OPTCR_LOCK) == 0) return ERROR_OK; /* unlock option registers */ @@ -302,7 +303,7 @@ static int stm32x_unlock_option_reg(struct target *target) if (retval != ERROR_OK) return retval; - if (ctrl & OPT_LOCK) { + if (ctrl & OPTCR_LOCK) { LOG_ERROR("options not unlocked STM32_FLASH_OPTCR: %" PRIx32, ctrl); return ERROR_TARGET_FAILURE; } @@ -323,18 +324,30 @@ static int stm32x_read_options(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - stm32x_info->option_bytes.user_options = optiondata & 0xec; + /* caution: F2 implements 5 bits (WDG_SW only) + * whereas F7 6 bits (IWDG_SW and WWDG_SW) in user_options */ + stm32x_info->option_bytes.user_options = optiondata & 0xfc; stm32x_info->option_bytes.RDP = (optiondata >> 8) & 0xff; stm32x_info->option_bytes.protection = (optiondata >> 16) & 0xfff; - if (stm32x_info->has_large_mem) { + if (stm32x_info->has_extra_options) { + /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */ + stm32x_info->option_bytes.user_options |= (optiondata >> 20) & 0xf00; + } + if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) { retval = target_read_u32(target, STM32_FLASH_OPTCR1, &optiondata); if (retval != ERROR_OK) return retval; - /* append protection bits */ - stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000; + /* FLASH_OPTCR1 has quite diffent meanings ... */ + if (stm32x_info->has_boot_addr) { + /* for F7xx it contains boot0 and boot1 */ + stm32x_info->option_bytes.boot_addr = optiondata; + } else { + /* for F42x/43x/469/479 it contains 12 additional protection bits */ + stm32x_info->option_bytes.protection |= (optiondata >> 4) & 0x00fff000; + } } if (stm32x_info->option_bytes.RDP != 0xAA) @@ -347,7 +360,7 @@ static int stm32x_write_options(struct flash_bank *bank) { struct stm32x_flash_bank *stm32x_info = NULL; struct target *target = bank->target; - uint32_t optiondata; + uint32_t optiondata, optiondata2; stm32x_info = bank->driver_priv; @@ -356,36 +369,46 @@ static int stm32x_write_options(struct flash_bank *bank) return retval; /* rebuild option data */ - optiondata = stm32x_info->option_bytes.user_options; + optiondata = stm32x_info->option_bytes.user_options & 0xfc; optiondata |= stm32x_info->option_bytes.RDP << 8; optiondata |= (stm32x_info->option_bytes.protection & 0x0fff) << 16; - /* program options */ - retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata); - if (retval != ERROR_OK) - return retval; + if (stm32x_info->has_extra_options) { + /* F42x/43x/469/479 and 7xx have up to 4 bits of extra options */ + optiondata |= (stm32x_info->option_bytes.user_options & 0xf00) << 20; + } - if (stm32x_info->has_large_mem) { + if (stm32x_info->has_large_mem || stm32x_info->has_boot_addr) { + if (stm32x_info->has_boot_addr) { + /* F7xx uses FLASH_OPTCR1 for boot0 and boot1 ... */ + optiondata2 = stm32x_info->option_bytes.boot_addr; + } else { + /* F42x/43x/469/479 uses FLASH_OPTCR1 for additional protection bits */ + optiondata2 = (stm32x_info->option_bytes.protection & 0x00fff000) << 4; + } - uint32_t optiondata2 = 0; - optiondata2 |= (stm32x_info->option_bytes.protection & 0x00fff000) << 4; retval = target_write_u32(target, STM32_FLASH_OPTCR1, optiondata2); if (retval != ERROR_OK) return retval; } + /* program options */ + retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata); + if (retval != ERROR_OK) + return retval; + /* start programming cycle */ - retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPT_START); + retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPTCR_START); if (retval != ERROR_OK) return retval; - /* wait for completion */ - retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); + /* wait for completion, this might trigger a security erase and take a while */ + retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; /* relock registers */ - retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPT_LOCK); + retval = target_write_u32(target, STM32_FLASH_OPTCR, optiondata | OPTCR_LOCK); if (retval != ERROR_OK) return retval; @@ -403,11 +426,25 @@ static int stm32x_protect_check(struct flash_bank *bank) return retval; } - for (int i = 0; i < bank->num_sectors; i++) { - if (stm32x_info->option_bytes.protection & (1 << i)) - bank->sectors[i].is_protected = 0; - else - bank->sectors[i].is_protected = 1; + if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) { + /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */ + for (int i = 0; i < (bank->num_sectors >> 1); i++) { + if (stm32x_info->option_bytes.protection & (1 << i)) { + bank->sectors[i << 1].is_protected = 0; + bank->sectors[(i << 1) + 1].is_protected = 0; + } else { + bank->sectors[i << 1].is_protected = 1; + bank->sectors[(i << 1) + 1].is_protected = 1; + } + } + } else { + /* one protection bit per sector */ + for (int i = 0; i < bank->num_sectors; i++) { + if (stm32x_info->option_bytes.protection & (1 << i)) + bank->sectors[i].is_protected = 0; + else + bank->sectors[i].is_protected = 1; + } } return ERROR_OK; @@ -418,8 +455,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) struct target *target = bank->target; int i; - assert(first < bank->num_sectors); - assert(last < bank->num_sectors); + assert((0 <= first) && (first <= last) && (last < bank->num_sectors)); if (bank->target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -479,8 +515,18 @@ static int stm32x_protect(struct flash_bank *bank, int set, int first, int last) return retval; } - for (int i = first; i <= last; i++) { + if (stm32x_info->has_boot_addr && stm32x_info->has_large_mem) { + /* F76x/77x: bit k protects sectors 2*k and 2*k+1 */ + if ((first & 1) != 0 || (last & 1) != 1) { + LOG_ERROR("sector protection must be double sector aligned"); + return ERROR_FAIL; + } else { + first >>= 1; + last >>= 1; + } + } + for (int i = first; i <= last; i++) { if (set) stm32x_info->option_bytes.protection &= ~(1 << i); else @@ -551,7 +597,7 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), @@ -570,7 +616,7 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; @@ -721,14 +767,31 @@ static int stm32x_write(struct flash_bank *bank, const uint8_t *buffer, return target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); } -static void setup_sector(struct flash_bank *bank, int start, int num, int size) +static int setup_sector(struct flash_bank *bank, int start, int num, int size) { + for (int i = start; i < (start + num) ; i++) { assert(i < bank->num_sectors); bank->sectors[i].offset = bank->size; bank->sectors[i].size = size; bank->size += bank->sectors[i].size; + LOG_DEBUG("sector %d: %dkBytes", i, size >> 10); } + + return start + num; +} + +static void setup_bank(struct flash_bank *bank, int start, + uint16_t flash_size_in_kb, uint16_t max_sector_size_in_kb) +{ + int remain; + + start = setup_sector(bank, start, 4, (max_sector_size_in_kb / 8) * 1024); + start = setup_sector(bank, start, 1, (max_sector_size_in_kb / 2) * 1024); + + /* remaining sectors all of size max_sector_size_in_kb */ + remain = (flash_size_in_kb / max_sector_size_in_kb) - 1; + start = setup_sector(bank, start, remain, max_sector_size_in_kb * 1024); } static int stm32x_get_device_id(struct flash_bank *bank, uint32_t *device_id) @@ -776,6 +839,8 @@ static int stm32x_probe(struct flash_bank *bank) stm32x_info->probed = 0; stm32x_info->has_large_mem = false; + stm32x_info->has_boot_addr = false; + stm32x_info->has_extra_options = false; /* read stm32 device id register */ int retval = stm32x_get_device_id(bank, &device_id); @@ -783,29 +848,50 @@ static int stm32x_probe(struct flash_bank *bank) return retval; LOG_INFO("device id = 0x%08" PRIx32 "", device_id); - /* set max flash size depending on family */ + /* set max flash size depending on family, id taken from AN2606 */ switch (device_id & 0xfff) { - case 0x411: - case 0x413: + case 0x411: /* F20x/21x */ + case 0x413: /* F40x/41x */ max_flash_size_in_kb = 1024; break; - case 0x419: - case 0x434: + + case 0x419: /* F42x/43x */ + case 0x434: /* F469/479 */ + stm32x_info->has_extra_options = true; max_flash_size_in_kb = 2048; break; - case 0x423: + + case 0x423: /* F401xB/C */ max_flash_size_in_kb = 256; break; - case 0x431: - case 0x433: - case 0x421: + + case 0x421: /* F446 */ + case 0x431: /* F411 */ + case 0x433: /* F401xD/E */ + case 0x441: /* F412 */ max_flash_size_in_kb = 512; break; - case 0x449: + + case 0x458: /* F410 */ + max_flash_size_in_kb = 128; + break; + + case 0x449: /* F74x/75x */ max_flash_size_in_kb = 1024; max_sector_size_in_kb = 256; flash_size_reg = 0x1FF0F442; + stm32x_info->has_extra_options = true; + stm32x_info->has_boot_addr = true; break; + + case 0x451: /* F76x/77x */ + max_flash_size_in_kb = 2048; + max_sector_size_in_kb = 256; + flash_size_reg = 0x1FF0F442; + stm32x_info->has_extra_options = true; + stm32x_info->has_boot_addr = true; + break; + default: LOG_WARNING("Cannot identify target as a STM32 family."); return ERROR_FAIL; @@ -834,33 +920,48 @@ static int stm32x_probe(struct flash_bank *bank) /* did we assign flash size? */ assert(flash_size_in_kb != 0xffff); - /* calculate numbers of pages */ - int num_pages = (flash_size_in_kb / max_sector_size_in_kb) + 4; - /* Devices with > 1024 kiByte always are dual-banked */ if (flash_size_in_kb > 1024) stm32x_info->has_large_mem = true; - /* F42x/43x 1024 kiByte devices have a dual bank option */ - if ((device_id & 0xfff) == 0x419 && (flash_size_in_kb == 1024)) { + /* F42x/43x/469/479 1024 kiByte devices have a dual bank option */ + if ((device_id & 0xfff) == 0x419 || (device_id & 0xfff) == 0x434) { uint32_t optiondata; retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); if (retval != ERROR_OK) { LOG_DEBUG("unable to read option bytes"); return retval; } - if (optiondata & (1 << OPT_DB1M)) { + if ((flash_size_in_kb > 1024) || (optiondata & OPTCR_DB1M)) { stm32x_info->has_large_mem = true; - LOG_INFO("Dual Bank 1024 kiB STM32F42x/43x found"); + LOG_INFO("Dual Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb); + } else { + stm32x_info->has_large_mem = false; + LOG_INFO("Single Bank %d kiB STM32F42x/43x/469/479 found", flash_size_in_kb); } } - /* check for dual-banked devices */ - if (stm32x_info->has_large_mem) - num_pages += 4; + /* F76x/77x devices have a dual bank option */ + if ((device_id & 0xfff) == 0x451) { + uint32_t optiondata; + retval = target_read_u32(target, STM32_FLASH_OPTCR, &optiondata); + if (retval != ERROR_OK) { + LOG_DEBUG("unable to read option bytes"); + return retval; + } + if (optiondata & OPTCR_NDBANK) { + stm32x_info->has_large_mem = false; + LOG_INFO("Single Bank %d kiB STM32F76x/77x found", flash_size_in_kb); + } else { + stm32x_info->has_large_mem = true; + max_sector_size_in_kb >>= 1; /* sector size divided by 2 in dual-bank mode */ + LOG_INFO("Dual Bank %d kiB STM32F76x/77x found", flash_size_in_kb); + } + } - /* check that calculation result makes sense */ - assert(num_pages > 0); + /* calculate numbers of pages */ + int num_pages = flash_size_in_kb / max_sector_size_in_kb + + (stm32x_info->has_large_mem ? 8 : 4); if (bank->sectors) { free(bank->sectors); @@ -870,35 +971,25 @@ static int stm32x_probe(struct flash_bank *bank) bank->base = base_address; bank->num_sectors = num_pages; bank->sectors = malloc(sizeof(struct flash_sector) * num_pages); + for (i = 0; i < num_pages; i++) { + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } bank->size = 0; - - /* fixed memory */ - setup_sector(bank, 0, 4, (max_sector_size_in_kb / 8) * 1024); - setup_sector(bank, 4, 1, (max_sector_size_in_kb / 2) * 1024); + LOG_DEBUG("allocated %d sectors", num_pages); if (stm32x_info->has_large_mem) { - if (flash_size_in_kb == 1024) { - setup_sector(bank, 5, 3, 128 * 1024); - setup_sector(bank, 12, 4, 16 * 1024); - setup_sector(bank, 16, 1, 64 * 1024); - setup_sector(bank, 17, 3, 128 * 1024); - } else { - setup_sector(bank, 5, 7, 128 * 1024); - setup_sector(bank, 12, 4, 16 * 1024); - setup_sector(bank, 16, 1, 64 * 1024); - setup_sector(bank, 17, 7, 128 * 1024); - } + /* dual-bank */ + setup_bank(bank, 0, flash_size_in_kb >> 1, max_sector_size_in_kb); + setup_bank(bank, num_pages >> 1, flash_size_in_kb >> 1, + max_sector_size_in_kb); } else { - setup_sector(bank, 4 + 1, MIN(12, num_pages) - 5, - max_sector_size_in_kb * 1024); - } - for (i = 0; i < num_pages; i++) { - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = 0; + /* single-bank */ + setup_bank(bank, 0, flash_size_in_kb, max_sector_size_in_kb); } + assert((bank->size >> 10) == flash_size_in_kb); stm32x_info->probed = 1; - return ERROR_OK; } @@ -948,6 +1039,18 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) case 0x2003: rev_str = "X"; break; + + case 0x2007: + rev_str = "1"; + break; + + case 0x200F: + rev_str = "V"; + break; + + case 0x201F: + rev_str = "2"; + break; } break; @@ -978,6 +1081,7 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) break; } break; + case 0x421: device_str = "STM32F446"; @@ -987,9 +1091,12 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) break; } break; + case 0x423: case 0x431: case 0x433: + case 0x458: + case 0x441: device_str = "STM32F4xx (Low Power)"; switch (rev_id) { @@ -1017,6 +1124,16 @@ static int get_stm32x_info(struct flash_bank *bank, char *buf, int buf_size) } break; + case 0x451: + device_str = "STM32F7[6|7]x"; + + switch (rev_id) { + case 0x1000: + rev_str = "A"; + break; + } + break; + default: snprintf(buf, buf_size, "Cannot identify target as a STM32F2/4/7\n"); return ERROR_FAIL; @@ -1114,6 +1231,7 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) static int stm32x_mass_erase(struct flash_bank *bank) { int retval; + uint32_t flash_mer; struct target *target = bank->target; struct stm32x_flash_bank *stm32x_info = NULL; @@ -1130,17 +1248,19 @@ static int stm32x_mass_erase(struct flash_bank *bank) /* mass erase flash memory */ if (stm32x_info->has_large_mem) - retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER | FLASH_MER1); + flash_mer = FLASH_MER | FLASH_MER1; else - retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER); + flash_mer = FLASH_MER; + + retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), flash_mer); if (retval != ERROR_OK) return retval; retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), - FLASH_MER | FLASH_STRT); + flash_mer | FLASH_STRT); if (retval != ERROR_OK) return retval; - retval = stm32x_wait_status_busy(bank, 30000); + retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -1179,6 +1299,107 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command) return retval; } +COMMAND_HANDLER(stm32f2x_handle_options_read_command) +{ + int retval; + struct flash_bank *bank; + struct stm32x_flash_bank *stm32x_info = NULL; + + if (CMD_ARGC != 1) { + command_print(CMD_CTX, "stm32f2x options_read "); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32x_read_options(bank); + if (ERROR_OK != retval) + return retval; + + stm32x_info = bank->driver_priv; + if (stm32x_info->has_extra_options) { + if (stm32x_info->has_boot_addr) { + uint32_t boot_addr = stm32x_info->option_bytes.boot_addr; + + command_print(CMD_CTX, "stm32f2x user_options 0x%03X," + " boot_add0 0x%04X, boot_add1 0x%04X", + stm32x_info->option_bytes.user_options, + boot_addr & 0xffff, (boot_addr & 0xffff0000) >> 16); + } else { + command_print(CMD_CTX, "stm32f2x user_options 0x%03X,", + stm32x_info->option_bytes.user_options); + } + } else { + command_print(CMD_CTX, "stm32f2x user_options 0x%02X", + stm32x_info->option_bytes.user_options); + + } + + return retval; +} + +COMMAND_HANDLER(stm32f2x_handle_options_write_command) +{ + int retval; + struct flash_bank *bank; + struct stm32x_flash_bank *stm32x_info = NULL; + uint16_t user_options, boot_addr0, boot_addr1; + + if (CMD_ARGC < 1) { + command_print(CMD_CTX, "stm32f2x options_write ..."); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32x_read_options(bank); + if (ERROR_OK != retval) + return retval; + + stm32x_info = bank->driver_priv; + if (stm32x_info->has_boot_addr) { + if (CMD_ARGC != 4) { + command_print(CMD_CTX, "stm32f2x options_write " + " "); + return ERROR_COMMAND_SYNTAX_ERROR; + } + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[2], boot_addr0); + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[3], boot_addr1); + stm32x_info->option_bytes.boot_addr = boot_addr0 | (((uint32_t) boot_addr1) << 16); + } else { + if (CMD_ARGC != 2) { + command_print(CMD_CTX, "stm32f2x options_write "); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } + + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], user_options); + if (user_options & (stm32x_info->has_extra_options ? ~0xffc : ~0xfc)) { + command_print(CMD_CTX, "stm32f2x invalid user_options"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + stm32x_info->option_bytes.user_options = user_options; + + if (stm32x_write_options(bank) != ERROR_OK) { + command_print(CMD_CTX, "stm32f2x failed to write options"); + return ERROR_OK; + } + + /* switching between single- and dual-bank modes requires re-probe */ + /* ... and reprogramming of whole flash */ + stm32x_info->probed = 0; + + command_print(CMD_CTX, "stm32f2x write options complete.\n" + "INFO: a reset or power cycle is required " + "for the new settings to take effect."); + return retval; +} + static const struct command_registration stm32x_exec_command_handlers[] = { { .name = "lock", @@ -1201,6 +1422,20 @@ static const struct command_registration stm32x_exec_command_handlers[] = { .usage = "bank_id", .help = "Erase entire flash device.", }, + { + .name = "options_read", + .handler = stm32f2x_handle_options_read_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Read and display device option bytes.", + }, + { + .name = "options_write", + .handler = stm32f2x_handle_options_write_command, + .mode = COMMAND_EXEC, + .usage = "bank_id user_options [ boot_add0 boot_add1]", + .help = "Write option bytes", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 6bdb51d60..fa0c48b4f 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -13,8 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -28,18 +27,22 @@ /* STM32L4xxx series for reference. * - * RM0351 - * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf + * RM0351 (STM32L4x5/STM32L4x6) + * http://www.st.com/resource/en/reference_manual/dm00083560.pdf * - * STM32L476RG Datasheet (for erase timing) - * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf + * RM0394 (STM32L43x/44x/45x/46x) + * http://www.st.com/resource/en/reference_manual/dm00151940.pdf * + * STM32L476RG Datasheet (for erase timing) + * http://www.st.com/resource/en/datasheet/stm32l476rg.pdf * - * The device has normally two banks, but on 512 and 256 kiB devices an - * option byte is available to map all sectors to the first bank. + * The RM0351 devices have normally two banks, but on 512 and 256 kiB devices + * an option byte is available to map all sectors to the first bank. * Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices * handlers do! * + * RM0394 devices have a single bank only. + * */ /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ @@ -463,21 +466,21 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, */ static const uint8_t stm32l4_flash_write_code[] = { - 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x22, 0xd0, 0x47, 0x68, - 0xb8, 0xeb, 0x07, 0x06, 0x07, 0x2e, 0xf5, 0xd3, 0xdf, 0xf8, 0x3c, 0x60, - 0x66, 0x61, 0x57, 0xf8, 0x04, 0x6b, 0x42, 0xf8, 0x04, 0x6b, 0x57, 0xf8, - 0x04, 0x6b, 0x42, 0xf8, 0x04, 0x6b, 0xbf, 0xf3, 0x4f, 0x8f, 0x26, 0x69, - 0x16, 0xf4, 0x80, 0x3f, 0xfb, 0xd1, 0x16, 0xf0, 0xfa, 0x0f, 0x07, 0xd1, - 0x8f, 0x42, 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x07, 0x47, 0x60, 0x01, 0x3b, - 0x13, 0xb1, 0xd9, 0xe7, 0x00, 0x21, 0x41, 0x60, 0x30, 0x46, 0x00, 0xbe, - 0x01, 0x00, 0x00, 0x00 + 0xd0, 0xf8, 0x00, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x21, 0xd0, 0x45, 0x68, + 0xb8, 0xeb, 0x05, 0x06, 0x44, 0xbf, 0x76, 0x18, 0x36, 0x1a, 0x08, 0x2e, + 0xf2, 0xd3, 0xdf, 0xf8, 0x36, 0x60, 0x66, 0x61, 0xf5, 0xe8, 0x02, 0x67, + 0xe2, 0xe8, 0x02, 0x67, 0xbf, 0xf3, 0x4f, 0x8f, 0x26, 0x69, 0x16, 0xf4, + 0x80, 0x3f, 0xfb, 0xd1, 0x16, 0xf0, 0xfa, 0x0f, 0x07, 0xd1, 0x8d, 0x42, + 0x28, 0xbf, 0x00, 0xf1, 0x08, 0x05, 0x45, 0x60, 0x01, 0x3b, 0x13, 0xb1, + 0xda, 0xe7, 0x00, 0x21, 0x41, 0x60, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x00, + 0x00, 0x00 }; if (target_alloc_working_area(target, sizeof(stm32l4_flash_write_code), &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32l4_flash_write_code), @@ -497,7 +500,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - }; + } armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; @@ -600,6 +603,7 @@ static int stm32l4_probe(struct flash_bank *bank) struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; int i; uint16_t flash_size_in_kb = 0xffff; + uint16_t max_flash_size_in_kb; uint32_t device_id; uint32_t options; uint32_t base_address = 0x08000000; @@ -614,7 +618,15 @@ static int stm32l4_probe(struct flash_bank *bank) /* set max flash size depending on family */ switch (device_id & 0xfff) { + case 0x461: case 0x415: + max_flash_size_in_kb = 1024; + break; + case 0x462: + max_flash_size_in_kb = 512; + break; + case 0x435: + max_flash_size_in_kb = 256; break; default: LOG_WARNING("Cannot identify target as a STM32L4 family."); @@ -624,6 +636,19 @@ static int stm32l4_probe(struct flash_bank *bank) /* get flash size from target. */ retval = target_read_u16(target, FLASH_SIZE_REG, &flash_size_in_kb); + /* failed reading flash size or flash size invalid (early silicon), + * default to max target family */ + if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { + LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash", + max_flash_size_in_kb); + flash_size_in_kb = max_flash_size_in_kb; + } + + LOG_INFO("flash size = %dkbytes", flash_size_in_kb); + + /* did we assign flash size? */ + assert(flash_size_in_kb != 0xffff); + /* get options to for DUAL BANK. */ retval = target_read_u32(target, STM32_FLASH_OPTR, &options); @@ -633,8 +658,6 @@ static int stm32l4_probe(struct flash_bank *bank) else stm32l4_info->option_bytes.bank_b_start = flash_size_in_kb << 9; - LOG_INFO("flash size = %dkbytes", flash_size_in_kb); - /* did we assign flash size? */ assert((flash_size_in_kb != 0xffff) && flash_size_in_kb); @@ -686,7 +709,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) if (retval != ERROR_OK) return retval; - uint16_t device_id = dbgmcu_idcode & 0xffff; + uint16_t device_id = dbgmcu_idcode & 0xfff; uint8_t rev_id = dbgmcu_idcode >> 28; uint8_t rev_minor = 0; int i; @@ -701,8 +724,20 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) const char *device_str; switch (device_id) { - case 0x6415: - device_str = "STM32L4xx"; + case 0x461: + device_str = "STM32L496/4A6"; + break; + + case 0x415: + device_str = "STM32L475/476/486"; + break; + + case 0x462: + device_str = "STM32L45x/46x"; + break; + + case 0x435: + device_str = "STM32L43x/44x"; break; default: diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 7b0b0cc1d..e4f499d3c 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -103,8 +101,11 @@ static int stm32lx_lock_program_memory(struct flash_bank *bank); static int stm32lx_enable_write_half_page(struct flash_bank *bank); static int stm32lx_erase_sector(struct flash_bank *bank, int sector); static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank); +static int stm32lx_lock(struct flash_bank *bank); +static int stm32lx_unlock(struct flash_bank *bank); static int stm32lx_mass_erase(struct flash_bank *bank); static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout); +static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb); struct stm32lx_rev { uint16_t rev; @@ -132,14 +133,17 @@ struct stm32lx_flash_bank { uint32_t user_bank_size; uint32_t flash_base; - const struct stm32lx_part_info *part_info; + struct stm32lx_part_info part_info; }; static const struct stm32lx_rev stm32_416_revs[] = { { 0x1000, "A" }, { 0x1008, "Y" }, { 0x1038, "W" }, { 0x1078, "V" }, }; static const struct stm32lx_rev stm32_417_revs[] = { - { 0x1000, "A" }, { 0x1008, "Z" }, + { 0x1000, "A" }, { 0x1008, "Z" }, { 0x1018, "Y" }, { 0x1038, "X" } +}; +static const struct stm32lx_rev stm32_425_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Y" }, }; static const struct stm32lx_rev stm32_427_revs[] = { { 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" }, @@ -153,6 +157,12 @@ static const struct stm32lx_rev stm32_436_revs[] = { static const struct stm32lx_rev stm32_437_revs[] = { { 0x1000, "A" }, }; +static const struct stm32lx_rev stm32_447_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Z" }, +}; +static const struct stm32lx_rev stm32_457_revs[] = { + { 0x1000, "A" }, { 0x1008, "Z" }, +}; static const struct stm32lx_part_info stm32lx_parts[] = { { @@ -171,7 +181,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .id = 0x417, .revs = stm32_417_revs, .num_revs = ARRAY_SIZE(stm32_417_revs), - .device_str = "STM32L0xx", + .device_str = "STM32L0xx (Cat. 3)", .page_size = 128, .pages_per_sector = 32, .max_flash_size_kb = 64, @@ -179,6 +189,18 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .flash_base = 0x40022000, .fsize_base = 0x1FF8007C, }, + { + .id = 0x425, + .revs = stm32_425_revs, + .num_revs = ARRAY_SIZE(stm32_425_revs), + .device_str = "STM32L0xx (Cat. 2)", + .page_size = 128, + .pages_per_sector = 32, + .max_flash_size_kb = 32, + .has_dual_banks = false, + .flash_base = 0x40022000, + .fsize_base = 0x1FF8007C, + }, { .id = 0x427, .revs = stm32_427_revs, @@ -187,8 +209,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 256, - .first_bank_size_kb = 192, - .has_dual_banks = true, + .has_dual_banks = false, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, }, @@ -225,11 +246,36 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 512, - .first_bank_size_kb = 256, + .first_bank_size_kb = 0, /* determined in runtime */ .has_dual_banks = true, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, }, + { + .id = 0x447, + .revs = stm32_447_revs, + .num_revs = ARRAY_SIZE(stm32_447_revs), + .device_str = "STM32L0xx (Cat.5)", + .page_size = 128, + .pages_per_sector = 32, + .max_flash_size_kb = 192, + .first_bank_size_kb = 0, /* determined in runtime */ + .has_dual_banks = false, /* determined in runtime */ + .flash_base = 0x40022000, + .fsize_base = 0x1FF8007C, + }, + { + .id = 0x457, + .revs = stm32_457_revs, + .num_revs = ARRAY_SIZE(stm32_457_revs), + .device_str = "STM32L0xx (Cat.1)", + .page_size = 128, + .pages_per_sector = 32, + .max_flash_size_kb = 16, + .has_dual_banks = false, + .flash_base = 0x40022000, + .fsize_base = 0x1FF8007C, + }, }; /* flash bank stm32lx 0 0 @@ -255,7 +301,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command) stm32lx_info->user_bank_size = bank->size; /* the stm32l erased value is 0x00 */ - bank->default_padded_value = 0x00; + bank->default_padded_value = bank->erased_value = 0x00; return ERROR_OK; } @@ -286,6 +332,46 @@ COMMAND_HANDLER(stm32lx_handle_mass_erase_command) return retval; } +COMMAND_HANDLER(stm32lx_handle_lock_command) +{ + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32lx_lock(bank); + + if (retval == ERROR_OK) + command_print(CMD_CTX, "STM32Lx locked, takes effect after power cycle."); + else + command_print(CMD_CTX, "STM32Lx lock failed"); + + return retval; +} + +COMMAND_HANDLER(stm32lx_handle_unlock_command) +{ + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct flash_bank *bank; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (ERROR_OK != retval) + return retval; + + retval = stm32lx_unlock(bank); + + if (retval == ERROR_OK) + command_print(CMD_CTX, "STM32Lx unlocked, takes effect after power cycle."); + else + command_print(CMD_CTX, "STM32Lx unlock failed"); + + return retval; +} + static int stm32lx_protect_check(struct flash_bank *bank) { int retval; @@ -351,7 +437,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; - uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; + uint32_t hp_nb = stm32lx_info->part_info.page_size / 2; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; @@ -365,19 +451,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff /* see contib/loaders/flash/stm32lx.S for src */ static const uint8_t stm32lx_flash_write_code[] = { - /* write_word: */ - 0x00, 0x23, /* movs r3, #0 */ - 0x04, 0xe0, /* b test_done */ - - /* write_word: */ - 0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */ - 0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */ - 0x01, 0x33, /* adds r3, #1 */ - - /* test_done: */ - 0x93, 0x42, /* cmp r3, r2 */ - 0xf8, 0xd3, /* bcc write_word */ - 0x00, 0xbe, /* bkpt 0 */ + 0x92, 0x00, 0x8A, 0x18, 0x01, 0xE0, 0x08, 0xC9, 0x08, 0xC0, 0x91, 0x42, 0xFB, 0xD1, 0x00, 0xBE }; /* Make sure we're performing a half-page aligned write. */ @@ -391,7 +465,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff &write_algorithm) != ERROR_OK) { LOG_DEBUG("no working area for block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } /* Write the flashing code */ retval = target_write_buffer(target, @@ -410,7 +484,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff else buffer_size /= 2; - if (buffer_size <= stm32lx_info->part_info->page_size) { + if (buffer_size <= stm32lx_info->part_info.page_size) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); @@ -503,7 +577,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff * is reduced by 50% using this slower method. */ - LOG_WARNING("couldn't use loader, falling back to page memory writes"); + LOG_WARNING("Couldn't use loader, falling back to page memory writes"); while (count > 0) { uint32_t this_count; @@ -544,7 +618,7 @@ static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer, struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; - uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; + uint32_t hp_nb = stm32lx_info->part_info.page_size / 2; uint32_t halfpages_number; uint32_t bytes_remaining = 0; uint32_t address = bank->base + offset; @@ -674,9 +748,9 @@ static int stm32lx_probe(struct flash_bank *bank) uint32_t device_id; uint32_t base_address = FLASH_BANK0_ADDRESS; uint32_t second_bank_base; + unsigned int n; stm32lx_info->probed = 0; - stm32lx_info->part_info = NULL; int retval = stm32lx_read_id_code(bank->target, &device_id); if (retval != ERROR_OK) @@ -686,20 +760,24 @@ static int stm32lx_probe(struct flash_bank *bank) LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id); - for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { - if ((device_id & 0xfff) == stm32lx_parts[n].id) - stm32lx_info->part_info = &stm32lx_parts[n]; + for (n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { + if ((device_id & 0xfff) == stm32lx_parts[n].id) { + stm32lx_info->part_info = stm32lx_parts[n]; + break; + } } - if (!stm32lx_info->part_info) { + if (n == ARRAY_SIZE(stm32lx_parts)) { LOG_WARNING("Cannot identify target as a STM32L family."); return ERROR_FAIL; + } else { + LOG_INFO("Device: %s", stm32lx_info->part_info.device_str); } - stm32lx_info->flash_base = stm32lx_info->part_info->flash_base; + stm32lx_info->flash_base = stm32lx_info->part_info.flash_base; /* Get the flash size from target. */ - retval = target_read_u16(target, stm32lx_info->part_info->fsize_base, + retval = target_read_u16(target, stm32lx_info->part_info.fsize_base, &flash_size_in_kb); /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K @@ -716,29 +794,34 @@ static int stm32lx_probe(struct flash_bank *bank) * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash", - stm32lx_info->part_info->max_flash_size_kb); - flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; - } else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) { + stm32lx_info->part_info.max_flash_size_kb); + flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb; + } else if (flash_size_in_kb > stm32lx_info->part_info.max_flash_size_kb) { LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash", - flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb, - stm32lx_info->part_info->max_flash_size_kb); - flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; + flash_size_in_kb, stm32lx_info->part_info.max_flash_size_kb, + stm32lx_info->part_info.max_flash_size_kb); + flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb; } - if (stm32lx_info->part_info->has_dual_banks) { + /* Overwrite default dual-bank configuration */ + retval = stm32lx_update_part_info(bank, flash_size_in_kb); + if (retval != ERROR_OK) + return ERROR_FAIL; + + if (stm32lx_info->part_info.has_dual_banks) { /* Use the configured base address to determine if this is the first or second flash bank. * Verify that the base address is reasonably correct and determine the flash bank size */ second_bank_base = base_address + - stm32lx_info->part_info->first_bank_size_kb * 1024; + stm32lx_info->part_info.first_bank_size_kb * 1024; if (bank->base == second_bank_base || !bank->base) { /* This is the second bank */ base_address = second_bank_base; flash_size_in_kb = flash_size_in_kb - - stm32lx_info->part_info->first_bank_size_kb; + stm32lx_info->part_info.first_bank_size_kb; } else if (bank->base == base_address) { /* This is the first bank */ - flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb; + flash_size_in_kb = stm32lx_info->part_info.first_bank_size_kb; } else { LOG_WARNING("STM32L flash bank base address config is incorrect." " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, @@ -797,60 +880,13 @@ static int stm32lx_auto_probe(struct flash_bank *bank) return stm32lx_probe(bank); } -static int stm32lx_erase_check(struct flash_bank *bank) -{ - struct target *target = bank->target; - const int buffer_size = 4096; - int i; - uint32_t nBytes; - int retval = ERROR_OK; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - uint8_t *buffer = malloc(buffer_size); - if (buffer == NULL) { - LOG_ERROR("failed to allocate read buffer"); - return ERROR_FAIL; - } - - for (i = 0; i < bank->num_sectors; i++) { - uint32_t j; - bank->sectors[i].is_erased = 1; - - /* Loop chunk by chunk over the sector */ - for (j = 0; j < bank->sectors[i].size; j += buffer_size) { - uint32_t chunk; - chunk = buffer_size; - if (chunk > (j - bank->sectors[i].size)) - chunk = (j - bank->sectors[i].size); - - retval = target_read_memory(target, bank->base - + bank->sectors[i].offset + j, 4, chunk / 4, buffer); - if (retval != ERROR_OK) - break; - - for (nBytes = 0; nBytes < chunk; nBytes++) { - if (buffer[nBytes] != 0x00) { - bank->sectors[i].is_erased = 0; - break; - } - } - } - if (retval != ERROR_OK) - break; - } - free(buffer); - - return retval; -} - /* This method must return a string displaying information about the bank */ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) { struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; + const struct stm32lx_part_info *info = &stm32lx_info->part_info; + uint16_t rev_id = stm32lx_info->idcode >> 16; + const char *rev_str = NULL; if (!stm32lx_info->probed) { int retval = stm32lx_probe(bank); @@ -861,32 +897,21 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) } } - const struct stm32lx_part_info *info = stm32lx_info->part_info; - - if (info) { - const char *rev_str = NULL; - uint16_t rev_id = stm32lx_info->idcode >> 16; - - for (unsigned int i = 0; i < info->num_revs; i++) - if (rev_id == info->revs[i].rev) - rev_str = info->revs[i].str; + for (unsigned int i = 0; i < info->num_revs; i++) + if (rev_id == info->revs[i].rev) + rev_str = info->revs[i].str; - if (rev_str != NULL) { - snprintf(buf, buf_size, - "%s - Rev: %s", - stm32lx_info->part_info->device_str, rev_str); - } else { - snprintf(buf, buf_size, - "%s - Rev: unknown (0x%04x)", - stm32lx_info->part_info->device_str, rev_id); - } - - return ERROR_OK; + if (rev_str != NULL) { + snprintf(buf, buf_size, + "%s - Rev: %s", + info->device_str, rev_str); } else { - snprintf(buf, buf_size, "Cannot identify target as a STM32Lx"); - - return ERROR_FAIL; + snprintf(buf, buf_size, + "%s - Rev: unknown (0x%04x)", + info->device_str, rev_id); } + + return ERROR_OK; } static const struct command_registration stm32lx_exec_command_handlers[] = { @@ -897,6 +922,20 @@ static const struct command_registration stm32lx_exec_command_handlers[] = { .usage = "bank_id", .help = "Erase entire flash device. including available EEPROM", }, + { + .name = "lock", + .handler = stm32lx_handle_lock_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Increase the readout protection to Level 1.", + }, + { + .name = "unlock", + .handler = stm32lx_handle_unlock_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Lower the readout protection from Level 1 to 0.", + }, COMMAND_REGISTRATION_DONE }; @@ -921,7 +960,7 @@ struct flash_driver stm32lx_flash = { .read = default_flash_read, .probe = stm32lx_probe, .auto_probe = stm32lx_auto_probe, - .erase_check = stm32lx_erase_check, + .erase_check = default_flash_blank_check, .protect_check = stm32lx_protect_check, .info = stm32lx_get_info, }; @@ -1081,7 +1120,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector) if (retval != ERROR_OK) return retval; - for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector; + for (int page = 0; page < (int)stm32lx_info->part_info.pages_per_sector; page++) { reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE; retval = target_write_u32(target, @@ -1094,7 +1133,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector) return retval; uint32_t addr = bank->base + bank->sectors[sector].offset + (page - * stm32lx_info->part_info->page_size); + * stm32lx_info->part_info.page_size); retval = target_write_u32(target, addr, 0x0); if (retval != ERROR_OK) return retval; @@ -1230,33 +1269,37 @@ static int stm32lx_obl_launch(struct flash_bank *bank) return tries ? ERROR_OK : ERROR_FAIL; } -static int stm32lx_mass_erase(struct flash_bank *bank) +static int stm32lx_lock(struct flash_bank *bank) { int retval; struct target *target = bank->target; - struct stm32lx_flash_bank *stm32lx_info = NULL; - uint32_t reg32; if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; } - stm32lx_info = bank->driver_priv; - retval = stm32lx_unlock_options_bytes(bank); if (retval != ERROR_OK) return retval; - /* mass erase flash memory */ /* set the RDP protection level to 1 */ retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR1); if (retval != ERROR_OK) return retval; - retval = stm32lx_obl_launch(bank); - if (retval != ERROR_OK) - return retval; + return ERROR_OK; +} + +static int stm32lx_unlock(struct flash_bank *bank) +{ + int retval; + struct target *target = bank->target; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } retval = stm32lx_unlock_options_bytes(bank); if (retval != ERROR_OK) @@ -1271,6 +1314,35 @@ static int stm32lx_mass_erase(struct flash_bank *bank) if (retval != ERROR_OK) return retval; + return ERROR_OK; +} + +static int stm32lx_mass_erase(struct flash_bank *bank) +{ + int retval; + struct target *target = bank->target; + struct stm32lx_flash_bank *stm32lx_info = NULL; + uint32_t reg32; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + stm32lx_info = bank->driver_priv; + + retval = stm32lx_lock(bank); + if (retval != ERROR_OK) + return retval; + + retval = stm32lx_obl_launch(bank); + if (retval != ERROR_OK) + return retval; + + retval = stm32lx_unlock(bank); + if (retval != ERROR_OK) + return retval; + retval = stm32lx_obl_launch(bank); if (retval != ERROR_OK) return retval; @@ -1285,3 +1357,22 @@ static int stm32lx_mass_erase(struct flash_bank *bank) return ERROR_OK; } + +static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb) +{ + struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; + + switch (stm32lx_info->part_info.id) { + case 0x447: /* STM32L0xx (Cat.5) devices */ + if (flash_size_in_kb == 192 || flash_size_in_kb == 128) { + stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2; + stm32lx_info->part_info.has_dual_banks = true; + } + break; + case 0x437: /* STM32L1xx (Cat.5/Cat.6) */ + stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2; + break; + } + + return ERROR_OK; +} diff --git a/src/flash/nor/stmsmi.c b/src/flash/nor/stmsmi.c index 6f73c3684..781ea3b5b 100644 --- a/src/flash/nor/stmsmi.c +++ b/src/flash/nor/stmsmi.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* STM Serial Memory Interface (SMI) controller is a SPI bus controller @@ -162,7 +160,7 @@ FLASH_BANK_COMMAND_HANDLER(stmsmi_flash_bank_command) /* timeout in ms */ static int poll_tff(struct target *target, uint32_t io_base, int timeout) { - long long endtime; + int64_t endtime; if (SMI_READ_REG(SMI_SR) & SMI_TFF) return ERROR_OK; @@ -213,7 +211,7 @@ static int wait_till_ready(struct flash_bank *bank, int timeout) { uint32_t status; int retval; - long long endtime; + int64_t endtime; endtime = timeval_ms() + timeout; do { diff --git a/src/flash/nor/str7x.c b/src/flash/nor/str7x.c index 515b97512..11179f520 100644 --- a/src/flash/nor/str7x.c +++ b/src/flash/nor/str7x.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -487,7 +485,7 @@ static int str7x_write_block(struct flash_bank *bank, const uint8_t *buffer, if (target_alloc_working_area_try(target, sizeof(str7x_flash_write_code), &write_algorithm) != ERROR_OK) { return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } uint8_t code[sizeof(str7x_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(str7x_flash_write_code), diff --git a/src/flash/nor/str9x.c b/src/flash/nor/str9x.c index 8b3c13714..3b7ca2aa7 100644 --- a/src/flash/nor/str9x.c +++ b/src/flash/nor/str9x.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -390,7 +388,7 @@ static int str9x_write_block(struct flash_bank *bank, &write_algorithm) != ERROR_OK) { LOG_WARNING("no working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - }; + } uint8_t code[sizeof(str9x_flash_write_code)]; target_buffer_set_u32_array(target, code, ARRAY_SIZE(str9x_flash_write_code), diff --git a/src/flash/nor/str9xpec.c b/src/flash/nor/str9xpec.c index f0af53a41..eb391e8fb 100644 --- a/src/flash/nor/str9xpec.c +++ b/src/flash/nor/str9xpec.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 8a30e1cd9..b93d12694 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -72,16 +70,27 @@ COMMAND_HANDLER(handle_flash_info_command) struct flash_bank *p; int j = 0; int retval; + bool show_sectors = false; + bool prot_block_available; - if (CMD_ARGC != 1) + if (CMD_ARGC < 1 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; + if (CMD_ARGC == 2) { + if (strcmp("sectors", CMD_ARGV[1]) == 0) + show_sectors = true; + else + return ERROR_COMMAND_SYNTAX_ERROR; + } + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (retval != ERROR_OK) return retval; if (p != NULL) { char buf[1024]; + int num_blocks; + struct flash_sector *block_array; /* attempt auto probe */ retval = p->driver->auto_probe(p); @@ -102,22 +111,32 @@ COMMAND_HANDLER(handle_flash_info_command) p->size, p->bus_width, p->chip_width); - for (j = 0; j < p->num_sectors; j++) { - char *protect_state; - if (p->sectors[j].is_protected == 0) + prot_block_available = p->num_prot_blocks && p->prot_blocks; + if (!show_sectors && prot_block_available) { + block_array = p->prot_blocks; + num_blocks = p->num_prot_blocks; + } else { + block_array = p->sectors; + num_blocks = p->num_sectors; + } + + for (j = 0; j < num_blocks; j++) { + char *protect_state = ""; + + if (block_array[j].is_protected == 0) protect_state = "not protected"; - else if (p->sectors[j].is_protected == 1) + else if (block_array[j].is_protected == 1) protect_state = "protected"; - else + else if (!show_sectors || !prot_block_available) protect_state = "protection state unknown"; command_print(CMD_CTX, "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", j, - p->sectors[j].offset, - p->sectors[j].size, - p->sectors[j].size >> 10, + block_array[j].offset, + block_array[j].size, + block_array[j].size >> 10, protect_state); } @@ -162,6 +181,7 @@ COMMAND_HANDLER(handle_flash_probe_command) COMMAND_HANDLER(handle_flash_erase_check_command) { + bool blank = true; if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; @@ -187,10 +207,11 @@ COMMAND_HANDLER(handle_flash_erase_check_command) if (p->sectors[j].is_erased == 0) erase_state = "not erased"; else if (p->sectors[j].is_erased == 1) - erase_state = "erased"; + continue; else erase_state = "erase state unknown"; + blank = false; command_print(CMD_CTX, "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s", j, @@ -200,6 +221,8 @@ COMMAND_HANDLER(handle_flash_erase_check_command) erase_state); } + if (blank) + command_print(CMD_CTX, "\tBank is erased"); return retval; } @@ -274,8 +297,8 @@ static int flash_check_sector_parameters(struct command_context *cmd_ctx, } if (!(last <= (num_sectors - 1))) { - command_print(cmd_ctx, "ERROR: last sector must be <= %d", - (int) num_sectors - 1); + command_print(cmd_ctx, "ERROR: last sector must be <= %" PRIu32, + num_sectors - 1); return ERROR_FAIL; } @@ -318,7 +341,7 @@ COMMAND_HANDLER(handle_flash_erase_command) "in %fs", first, last, p->bank_number, duration_elapsed(&bench)); } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_flash_protect_command) @@ -331,30 +354,35 @@ COMMAND_HANDLER(handle_flash_protect_command) struct flash_bank *p; int retval; + int num_blocks; retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); if (retval != ERROR_OK) return retval; + if (p->num_prot_blocks) + num_blocks = p->num_prot_blocks; + else + num_blocks = p->num_sectors; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first); if (strcmp(CMD_ARGV[2], "last") == 0) - last = p->num_sectors - 1; + last = num_blocks - 1; else COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); bool set; COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); - retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); + retval = flash_check_sector_parameters(CMD_CTX, first, last, num_blocks); if (retval != ERROR_OK) return retval; retval = flash_driver_protect(p, set, first, last); if (retval == ERROR_OK) { - command_print(CMD_CTX, "%s protection for sectors %i " - "through %i on flash bank %d", - (set) ? "set" : "cleared", (int) first, - (int) last, p->bank_number); + command_print(CMD_CTX, "%s protection for sectors %" PRIu32 + " through %" PRIu32 " on flash bank %d", + (set) ? "set" : "cleared", first, last, p->bank_number); } return retval; @@ -555,7 +583,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) { uint32_t offset; uint8_t *buffer; - struct fileio fileio; + struct fileio *fileio; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; @@ -571,26 +599,26 @@ COMMAND_HANDLER(handle_flash_write_bank_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) - return ERROR_OK; + return ERROR_FAIL; size_t filesize; - retval = fileio_size(&fileio, &filesize); + retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) { - fileio_close(&fileio); + fileio_close(fileio); return retval; } buffer = malloc(filesize); if (buffer == NULL) { - fileio_close(&fileio); + fileio_close(fileio); LOG_ERROR("Out of memory"); return ERROR_FAIL; } size_t buf_cnt; - if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { + if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { free(buffer); - fileio_close(&fileio); - return ERROR_OK; + fileio_close(fileio); + return ERROR_FAIL; } retval = flash_driver_write(p, buffer, offset, buf_cnt); @@ -605,7 +633,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) duration_elapsed(&bench), duration_kbps(&bench, filesize)); } - fileio_close(&fileio); + fileio_close(fileio); return retval; } @@ -614,7 +642,7 @@ COMMAND_HANDLER(handle_flash_read_bank_command) { uint32_t offset; uint8_t *buffer; - struct fileio fileio; + struct fileio *fileio; uint32_t length; size_t written; @@ -652,8 +680,8 @@ COMMAND_HANDLER(handle_flash_read_bank_command) return retval; } - retval = fileio_write(&fileio, length, buffer, &written); - fileio_close(&fileio); + retval = fileio_write(fileio, length, buffer, &written); + fileio_close(fileio); free(buffer); if (retval != ERROR_OK) { LOG_ERROR("Could not write file"); @@ -661,9 +689,9 @@ COMMAND_HANDLER(handle_flash_read_bank_command) } if (duration_measure(&bench) == ERROR_OK) - command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u" + command_print(CMD_CTX, "wrote %zd bytes to file %s from flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - (long)written, CMD_ARGV[1], p->bank_number, offset, + written, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, written)); return retval; @@ -674,12 +702,12 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) { uint32_t offset; uint8_t *buffer_file, *buffer_flash; - struct fileio fileio; + struct fileio *fileio; size_t read_cnt; size_t filesize; int differ; - if (CMD_ARGC != 3) + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; struct duration bench; @@ -690,7 +718,16 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) if (ERROR_OK != retval) return retval; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + offset = 0; + + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + + if (offset > p->size) { + LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank", + offset); + return ERROR_COMMAND_ARGUMENT_INVALID; + } retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) { @@ -698,21 +735,21 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) return retval; } - retval = fileio_size(&fileio, &filesize); + retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) { - fileio_close(&fileio); + fileio_close(fileio); return retval; } buffer_file = malloc(filesize); if (buffer_file == NULL) { LOG_ERROR("Out of memory"); - fileio_close(&fileio); + fileio_close(fileio); return ERROR_FAIL; } - retval = fileio_read(&fileio, filesize, buffer_file, &read_cnt); - fileio_close(&fileio); + retval = fileio_read(fileio, filesize, buffer_file, &read_cnt); + fileio_close(fileio); if (retval != ERROR_OK) { LOG_ERROR("File read failure"); free(buffer_file); @@ -741,9 +778,9 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) } if (duration_measure(&bench) == ERROR_OK) - command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u" + command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - (long)read_cnt, CMD_ARGV[1], p->bank_number, offset, + read_cnt, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, read_cnt)); differ = memcmp(buffer_file, buffer_flash, read_cnt); @@ -811,7 +848,7 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "info", .handler = handle_flash_info_command, .mode = COMMAND_EXEC, - .usage = "bank_id", + .usage = "bank_id ['sectors']", .help = "Print information about a flash bank.", }, { @@ -898,19 +935,20 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "verify_bank", .handler = handle_flash_verify_bank_command, .mode = COMMAND_EXEC, - .usage = "bank_id filename offset", - .help = "Read binary data from flash bank and file, " - "starting at specified byte offset from the " - "beginning of the bank. Compare the contents.", + .usage = "bank_id filename [offset]", + .help = "Compare the contents of a file with the contents of the " + "flash bank. Allow optional offset from beginning of the bank " + "(defaults to zero).", }, { .name = "protect", .handler = handle_flash_protect_command, .mode = COMMAND_EXEC, - .usage = "bank_id first_sector [last_sector|'last'] " + .usage = "bank_id first_block [last_block|'last'] " "('on'|'off')", - .help = "Turn protection on or off for a range of sectors " - "in a given flash bank.", + .help = "Turn protection on or off for a range of protection " + "blocks or sectors in a given flash bank. " + "See 'flash info' output for a list of blocks.", }, { .name = "padded_value", @@ -983,9 +1021,11 @@ COMMAND_HANDLER(handle_flash_bank_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width); - c->default_padded_value = 0xff; + c->default_padded_value = c->erased_value = 0xff; c->num_sectors = 0; c->sectors = NULL; + c->num_prot_blocks = 0; + c->prot_blocks = NULL; c->next = NULL; int retval; diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 86858a84e..a70891e89 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index 599a9c09d..06981f4f4 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -46,6 +44,7 @@ static void virtual_update_bank_info(struct flash_bank *bank) bank->size = master_bank->size; bank->chip_width = master_bank->chip_width; bank->bus_width = master_bank->bus_width; + bank->erased_value = master_bank->erased_value; bank->default_padded_value = master_bank->default_padded_value; bank->num_sectors = master_bank->num_sectors; bank->sectors = master_bank->sectors; diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index 9212e43e2..02df46a3f 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -11,6 +11,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * +* You should have received a copy of the GNU General Public License * +* along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -181,7 +183,7 @@ /* Flash controller configuration values */ #define FLASH_ID_XMC4500 0xA2 -#define FLASH_ID_XMC4800 0x92 +#define FLASH_ID_XMC4300_XMC4700_4800 0x92 #define FLASH_ID_XMC4100_4200 0x9C #define FLASH_ID_XMC4400 0x9F @@ -317,8 +319,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank) } /* This part doesn't follow the typical standard of 0xff - * being the default padding value.*/ - bank->default_padded_value = 0x00; + * being the erased value.*/ + bank->default_padded_value = bank->erased_value = 0x00; return ERROR_OK; } @@ -381,9 +383,9 @@ static int xmc4xxx_probe(struct flash_bank *bank) bank->num_sectors = 12; LOG_DEBUG("XMC4xxx: XMC4500 detected."); break; - case FLASH_ID_XMC4800: + case FLASH_ID_XMC4300_XMC4700_4800: bank->num_sectors = 16; - LOG_DEBUG("XMC4xxx: XMC4800 detected."); + LOG_DEBUG("XMC4xxx: XMC4700/4800 detected."); break; default: LOG_ERROR("XMC4xxx: Unexpected flash ID. got %02" PRIx8, @@ -615,106 +617,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank) return res; } -/* The logical erase value of an xmc4xxx memory cell is 0x00, - * therefore, we cannot use the built in flash blank check and must - * implement our own */ - -/** Checks whether a memory region is zeroed. */ -int xmc4xxx_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) -{ - struct working_area *erase_check_algorithm; - struct reg_param reg_params[3]; - struct armv7m_algorithm armv7m_info; - int retval; - - /* see contrib/loaders/erase_check/armv7m_0_erase_check.s for src */ - - static const uint8_t erase_check_code[] = { - /* loop: */ - 0x03, 0x78, /* ldrb r3, [r0] */ - 0x01, 0x30, /* adds r0, #1 */ - 0x1A, 0x43, /* orrs r2, r2, r3 */ - 0x01, 0x39, /* subs r1, r1, #1 */ - 0xFA, 0xD1, /* bne loop */ - 0x00, 0xBE /* bkpt #0 */ - }; - - /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), - &erase_check_algorithm) != ERROR_OK) - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - - retval = target_write_buffer(target, erase_check_algorithm->address, - sizeof(erase_check_code), (uint8_t *)erase_check_code); - if (retval != ERROR_OK) - return retval; - - armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; - armv7m_info.core_mode = ARM_MODE_THREAD; - - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - buf_set_u32(reg_params[0].value, 0, 32, address); - - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); - - init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0x00); - - retval = target_run_algorithm(target, - 0, - NULL, - 3, - reg_params, - erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 2), - 10000, - &armv7m_info); - - if (retval == ERROR_OK) - *blank = buf_get_u32(reg_params[2].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - - target_free_working_area(target, erase_check_algorithm); - - return retval; -} - -static int xmc4xxx_flash_blank_check(struct flash_bank *bank) -{ - struct target *target = bank->target; - int i; - int retval; - uint32_t blank; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - for (i = 0; i < bank->num_sectors; i++) { - uint32_t address = bank->base + bank->sectors[i].offset; - uint32_t size = bank->sectors[i].size; - - LOG_DEBUG("Erase checking 0x%08"PRIx32, address); - retval = xmc4xxx_blank_check_memory(target, address, size, &blank); - - if (retval != ERROR_OK) - break; - - if (blank == 0x00) - bank->sectors[i].is_erased = 1; - else - bank->sectors[i].is_erased = 0; - } - - return ERROR_OK; -} - static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf, uint32_t offset, bool user_config) { @@ -949,6 +851,14 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_ break; } break; + case 0x300: + dev_str = "XMC4300"; + + switch (rev_id) { + case 0x1: + rev_str = "AA"; + } + break; case 0x400: dev_str = "XMC4400"; @@ -983,6 +893,15 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_ break; } break; + case 0x700: + dev_str = "XMC4700"; + + switch (rev_id) { + case 0x1: + rev_str = "EES-AA"; + break; + } + break; case 0x800: dev_str = "XMC4800"; @@ -1087,11 +1006,6 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level) uint32_t addr; int res; - if ((level < 0) || (level > 1)) { - LOG_ERROR("Invalid user level. Must be 0-1"); - return ERROR_FAIL; - } - switch (level) { case 0: addr = UCB0_BASE; @@ -1099,6 +1013,9 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level) case 1: addr = UCB1_BASE; break; + default: + LOG_ERROR("Invalid user level. Must be 0-1"); + return ERROR_FAIL; } res = xmc4xxx_erase_sector(bank, addr, true); @@ -1435,7 +1352,7 @@ struct flash_driver xmc4xxx_flash = { .read = default_flash_read, .probe = xmc4xxx_probe, .auto_probe = xmc4xxx_probe, - .erase_check = xmc4xxx_flash_blank_check, + .erase_check = default_flash_blank_check, .info = xmc4xxx_get_info_command, .protect_check = xmc4xxx_protect_check, .protect = xmc4xxx_protect, diff --git a/src/hello.c b/src/hello.c index f103ed23c..25938bcf8 100644 --- a/src/hello.c +++ b/src/hello.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/hello.h b/src/hello.h index d06695124..c88c89ddf 100644 --- a/src/hello.h +++ b/src/hello.h @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef OPENOCD_HELLO_H @@ -28,4 +26,4 @@ struct command_registration; */ extern const struct command_registration hello_command_handlers[]; -#endif /* OPENOCD_HELLO_H */ +#endif /* OPENOCD_HELLO_H */ diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am index 9477267f6..e0f7f49bb 100644 --- a/src/helper/Makefile.am +++ b/src/helper/Makefile.am @@ -1,52 +1,49 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libhelper.la - -CONFIGFILES = options.c time_support_common.c - -libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) - -libhelper_la_SOURCES = \ - binarybuffer.c \ - $(CONFIGFILES) \ - configuration.c \ - log.c \ - command.c \ - time_support.c \ - replacements.c \ - fileio.c \ - util.c \ - jim-nvp.c +noinst_LTLIBRARIES += %D%/libhelper.la + +%C%_libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) + +%C%_libhelper_la_SOURCES = \ + %D%/binarybuffer.c \ + %D%/options.c \ + %D%/time_support_common.c \ + %D%/configuration.c \ + %D%/log.c \ + %D%/command.c \ + %D%/time_support.c \ + %D%/replacements.c \ + %D%/fileio.c \ + %D%/util.c \ + %D%/jep106.c \ + %D%/jim-nvp.c \ + %D%/binarybuffer.h \ + %D%/configuration.h \ + %D%/ioutil.h \ + %D%/list.h \ + %D%/util.h \ + %D%/types.h \ + %D%/log.h \ + %D%/command.h \ + %D%/time_support.h \ + %D%/replacements.h \ + %D%/fileio.h \ + %D%/system.h \ + %D%/jep106.h \ + %D%/jep106.inc \ + %D%/jim-nvp.h if IOUTIL -libhelper_la_SOURCES += ioutil.c +%C%_libhelper_la_SOURCES += %D%/ioutil.c else -libhelper_la_SOURCES += ioutil_stubs.c +%C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c endif -libhelper_la_CFLAGS = +%C%_libhelper_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -libhelper_la_CFLAGS += -Wno-sign-compare +%C%_libhelper_la_CFLAGS += -Wno-sign-compare endif -noinst_HEADERS = \ - binarybuffer.h \ - configuration.h \ - ioutil.h \ - list.h \ - util.h \ - types.h \ - log.h \ - command.h \ - time_support.h \ - replacements.h \ - fileio.h \ - system.h \ - bin2char.sh \ - jim-nvp.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +STARTUP_TCL_SRCS += %D%/startup.tcl +EXTRA_DIST += \ + %D%/bin2char.sh \ + %D%/update_jep106.pl diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 3cadabdb1..76f657f8d 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -47,6 +45,11 @@ static const unsigned char bit_reverse_table256[] = { 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; +static const char hex_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' +}; + void *buf_cpy(const void *from, void *_to, unsigned size) { if (NULL == from || NULL == _to) @@ -371,31 +374,72 @@ void bit_copy_discard(struct bit_copy_queue *q) } } -int unhexify(char *bin, const char *hex, int count) +/** + * Convert a string of hexadecimal pairs into its binary + * representation. + * + * @param[out] bin Buffer to store binary representation. The buffer size must + * be at least @p count. + * @param[in] hex String with hexadecimal pairs to convert into its binary + * representation. + * @param[in] count Number of hexadecimal pairs to convert. + * + * @return The number of converted hexadecimal pairs. + */ +size_t unhexify(uint8_t *bin, const char *hex, size_t count) { - int i, tmp; + size_t i; + char tmp; + + if (!bin || !hex) + return 0; + + memset(bin, 0, count); + + for (i = 0; i < 2 * count; i++) { + if (hex[i] >= 'a' && hex[i] <= 'f') + tmp = hex[i] - 'a' + 10; + else if (hex[i] >= 'A' && hex[i] <= 'F') + tmp = hex[i] - 'A' + 10; + else if (hex[i] >= '0' && hex[i] <= '9') + tmp = hex[i] - '0'; + else + return i / 2; - for (i = 0; i < count; i++) { - if (sscanf(hex + (2 * i), "%02x", &tmp) != 1) - return i; - bin[i] = tmp; + bin[i / 2] |= tmp << (4 * ((i + 1) % 2)); } - return i; + return i / 2; } -int hexify(char *hex, const char *bin, int count, int out_maxlen) +/** + * Convert binary data into a string of hexadecimal pairs. + * + * @param[out] hex Buffer to store string of hexadecimal pairs. The buffer size + * must be at least @p length. + * @param[in] bin Buffer with binary data to convert into hexadecimal pairs. + * @param[in] count Number of bytes to convert. + * @param[in] length Maximum number of characters, including null-terminator, + * to store into @p hex. + * + * @returns The length of the converted string excluding null-terminator. + */ +size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length) { - int i, cmd_len = 0; + size_t i; + uint8_t tmp; + + if (!length) + return 0; - /* May use a length, or a null-terminated string as input. */ - if (count == 0) - count = strlen(bin); + for (i = 0; i < length - 1 && i < 2 * count; i++) { + tmp = (bin[i / 2] >> (4 * ((i + 1) % 2))) & 0x0f; + hex[i] = hex_digits[tmp]; + } - for (i = 0; i < count; i++) - cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff); + hex[i] = 0; - return cmd_len; + return i; } void buffer_shr(void *_buf, unsigned buf_len, unsigned count) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index eaa8c5263..f1da8c4aa 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef BINARYBUFFER_H -#define BINARYBUFFER_H +#ifndef OPENOCD_HELPER_BINARYBUFFER_H +#define OPENOCD_HELPER_BINARYBUFFER_H #include "list.h" @@ -236,8 +234,8 @@ void bit_copy_discard(struct bit_copy_queue *q); /* functions to convert to/from hex encoded buffer * used in ti-icdi driver and gdb server */ -int unhexify(char *bin, const char *hex, int count); -int hexify(char *hex, const char *bin, int count, int out_maxlen); +size_t unhexify(uint8_t *bin, const char *hex, size_t count); +size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen); void buffer_shr(void *_buf, unsigned buf_len, unsigned count); -#endif /* BINARYBUFFER_H */ +#endif /* OPENOCD_HELPER_BINARYBUFFER_H */ diff --git a/src/helper/command.c b/src/helper/command.c index a0aa9e857..5deaee859 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -1175,8 +1173,8 @@ COMMAND_HANDLER(handle_sleep_command) return retval; if (!busy) { - long long then = timeval_ms(); - while (timeval_ms() - then < (long long)duration) { + int64_t then = timeval_ms(); + while (timeval_ms() - then < (int64_t)duration) { target_call_timer_callbacks_now(); usleep(1000); } @@ -1412,6 +1410,8 @@ DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX) +DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX) + #define DEFINE_PARSE_LONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong) DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX) diff --git a/src/helper/command.h b/src/helper/command.h index 0eda5b5e7..bd24156e3 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef COMMAND_H -#define COMMAND_H +#ifndef OPENOCD_HELPER_COMMAND_H +#define OPENOCD_HELPER_COMMAND_H #include @@ -359,10 +357,13 @@ DECLARE_PARSE_WRAPPER(_u16, uint16_t); DECLARE_PARSE_WRAPPER(_u8, uint8_t); DECLARE_PARSE_WRAPPER(_int, int); +DECLARE_PARSE_WRAPPER(_s64, int64_t); DECLARE_PARSE_WRAPPER(_s32, int32_t); DECLARE_PARSE_WRAPPER(_s16, int16_t); DECLARE_PARSE_WRAPPER(_s8, int8_t); +DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); + /** * @brief parses the string @a in into @a out as a @a type, or prints * a command error and passes the error code to the caller. If an error @@ -384,6 +385,9 @@ DECLARE_PARSE_WRAPPER(_s8, int8_t); } \ } while (0) +#define COMMAND_PARSE_ADDRESS(in, out) \ + COMMAND_PARSE_NUMBER(target_addr, in, out) + /** * Parse the string @c as a binary parameter, storing the boolean value * in @c out. The strings @c on and @c off are used to match different @@ -417,4 +421,4 @@ COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label); void script_debug(Jim_Interp *interp, const char *cmd, unsigned argc, Jim_Obj * const *argv); -#endif /* COMMAND_H */ +#endif /* OPENOCD_HELPER_COMMAND_H */ diff --git a/src/helper/configuration.c b/src/helper/configuration.c index dde1491ad..2a278838d 100644 --- a/src/helper/configuration.c +++ b/src/helper/configuration.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/src/helper/configuration.h b/src/helper/configuration.h index 7b9f7119a..3cbcd41f6 100644 --- a/src/helper/configuration.h +++ b/src/helper/configuration.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef CONFIGURATION_H -#define CONFIGURATION_H +#ifndef OPENOCD_HELPER_CONFIGURATION_H +#define OPENOCD_HELPER_CONFIGURATION_H #include @@ -42,4 +40,4 @@ FILE *open_file_from_path(const char *file, const char *mode); char *find_file(const char *name); char *get_home_dir(const char *append_path); -#endif /* CONFIGURATION_H */ +#endif /* OPENOCD_HELPER_CONFIGURATION_H */ diff --git a/src/helper/fileio.c b/src/helper/fileio.c index 2664bfa11..47494dfcd 100644 --- a/src/helper/fileio.c +++ b/src/helper/fileio.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -32,7 +30,7 @@ #include "configuration.h" #include "fileio.h" -struct fileio_internal { +struct fileio { char *url; size_t size; enum fileio_type type; @@ -40,8 +38,22 @@ struct fileio_internal { FILE *file; }; -static inline int fileio_close_local(struct fileio_internal *fileio); -static inline int fileio_open_local(struct fileio_internal *fileio) +static inline int fileio_close_local(struct fileio *fileio) +{ + int retval = fclose(fileio->file); + if (retval != 0) { + if (retval == EBADF) + LOG_ERROR("BUG: fileio->file not a valid file descriptor"); + else + LOG_ERROR("couldn't close %s: %s", fileio->url, strerror(errno)); + + return ERROR_FILEIO_OPERATION_FAILED; + } + + return ERROR_OK; +} + +static inline int fileio_open_local(struct fileio *fileio) { char file_access[4]; ssize_t file_size; @@ -104,69 +116,49 @@ static inline int fileio_open_local(struct fileio_internal *fileio) return ERROR_OK; } -int fileio_open(struct fileio *fileio_p, - const char *url, - enum fileio_access access_type, - enum fileio_type type) +int fileio_open(struct fileio **fileio, const char *url, + enum fileio_access access_type, enum fileio_type type) { int retval; - struct fileio_internal *fileio; + struct fileio *tmp; - fileio = malloc(sizeof(struct fileio_internal)); + tmp = malloc(sizeof(struct fileio)); - fileio->type = type; - fileio->access = access_type; - fileio->url = strdup(url); + tmp->type = type; + tmp->access = access_type; + tmp->url = strdup(url); - retval = fileio_open_local(fileio); + retval = fileio_open_local(tmp); if (retval != ERROR_OK) { - free(fileio->url); - free(fileio); + free(tmp->url); + free(tmp); return retval; } - fileio_p->fp = fileio; - - return ERROR_OK; -} - -static inline int fileio_close_local(struct fileio_internal *fileio) -{ - int retval = fclose(fileio->file); - if (retval != 0) { - if (retval == EBADF) - LOG_ERROR("BUG: fileio_local->file not a valid file descriptor"); - else - LOG_ERROR("couldn't close %s: %s", fileio->url, strerror(errno)); - - return ERROR_FILEIO_OPERATION_FAILED; - } + *fileio = tmp; return ERROR_OK; } -int fileio_close(struct fileio *fileio_p) +int fileio_close(struct fileio *fileio) { int retval; - struct fileio_internal *fileio = fileio_p->fp; retval = fileio_close_local(fileio); free(fileio->url); - fileio->url = NULL; - free(fileio); - fileio_p->fp = NULL; return retval; } -int fileio_seek(struct fileio *fileio_p, size_t position) +int fileio_seek(struct fileio *fileio, size_t position) { int retval; - struct fileio_internal *fileio = fileio_p->fp; + retval = fseek(fileio->file, position, SEEK_SET); + if (retval != 0) { LOG_ERROR("couldn't seek file %s: %s", fileio->url, strerror(errno)); return ERROR_FILEIO_OPERATION_FAILED; @@ -175,36 +167,40 @@ int fileio_seek(struct fileio *fileio_p, size_t position) return ERROR_OK; } -static int fileio_local_read(struct fileio_internal *fileio, - size_t size, void *buffer, size_t *size_read) +static int fileio_local_read(struct fileio *fileio, size_t size, void *buffer, + size_t *size_read) { - ssize_t retval = fread(buffer, 1, size, fileio->file); + ssize_t retval; + + retval = fread(buffer, 1, size, fileio->file); *size_read = (retval >= 0) ? retval : 0; + return (retval < 0) ? retval : ERROR_OK; } -int fileio_read(struct fileio *fileio_p, size_t size, void *buffer, - size_t *size_read) +int fileio_read(struct fileio *fileio, size_t size, void *buffer, + size_t *size_read) { - struct fileio_internal *fileio = fileio_p->fp; return fileio_local_read(fileio, size, buffer, size_read); } -int fileio_read_u32(struct fileio *fileio_p, uint32_t *data) +int fileio_read_u32(struct fileio *fileio, uint32_t *data) { + int retval; uint8_t buf[4]; size_t size_read; - struct fileio_internal *fileio = fileio_p->fp; - int retval = fileio_local_read(fileio, sizeof(uint32_t), buf, &size_read); + + retval = fileio_local_read(fileio, sizeof(uint32_t), buf, &size_read); + if (ERROR_OK == retval && sizeof(uint32_t) != size_read) retval = -EIO; if (ERROR_OK == retval) *data = be_to_h_u32(buf); + return retval; } -static int fileio_local_fgets(struct fileio_internal *fileio, - size_t size, void *buffer) +static int fileio_local_fgets(struct fileio *fileio, size_t size, void *buffer) { if (fgets(buffer, size, fileio->file) == NULL) return ERROR_FILEIO_OPERATION_FAILED; @@ -212,36 +208,44 @@ static int fileio_local_fgets(struct fileio_internal *fileio, return ERROR_OK; } -int fileio_fgets(struct fileio *fileio_p, size_t size, void *buffer) +int fileio_fgets(struct fileio *fileio, size_t size, void *buffer) { - struct fileio_internal *fileio = fileio_p->fp; return fileio_local_fgets(fileio, size, buffer); } -static int fileio_local_write(struct fileio_internal *fileio, - size_t size, const void *buffer, size_t *size_written) +static int fileio_local_write(struct fileio *fileio, size_t size, + const void *buffer, size_t *size_written) { - ssize_t retval = fwrite(buffer, 1, size, fileio->file); + ssize_t retval; + + retval = fwrite(buffer, 1, size, fileio->file); *size_written = (retval >= 0) ? retval : 0; + return (retval < 0) ? retval : ERROR_OK; } -int fileio_write(struct fileio *fileio_p, - size_t size, const void *buffer, size_t *size_written) +int fileio_write(struct fileio *fileio, size_t size, const void *buffer, + size_t *size_written) { - struct fileio_internal *fileio = fileio_p->fp; - int retval = fileio_local_write(fileio, size, buffer, size_written); + int retval; + + retval = fileio_local_write(fileio, size, buffer, size_written); + if (retval == ERROR_OK) fileio->size += *size_written; + return retval; } -int fileio_write_u32(struct fileio *fileio_p, uint32_t data) +int fileio_write_u32(struct fileio *fileio, uint32_t data) { + int retval; uint8_t buf[4]; h_u32_to_be(buf, data); size_t size_written; - int retval = fileio_write(fileio_p, 4, buf, &size_written); + + retval = fileio_write(fileio, 4, buf, &size_written); + if (ERROR_OK == retval && size_written != sizeof(uint32_t)) retval = -EIO; @@ -257,9 +261,8 @@ int fileio_write_u32(struct fileio *fileio_p, uint32_t data) * Avoiding the seek on startup opens up for using streams. * */ -int fileio_size(struct fileio *fileio_p, size_t *size) +int fileio_size(struct fileio *fileio, size_t *size) { - struct fileio_internal *fileio = fileio_p->fp; *size = fileio->size; return ERROR_OK; diff --git a/src/helper/fileio.h b/src/helper/fileio.h index c3824ff8f..ae4a3ecfc 100644 --- a/src/helper/fileio.h +++ b/src/helper/fileio.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef FILEIO_H -#define FILEIO_H +#ifndef OPENOCD_HELPER_FILEIO_H +#define OPENOCD_HELPER_FILEIO_H #define FILEIO_MAX_ERROR_STRING (128) @@ -43,13 +41,10 @@ enum fileio_access { FILEIO_APPENDREAD, /* open for writing, position at end, allow reading */ }; -struct fileio { - /* The structure is opaque */ - struct fileio_internal *fp; -}; +struct fileio; -int fileio_open(struct fileio *fileio, - const char *url, enum fileio_access access_type, enum fileio_type type); +int fileio_open(struct fileio **fileio, const char *url, + enum fileio_access access_type, enum fileio_type type); int fileio_close(struct fileio *fileio); int fileio_seek(struct fileio *fileio, size_t position); @@ -71,4 +66,4 @@ int fileio_size(struct fileio *fileio, size_t *size); #define ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN (-1204) #define ERROR_FILEIO_OPERATION_NOT_SUPPORTED (-1205) -#endif /* FILEIO_H */ +#endif /* OPENOCD_HELPER_FILEIO_H */ diff --git a/src/helper/ioutil.c b/src/helper/ioutil.c index 166256c7d..f1123cd82 100644 --- a/src/helper/ioutil.c +++ b/src/helper/ioutil.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* this file contains various functionality useful to standalone systems */ @@ -243,117 +241,6 @@ COMMAND_HANDLER(handle_cp_command) return retval; } -#define SHOW_RESULT(a, b) LOG_ERROR(# a " failed %d\n", (int)b) - -#define IOSIZE 512 -void copyfile(char *name2, char *name1) -{ - - int err; - char buf[IOSIZE]; - int fd1, fd2; - ssize_t done, wrote; - - fd1 = open(name1, O_WRONLY | O_CREAT, 0664); - if (fd1 < 0) - SHOW_RESULT(open, fd1); - - fd2 = open(name2, O_RDONLY); - if (fd2 < 0) - SHOW_RESULT(open, fd2); - - for (;; ) { - done = read(fd2, buf, IOSIZE); - if (done < 0) { - SHOW_RESULT(read, done); - break; - } - - if (done == 0) - break; - - wrote = write(fd1, buf, done); - if (wrote != done) - SHOW_RESULT(write, wrote); - - if (wrote != done) - break; - } - - err = close(fd1); - if (err < 0) - SHOW_RESULT(close, err); - - err = close(fd2); - if (err < 0) - SHOW_RESULT(close, err); -} - -/* utility fn to copy a directory */ -void copydir(char *name, char *destdir) -{ - int err; - DIR *dirp; - - dirp = opendir(destdir); - if (dirp == NULL) - mkdir(destdir, 0777); - else - err = closedir(dirp); - - dirp = opendir(name); - if (dirp == NULL) - SHOW_RESULT(opendir, -1); - - for (;; ) { - struct dirent *entry = readdir(dirp); - - if (entry == NULL) - break; - - if (strcmp(entry->d_name, ".") == 0) - continue; - if (strcmp(entry->d_name, "..") == 0) - continue; - - int isDir = 0; - struct stat buf; - char fullPath[PATH_MAX]; - strncpy(fullPath, name, PATH_MAX); - strcat(fullPath, "/"); - strncat(fullPath, entry->d_name, PATH_MAX - strlen(fullPath)); - - if (stat(fullPath, &buf) == -1) { - LOG_ERROR("unable to read status from %s", fullPath); - break; - } - isDir = S_ISDIR(buf.st_mode) != 0; - - if (isDir) - continue; - - /* diag_printf(": entry %14s",entry->d_name); */ - char fullname[PATH_MAX]; - char fullname2[PATH_MAX]; - - strcpy(fullname, name); - strcat(fullname, "/"); - strcat(fullname, entry->d_name); - - strcpy(fullname2, destdir); - strcat(fullname2, "/"); - strcat(fullname2, entry->d_name); - /* diag_printf("from %s to %s\n", fullname, fullname2); */ - copyfile(fullname, fullname2); - - /* diag_printf("\n"); */ - } - - err = closedir(dirp); - if (err < 0) - SHOW_RESULT(stat, err); -} - COMMAND_HANDLER(handle_rm_command) { if (CMD_ARGC != 1) diff --git a/src/helper/ioutil.h b/src/helper/ioutil.h index 8cd9157b7..f060aab09 100644 --- a/src/helper/ioutil.h +++ b/src/helper/ioutil.h @@ -12,16 +12,14 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef HELPER_IOUTILS_H -#define HELPER_IOUTILS_H +#ifndef OPENOCD_HELPER_IOUTIL_H +#define OPENOCD_HELPER_IOUTIL_H struct command_context; int ioutil_init(struct command_context *cmd_ctx); -#endif /* HELPER_IOUTILS_H */ +#endif /* OPENOCD_HELPER_IOUTIL_H */ diff --git a/src/helper/ioutil_stubs.c b/src/helper/ioutil_stubs.c index a87f1b6e4..0d81fe665 100644 --- a/src/helper/ioutil_stubs.c +++ b/src/helper/ioutil_stubs.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/helper/jim-nvp.c b/src/helper/jim-nvp.c index 4602a8db9..d13bdfba4 100644 --- a/src/helper/jim-nvp.c +++ b/src/helper/jim-nvp.c @@ -205,7 +205,7 @@ int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere) return JIM_ERR; } -int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len) +int Jim_GetOpt_String(Jim_GetOptInfo *goi, const char **puthere, int *len) { int r; Jim_Obj *o; @@ -215,8 +215,7 @@ int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len) if (r == JIM_OK) { cp = Jim_GetString(o, len); if (puthere) { - /* remove const */ - *puthere = (char *)(cp); + *puthere = cp; } } return r; diff --git a/src/helper/jim-nvp.h b/src/helper/jim-nvp.h index 05d79c4a7..7b4a491d3 100644 --- a/src/helper/jim-nvp.h +++ b/src/helper/jim-nvp.h @@ -41,8 +41,8 @@ * official policies, either expressed or implied, of the Jim Tcl Project. */ -#ifndef JIM_NVP_H -#define JIM_NVP_H +#ifndef OPENOCD_HELPER_JIM_NVP_H +#define OPENOCD_HELPER_JIM_NVP_H #include @@ -245,7 +245,7 @@ int Jim_GetOpt_Obj(Jim_GetOptInfo *goi, Jim_Obj **puthere); * \param puthere - where param is put * \param len - return its length */ -int Jim_GetOpt_String(Jim_GetOptInfo *goi, char **puthere, int *len); +int Jim_GetOpt_String(Jim_GetOptInfo *goi, const char **puthere, int *len); /** Remove argv[0] as double. * @@ -326,4 +326,4 @@ void Jim_GetOpt_NvpUnknown(Jim_GetOptInfo *goi, const Jim_Nvp *lookup, int hadpr */ int Jim_GetOpt_Enum(Jim_GetOptInfo *goi, const char *const *lookup, int *puthere); -#endif +#endif /* OPENOCD_HELPER_JIM_NVP_H */ diff --git a/src/helper/list.h b/src/helper/list.h index 302b91097..6fd0e7ca7 100644 --- a/src/helper/list.h +++ b/src/helper/list.h @@ -1,5 +1,5 @@ -#ifndef _LINUX_LIST_H -#define _LINUX_LIST_H +#ifndef OPENOCD_HELPER_LIST_H +#define OPENOCD_HELPER_LIST_H /* begin local changes */ #include @@ -734,4 +734,4 @@ static inline void hlist_move_list(struct hlist_head *old, ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ pos = n) -#endif +#endif /* OPENOCD_HELPER_LIST_H */ diff --git a/src/helper/log.c b/src/helper/log.c index 0bea1c50c..d4e87f662 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -47,10 +45,10 @@ int debug_level = -1; static FILE *log_output; static struct log_callback *log_callbacks; -static long long last_time; -static long long current_time; +static int64_t last_time; +static int64_t current_time; -static long long start; +static int64_t start; static const char * const log_strings[5] = { "User : ", @@ -105,7 +103,7 @@ static void log_forward(const char *file, unsigned line, const char *function, c } } -/* The log_puts() serves to somewhat different goals: +/* The log_puts() serves two somewhat different goals: * * - logging * - feeding low-level info to the user in GDB or Telnet @@ -136,12 +134,12 @@ static void log_puts(enum log_levels level, if (strlen(string) > 0) { if (debug_level >= LOG_LVL_DEBUG) { /* print with count and time information */ - int t = (int)(timeval_ms()-start); + int64_t t = timeval_ms() - start; #ifdef _DEBUG_FREE_SPACE_ struct mallinfo info; info = mallinfo(); #endif - fprintf(log_output, "%s%d %d %s:%d %s()" + fprintf(log_output, "%s%d %" PRId64 " %s:%d %s()" #ifdef _DEBUG_FREE_SPACE_ " %d" #endif @@ -193,6 +191,30 @@ void log_printf(enum log_levels level, va_end(ap); } +void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, + const char *function, const char *format, va_list args) +{ + char *tmp; + + count++; + + if (level > debug_level) + return; + + tmp = alloc_vprintf(format, args); + + if (!tmp) + return; + + /* + * Note: alloc_vprintf() guarantees that the buffer is at least one + * character longer. + */ + strcat(tmp, "\n"); + log_puts(level, file, line, function, tmp); + free(tmp); +} + void log_printf_lf(enum log_levels level, const char *file, unsigned line, @@ -200,23 +222,10 @@ void log_printf_lf(enum log_levels level, const char *format, ...) { - char *string; va_list ap; - count++; - if (level > debug_level) - return; - va_start(ap, format); - - string = alloc_vprintf(format, ap); - if (string != NULL) { - strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one - *char longer */ - log_puts(level, file, line, function, string); - free(string); - } - + log_vprintf_lf(level, file, line, function, format, ap); va_end(ap); } @@ -242,9 +251,15 @@ COMMAND_HANDLER(handle_log_output_command) { if (CMD_ARGC == 1) { FILE *file = fopen(CMD_ARGV[0], "w"); - - if (file) - log_output = file; + if (file == NULL) { + LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]); + return ERROR_FAIL; + } + if (log_output != stderr && log_output != NULL) { + /* Close previous log file, if it was open and wasn't stderr. */ + fclose(log_output); + } + log_output = file; } return ERROR_OK; @@ -412,12 +427,12 @@ void keep_alive() if (gdb_actual_connections) LOG_WARNING("keep_alive() was not invoked in the " "1000ms timelimit. GDB alive packet not " - "sent! (%lld). Workaround: increase " + "sent! (%" PRId64 "). Workaround: increase " "\"set remotetimeout\" in GDB", current_time-last_time); else LOG_DEBUG("keep_alive() was not invoked in the " - "1000ms timelimit (%lld). This may cause " + "1000ms timelimit (%" PRId64 "). This may cause " "trouble with GDB connections.", current_time-last_time); } diff --git a/src/helper/log.h b/src/helper/log.h index 7f9f32c59..6b938165b 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ERROR_H -#define ERROR_H +#ifndef OPENOCD_HELPER_LOG_H +#define OPENOCD_HELPER_LOG_H #include @@ -62,6 +60,8 @@ enum log_levels { void log_printf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); +void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, + const char *function, const char *format, va_list args); void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); @@ -141,4 +141,4 @@ extern int debug_level; #define ERROR_WAIT (-5) -#endif /* LOG_H */ +#endif /* OPENOCD_HELPER_LOG_H */ diff --git a/src/helper/options.c b/src/helper/options.c index 35bdae299..1cfa55376 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -31,6 +29,15 @@ #include +#include +#include +#if IS_DARWIN +#include +#endif +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + static int help_flag, version_flag; static const struct option long_options[] = { @@ -52,84 +59,129 @@ int configuration_output_handler(struct command_context *context, const char *li return ERROR_OK; } -// #ifdef _WIN32 -static char *find_suffix(const char *text, const char *suffix) +/* Return the canonical path to the directory the openocd executable is in. + * The path should be absolute, use / as path separator and have all symlinks + * resolved. The returned string is malloc'd. */ +static char *find_exe_path(void) { - size_t text_len = strlen(text); - size_t suffix_len = strlen(suffix); + char *exepath = NULL; - if (suffix_len == 0) - return (char *)text + text_len; + do { +#if IS_WIN32 && !IS_CYGWIN + exepath = malloc(MAX_PATH); + if (exepath == NULL) + break; + GetModuleFileName(NULL, exepath, MAX_PATH); - if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0) - return NULL; /* Not a suffix of text */ + /* Convert path separators to UNIX style, should work on Windows also. */ + for (char *p = exepath; *p; p++) { + if (*p == '\\') + *p = '/'; + } - return (char *)text + text_len - suffix_len; -} -// #endif +#elif IS_DARWIN + exepath = malloc(PROC_PIDPATHINFO_MAXSIZE); + if (exepath == NULL) + break; + if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) { + free(exepath); + exepath = NULL; + } -static void add_default_dirs(char* argv0) -{ - const char *run_prefix; - char *path; +#elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */ +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + char *path = malloc(PATH_MAX); + if (path == NULL) + break; + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t size = PATH_MAX; -#ifdef _WIN32 - char strExePath[MAX_PATH]; - GetModuleFileName(NULL, strExePath, MAX_PATH); + if (sysctl(mib, (u_int)ARRAY_SIZE(mib), path, &size, NULL, 0) != 0) + break; - /* Strip executable file name, leaving path */ - *strrchr(strExePath, '\\') = '\0'; +#ifdef HAVE_REALPATH + exepath = realpath(path, NULL); + free(path); +#else + exepath = path; +#endif - /* Convert path separators to UNIX style, should work on Windows also. */ - for (char *p = strExePath; *p; p++) { - if (*p == '\\') - *p = '/'; +#elif defined(HAVE_REALPATH) /* Assume POSIX.1-2008 */ + /* Try Unices in order of likelihood. */ + exepath = realpath("/proc/self/exe", NULL); /* Linux/Cygwin */ + if (exepath == NULL) + exepath = realpath("/proc/self/path/a.out", NULL); /* Solaris */ + if (exepath == NULL) + exepath = realpath("/proc/curproc/file", NULL); /* FreeBSD (Should be covered above) */ +#endif + } while (0); + + if (exepath != NULL) { + /* Strip executable file name, leaving path */ + *strrchr(exepath, '/') = '\0'; + } else { + LOG_WARNING("Could not determine executable path, using configured BINDIR."); + LOG_DEBUG("BINDIR = %s", BINDIR); +#ifdef HAVE_REALPATH + exepath = realpath(BINDIR, NULL); +#else + exepath = strdup(BINDIR); +#endif } - char *end_of_prefix = find_suffix(strExePath, BINDIR); - if (end_of_prefix != NULL) - *end_of_prefix = '\0'; + return exepath; +} - run_prefix = strExePath; -#else - char strElfPath[PATH_MAX]; - char strElfRealPath[PATH_MAX]; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-result" - if (strchr(argv0, '/') == NULL) { - /* If the name has no path separators, use default logic */ - run_prefix = ""; - } else { - if (*argv0 != '/') { - /* Relative path must be appended to current directory */ - getcwd(strElfPath, PATH_MAX); - if (strElfPath[strlen(strElfPath)-1] != '/') { - strcat(strElfPath, "/"); - } - strcat(strElfPath, argv0); - } else { - /* Absolute folder is used as is */ - strncpy(strElfPath, argv0, PATH_MAX); - } - /* Convert to canonical path */ - realpath(strElfPath, strElfRealPath); -#pragma GCC diagnostic pop - - /* Strip executable file name, leaving path (there always is a '/' */ - *strrchr(strElfRealPath, '/') = '\0'; - - char *end_of_prefix = find_suffix(strElfRealPath, BINDIR); - if (end_of_prefix != NULL) - *end_of_prefix = '\0'; - - run_prefix = strElfRealPath; - } -#endif +static char *find_relative_path(const char *from, const char *to) +{ + size_t i; + + /* Skip common /-separated parts of from and to */ + i = 0; + for (size_t n = 0; from[n] == to[n]; n++) { + if (from[n] == '\0') { + i = n; + break; + } + if (from[n] == '/') + i = n + 1; + } + from += i; + to += i; + + /* Count number of /-separated non-empty parts of from */ + i = 0; + while (from[0] != '\0') { + if (from[0] != '/') + i++; + char *next = strchr(from, '/'); + if (next == NULL) + break; + from = next + 1; + } + + /* Prepend that number of ../ in front of to */ + char *relpath = malloc(i * 3 + strlen(to) + 1); + relpath[0] = '\0'; + for (size_t n = 0; n < i; n++) + strcat(relpath, "../"); + strcat(relpath, to); + + return relpath; +} + +static void add_default_dirs(void) +{ + char *path; + char *exepath = find_exe_path(); + char *bin2data = find_relative_path(BINDIR, PKGDATADIR); LOG_DEBUG("bindir=%s", BINDIR); LOG_DEBUG("pkgdatadir=%s", PKGDATADIR); - LOG_DEBUG("run_prefix=%s", run_prefix); + LOG_DEBUG("exepath=%s", exepath); + LOG_DEBUG("bin2data=%s", bin2data); /* * The directory containing OpenOCD-supplied scripts should be @@ -163,17 +215,20 @@ static void add_default_dirs(char* argv0) } #endif - path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site"); + path = alloc_printf("%s/%s/%s", exepath, bin2data, "site"); if (path) { add_script_search_dir(path); free(path); } - path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts"); + path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts"); if (path) { add_script_search_dir(path); free(path); } + + free(exepath); + free(bin2data); } int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) @@ -212,8 +267,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) case 'd': /* --debug | -d */ { char *command = alloc_printf("debug_level %s", optarg ? optarg : "3"); - command_run_line(cmd_ctx, command); + int retval = command_run_line(cmd_ctx, command); free(command); + if (retval != ERROR_OK) + return retval; break; } case 'l': /* --log_output | -l */ @@ -234,16 +291,26 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; " "log_output openocd.log\"' instead."); break; + default: /* '?' */ + /* getopt will emit an error message, all we have to do is bail. */ + return ERROR_FAIL; } } + if (optind < argc) { + /* Catch extra arguments on the command line. */ + LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]); + return ERROR_FAIL; + } + if (help_flag) { LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--file | -f\tuse configuration file \n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); - LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); + LOG_OUTPUT("--debug | -d\tset debug level to 3\n"); + LOG_OUTPUT(" | -d\tset debug level to \n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file \n"); LOG_OUTPUT("--command | -c\trun \n"); exit(-1); @@ -258,7 +325,7 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) /* paths specified on the command line take precedence over these * built-in paths */ - add_default_dirs(argv[0]); + add_default_dirs(); return ERROR_OK; } diff --git a/src/helper/replacements.c b/src/helper/replacements.c index bb23dd92b..b4bb94f06 100644 --- a/src/helper/replacements.c +++ b/src/helper/replacements.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* DANGER!!!! These must be defined *BEFORE* replacements.h and the malloc() macro!!!! */ diff --git a/src/helper/replacements.h b/src/helper/replacements.h index 277660228..1e2fbf20f 100644 --- a/src/helper/replacements.h +++ b/src/helper/replacements.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef REPLACEMENTS_H -#define REPLACEMENTS_H +#ifndef OPENOCD_HELPER_REPLACEMENTS_H +#define OPENOCD_HELPER_REPLACEMENTS_H /* MIN,MAX macros */ #ifndef MIN @@ -282,4 +280,4 @@ typedef struct { const char *libusb_error_name(int error_code); #endif /* defined HAVE_LIBUSB1 && !defined HAVE_LIBUSB_ERROR_NAME */ -#endif /* REPLACEMENTS_H */ +#endif /* OPENOCD_HELPER_REPLACEMENTS_H */ diff --git a/src/helper/system.h b/src/helper/system.h index a6dfd7ec1..97b3443be 100644 --- a/src/helper/system.h +++ b/src/helper/system.h @@ -15,13 +15,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef SYSTEM_H -#define SYSTEM_H +#ifndef OPENOCD_HELPER_SYSTEM_H +#define OPENOCD_HELPER_SYSTEM_H /* standard C library header files */ #include @@ -88,4 +86,4 @@ #define false 0 #endif -#endif /* SYSTEM_H */ +#endif /* OPENOCD_HELPER_SYSTEM_H */ diff --git a/src/helper/time_support.c b/src/helper/time_support.c index c5978b423..8337e73ba 100644 --- a/src/helper/time_support.c +++ b/src/helper/time_support.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -78,14 +76,14 @@ int duration_measure(struct duration *duration) return retval; } -float duration_elapsed(struct duration *duration) +float duration_elapsed(const struct duration *duration) { float t = duration->elapsed.tv_sec; t += (float)duration->elapsed.tv_usec / 1000000.0; return t; } -float duration_kbps(struct duration *duration, size_t count) +float duration_kbps(const struct duration *duration, size_t count) { return count / (1024.0 * duration_elapsed(duration)); } diff --git a/src/helper/time_support.h b/src/helper/time_support.h index ab839826b..58c8c48bb 100644 --- a/src/helper/time_support.h +++ b/src/helper/time_support.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TIME_SUPPORT_H -#define TIME_SUPPORT_H +#ifndef OPENOCD_HELPER_TIME_SUPPORT_H +#define OPENOCD_HELPER_TIME_SUPPORT_H #ifdef TIME_WITH_SYS_TIME # include @@ -55,8 +53,8 @@ int duration_start(struct duration *duration); int duration_measure(struct duration *duration); /** @returns Elapsed time in seconds. */ -float duration_elapsed(struct duration *duration); +float duration_elapsed(const struct duration *duration); /** @returns KB/sec for the elapsed @a duration and @a count bytes. */ -float duration_kbps(struct duration *duration, size_t count); +float duration_kbps(const struct duration *duration, size_t count); -#endif /* TIME_SUPPORT_H */ +#endif /* OPENOCD_HELPER_TIME_SUPPORT_H */ diff --git a/src/helper/time_support_common.c b/src/helper/time_support_common.c index fd564e337..b733c270e 100644 --- a/src/helper/time_support_common.c +++ b/src/helper/time_support_common.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -33,7 +31,7 @@ /* simple and low overhead fetching of ms counter. Use only * the difference between ms counters returned from this fn. */ -int64_t timeval_ms() +int64_t timeval_ms(void) { struct timeval now; int retval = gettimeofday(&now, NULL); diff --git a/src/helper/types.h b/src/helper/types.h index 3f0724c3a..58c9e7245 100644 --- a/src/helper/types.h +++ b/src/helper/types.h @@ -16,12 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TYPES_H -#define TYPES_H + +#ifndef OPENOCD_HELPER_TYPES_H +#define OPENOCD_HELPER_TYPES_H #include #ifdef HAVE_SYS_TYPES_H @@ -297,14 +296,21 @@ static inline int parity_u32(uint32_t x) */ #if !defined(_STDINT_H) -#define PRIx32 "x" #define PRId32 "d" -#define SCNx32 "x" #define PRIi32 "i" +#define PRIo32 "o" #define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define SCNx32 "x" #define PRId8 PRId32 #define SCNx64 "llx" +#define PRId64 "lld" +#define PRIi64 "lli" +#define PRIo64 "llo" +#define PRIu64 "llu" #define PRIx64 "llx" +#define PRIX64 "llX" typedef CYG_ADDRWORD intptr_t; typedef int64_t intmax_t; @@ -338,4 +344,23 @@ typedef uint64_t uintmax_t; #endif -#endif /* TYPES_H */ +#if BUILD_TARGET64 +typedef uint64_t target_addr_t; +#define TARGET_ADDR_MAX UINT64_MAX +#define TARGET_PRIdADDR PRId64 +#define TARGET_PRIuADDR PRIu64 +#define TARGET_PRIoADDR PRIo64 +#define TARGET_PRIxADDR PRIx64 +#define TARGET_PRIXADDR PRIX64 +#else +typedef uint32_t target_addr_t; +#define TARGET_ADDR_MAX UINT32_MAX +#define TARGET_PRIdADDR PRId32 +#define TARGET_PRIuADDR PRIu32 +#define TARGET_PRIoADDR PRIo32 +#define TARGET_PRIxADDR PRIx32 +#define TARGET_PRIXADDR PRIX32 +#endif +#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR + +#endif /* OPENOCD_HELPER_TYPES_H */ diff --git a/src/helper/util.c b/src/helper/util.c index 55b92a755..56baf95d1 100644 --- a/src/helper/util.c +++ b/src/helper/util.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* this file contains various functionality useful to standalone systems */ diff --git a/src/helper/util.h b/src/helper/util.h index 48db725cf..c9a11ddac 100644 --- a/src/helper/util.h +++ b/src/helper/util.h @@ -12,16 +12,14 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef HELPER_UTILS_H -#define HELPER_UTILS_H +#ifndef OPENOCD_HELPER_UTIL_H +#define OPENOCD_HELPER_UTIL_H struct command_context; int util_init(struct command_context *cmd_ctx); -#endif /* HELPER_UTILS_H */ +#endif /* OPENOCD_HELPER_UTIL_H */ diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index db3e6ff2a..50ee263d0 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -1,86 +1,72 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libjtag.la -METASOURCES = AUTO -noinst_LTLIBRARIES = libjtag.la +JTAG_SRCS = +%C%_libjtag_la_LIBADD = -SUBDIRS = -DRIVERFILES = -libjtag_la_LIBADD = - -CLEANFILES = - -BUILT_SOURCES = - -BUILT_SOURCES += minidriver_imp.h -CLEANFILES += minidriver_imp.h +BUILT_SOURCES += %D%/minidriver_imp.h +CLEANFILES += %D%/minidriver_imp.h if MINIDRIVER if ZY1000 -DRIVERFILES += zy1000/zy1000.c -JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 +JTAG_SRCS += %D%/zy1000/zy1000.c +JTAG_MINIDRIVER_DIR = %D%/zy1000 endif if MINIDRIVER_DUMMY -DRIVERFILES += minidummy/minidummy.c commands.c -JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy +JTAG_SRCS += %D%/minidummy/minidummy.c %D%/commands.c +JTAG_MINIDRIVER_DIR = %D%/minidummy endif -MINIDRIVER_IMP_DIR = $(srcdir)/minidriver +MINIDRIVER_IMP_DIR = %D%/minidriver -jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h +%D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h cp $< $@ -BUILT_SOURCES += jtag_minidriver.h +BUILT_SOURCES += %D%/jtag_minidriver.h -CLEANFILES += jtag_minidriver.h +CLEANFILES += %D%/jtag_minidriver.h else -MINIDRIVER_IMP_DIR = $(srcdir)/drivers -DRIVERFILES += commands.c +MINIDRIVER_IMP_DIR = %D%/drivers +JTAG_SRCS += %D%/commands.c if HLADAPTER -SUBDIRS += hla -libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la +include %D%/hla/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la endif if AICE -SUBDIRS += aice -libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la +include %D%/aice/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la endif -SUBDIRS += drivers -libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la - +include %D%/drivers/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la endif - # endif // MINIDRIVER -minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h +%D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h cp $< $@ -libjtag_la_SOURCES = \ - adapter.c \ - core.c \ - interface.c \ - interfaces.c \ - tcl.c \ - $(DRIVERFILES) - -noinst_HEADERS = \ - commands.h \ - driver.h \ - interface.h \ - interfaces.h \ - minidriver.h \ - jtag.h \ - minidriver/minidriver_imp.h \ - minidummy/jtag_minidriver.h \ - swd.h \ - tcl.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +%C%_libjtag_la_SOURCES = \ + %D%/adapter.c \ + %D%/core.c \ + %D%/interface.c \ + %D%/interfaces.c \ + %D%/tcl.c \ + %D%/commands.h \ + %D%/driver.h \ + %D%/interface.h \ + %D%/interfaces.h \ + %D%/minidriver.h \ + %D%/jtag.h \ + %D%/minidriver/minidriver_imp.h \ + %D%/minidummy/jtag_minidriver.h \ + %D%/swd.h \ + %D%/tcl.h \ + $(JTAG_SRCS) + +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c index 2f5f6b436..5953de7e5 100644 --- a/src/jtag/adapter.c +++ b/src/jtag/adapter.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/aice/Makefile.am b/src/jtag/aice/Makefile.am index 7b9469d86..97e38258a 100644 --- a/src/jtag/aice/Makefile.am +++ b/src/jtag/aice/Makefile.am @@ -1,27 +1,14 @@ -include $(top_srcdir)/common.mk - -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) - -noinst_LTLIBRARIES = libocdaice.la - -libocdaice_la_SOURCES = \ - $(AICEFILES) - -AICEFILES = - -if AICE -AICEFILES += aice_transport.c -AICEFILES += aice_interface.c -AICEFILES += aice_port.c -AICEFILES += aice_usb.c -AICEFILES += aice_pipe.c -endif - -noinst_HEADERS = \ - aice_transport.h \ - aice_interface.h \ - aice_port.h \ - aice_usb.h \ - aice_pipe.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdaice.la + +%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) +%C%_libocdaice_la_SOURCES = \ + %D%/aice_transport.c \ + %D%/aice_interface.c \ + %D%/aice_port.c \ + %D%/aice_usb.c \ + %D%/aice_pipe.c \ + %D%/aice_transport.h \ + %D%/aice_interface.h \ + %D%/aice_port.h \ + %D%/aice_usb.h \ + %D%/aice_pipe.h diff --git a/src/jtag/aice/aice_interface.c b/src/jtag/aice/aice_interface.c index 363b208a3..20f1f07f9 100644 --- a/src/jtag/aice/aice_interface.c +++ b/src/jtag/aice/aice_interface.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/aice/aice_interface.h b/src/jtag/aice/aice_interface.h index ddb6ad419..0e3f10836 100644 --- a/src/jtag/aice/aice_interface.h +++ b/src/jtag/aice/aice_interface.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __AICE_INTERFACE_H__ -#define __AICE_INTERFACE_H__ + +#ifndef OPENOCD_JTAG_AICE_AICE_INTERFACE_H +#define OPENOCD_JTAG_AICE_AICE_INTERFACE_H struct aice_interface_param_s { /** */ @@ -33,4 +32,4 @@ struct aice_interface_param_s { int aice_init_targets(void); -#endif +#endif /* OPENOCD_JTAG_AICE_AICE_INTERFACE_H */ diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c index 3180ad008..bdc8c090a 100644 --- a/src/jtag/aice/aice_pipe.c +++ b/src/jtag/aice/aice_pipe.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -176,7 +174,7 @@ static int aice_pipe_write(const void *buffer, int count) static int aice_pipe_read(void *buffer, int count) { int n; - long long then, cur; + int64_t then, cur; then = timeval_ms(); @@ -788,8 +786,8 @@ static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_sel return ERROR_FAIL; } -static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; diff --git a/src/jtag/aice/aice_pipe.h b/src/jtag/aice/aice_pipe.h index 48b0c4912..467ad0ad5 100644 --- a/src/jtag/aice/aice_pipe.h +++ b/src/jtag/aice/aice_pipe.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _AICE_PIPE_H_ -#define _AICE_PIPE_H_ + +#ifndef OPENOCD_JTAG_AICE_AICE_PIPE_H +#define OPENOCD_JTAG_AICE_AICE_PIPE_H #include @@ -29,4 +28,4 @@ extern struct aice_port_api_s aice_pipe; -#endif +#endif /* OPENOCD_JTAG_AICE_AICE_PIPE_H */ diff --git a/src/jtag/aice/aice_port.c b/src/jtag/aice/aice_port.c index b61275c8b..2fa346ca0 100644 --- a/src/jtag/aice/aice_port.c +++ b/src/jtag/aice/aice_port.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h index d29e9e142..d3d6a1a2c 100644 --- a/src/jtag/aice/aice_port.h +++ b/src/jtag/aice/aice_port.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _AICE_PORT_H_ -#define _AICE_PORT_H_ + +#ifndef OPENOCD_JTAG_AICE_AICE_PORT_H +#define OPENOCD_JTAG_AICE_AICE_PORT_H #include @@ -181,7 +180,7 @@ struct aice_port_api_s { int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select); /** */ - int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address); + int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address); /** */ int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address); @@ -235,4 +234,4 @@ struct aice_port { /** */ const struct aice_port *aice_port_get_list(void); -#endif +#endif /* OPENOCD_JTAG_AICE_AICE_PORT_H */ diff --git a/src/jtag/aice/aice_transport.c b/src/jtag/aice/aice_transport.c index f3012bb22..9f079468c 100644 --- a/src/jtag/aice/aice_transport.c +++ b/src/jtag/aice/aice_transport.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -90,11 +88,13 @@ static int jim_aice_newtap_cmd(Jim_GetOptInfo *goi) free(pTap); return JIM_ERR; } - Jim_GetOpt_String(goi, &cp, NULL); - pTap->chip = strdup(cp); - Jim_GetOpt_String(goi, &cp, NULL); - pTap->tapname = strdup(cp); + const char *tmp; + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->chip = strdup(tmp); + + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->tapname = strdup(tmp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; diff --git a/src/jtag/aice/aice_transport.h b/src/jtag/aice/aice_transport.h index e93d13127..3af8bc2ee 100644 --- a/src/jtag/aice/aice_transport.h +++ b/src/jtag/aice/aice_transport.h @@ -13,14 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _AICE_TRANSPORT_ -#define _AICE_TRANSPORT_ +#ifndef OPENOCD_JTAG_AICE_AICE_TRANSPORT_H +#define OPENOCD_JTAG_AICE_AICE_TRANSPORT_H extern const char *aice_transports[]; -#endif +#endif /* OPENOCD_JTAG_AICE_AICE_TRANSPORT_H */ diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 50b3b9a22..50468f375 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1858,7 +1856,7 @@ static int aice_check_dbger(uint32_t coreid, uint32_t expect_status) if ((i % 30) == 0) keep_alive(); - long long then = 0; + int64_t then = 0; if (i == aice_count_to_check_dbger) then = timeval_ms(); if (i >= aice_count_to_check_dbger) { @@ -2137,10 +2135,16 @@ static int aice_usb_open(struct aice_port_param_s *param) /* usb_set_configuration required under win32 */ jtag_libusb_set_configuration(devh, 0); + jtag_libusb_claim_interface(devh, 0); unsigned int aice_read_ep; unsigned int aice_write_ep; - jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); +#ifdef HAVE_LIBUSB1 + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK); +#else + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK); +#endif + LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep); aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_write_ep = aice_write_ep; @@ -2999,7 +3003,7 @@ static int aice_usb_step(uint32_t coreid) if (AICE_TARGET_HALTED == state) break; - long long then = 0; + int64_t then = 0; if (i == 30) then = timeval_ms(); @@ -3426,10 +3430,10 @@ static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_sele return ERROR_OK; } -static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { - LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address); + LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address); uint32_t instructions[4]; uint32_t probe_result; diff --git a/src/jtag/aice/aice_usb.h b/src/jtag/aice/aice_usb.h index adb027eaa..2911ae56b 100644 --- a/src/jtag/aice/aice_usb.h +++ b/src/jtag/aice/aice_usb.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __AICE_USB_H__ -#define __AICE_USB_H__ + +#ifndef OPENOCD_JTAG_AICE_AICE_USB_H +#define OPENOCD_JTAG_AICE_AICE_USB_H #include "aice_port.h" @@ -130,4 +129,4 @@ extern struct aice_port_api_s aice_usb_api; int aice_read_ctrl(uint32_t address, uint32_t *data); int aice_write_ctrl(uint32_t address, uint32_t data); -#endif +#endif /* OPENOCD_JTAG_AICE_AICE_USB_H */ diff --git a/src/jtag/commands.c b/src/jtag/commands.c index 750ebab0d..ed40755b7 100644 --- a/src/jtag/commands.c +++ b/src/jtag/commands.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/commands.h b/src/jtag/commands.h index 06ec24837..947c94725 100644 --- a/src/jtag/commands.h +++ b/src/jtag/commands.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_COMMANDS_H -#define JTAG_COMMANDS_H +#ifndef OPENOCD_JTAG_COMMANDS_H +#define OPENOCD_JTAG_COMMANDS_H /** * The inferred type of a scan_command_s structure, indicating whether @@ -175,4 +173,4 @@ int jtag_scan_size(const struct scan_command *cmd); int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd); int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer); -#endif /* JTAG_COMMANDS_H */ +#endif /* OPENOCD_JTAG_COMMANDS_H */ diff --git a/src/jtag/core.c b/src/jtag/core.c index 74c2731c2..5e297b8e9 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -36,6 +34,7 @@ #include "swd.h" #include "interface.h" #include +#include #ifdef HAVE_STRINGS_H #include @@ -837,7 +836,124 @@ int default_interface_jtag_execute_queue(void) return ERROR_FAIL; } +#if BUILD_RISCV == 1 + int result = jtag->execute_queue(); + +#if 0 + // TODO: I like these better than some of the other JTAG debug statements, + // but having both is silly. + struct jtag_command *cmd = jtag_command_queue; + while (debug_level >= LOG_LVL_DEBUG && cmd) { + switch (cmd->type) { + case JTAG_SCAN: +#if 0 + LOG_DEBUG("JTAG %s SCAN to %s", + cmd->cmd.scan->ir_scan ? "IR" : "DR", + tap_state_name(cmd->cmd.scan->end_state)); + for (int i = 0; i < cmd->cmd.scan->num_fields; i++) { + struct scan_field *field = cmd->cmd.scan->fields + i; + if (field->out_value) { + char *str = buf_to_str(field->out_value, field->num_bits, 16); + LOG_DEBUG(" %db out: %s", field->num_bits, str); + free(str); + } + if (field->in_value) { + char *str = buf_to_str(field->in_value, field->num_bits, 16); + LOG_DEBUG(" %db in: %s", field->num_bits, str); + free(str); + } + if (field->check_value) { + char *str = buf_to_str(field->check_value, field->num_bits, 16); + LOG_DEBUG(" %db check: %s", field->num_bits, str); + free(str); + } + if (field->check_mask) { + char *str = buf_to_str(field->check_mask, field->num_bits, 16); + LOG_DEBUG(" %db mask: %s", field->num_bits, str); + free(str); + } + } +#endif + { + uint8_t *buf = NULL; + int scan_bits = jtag_build_buffer(cmd->cmd.scan, &buf); + char *str_out = buf_to_str(buf, scan_bits, 16); + free(buf); + LOG_DEBUG("vvv jtag_scan(%d, %d, %d'h%s, %d); // %s", + cmd->cmd.scan->ir_scan, + scan_bits, + scan_bits, str_out, + cmd->cmd.scan->end_state, tap_state_name(cmd->cmd.scan->end_state)); + free(str_out); + + struct scan_field *last_field = cmd->cmd.scan->fields + cmd->cmd.scan->num_fields - 1; + if (last_field->in_value) { + char *str_in = buf_to_str(last_field->in_value, last_field->num_bits, 16); + LOG_DEBUG("vvv jtag_check_tdo(%d, %d'h%s);", + last_field->num_bits, + last_field->num_bits, str_in); + free(str_in); + } + } + break; + case JTAG_TLR_RESET: +#if 0 + LOG_DEBUG("JTAG TLR RESET to %s", + tap_state_name(cmd->cmd.statemove->end_state)); +#endif + LOG_DEBUG("vvv jtag_tlr_reset(%d); // %s", + cmd->cmd.statemove->end_state, + tap_state_name(cmd->cmd.statemove->end_state)); + break; + case JTAG_RUNTEST: +#if 0 + LOG_DEBUG("JTAG RUNTEST %d cycles to %s", + cmd->cmd.runtest->num_cycles, + tap_state_name(cmd->cmd.runtest->end_state)); +#endif + LOG_DEBUG("vvv jtag_runtest(%d, %d); // %s", + cmd->cmd.runtest->num_cycles, + cmd->cmd.runtest->end_state, + tap_state_name(cmd->cmd.runtest->end_state)); + break; + case JTAG_RESET: + { +#if 0 + const char *reset_str[3] = { + "leave", "deassert", "assert" + }; + LOG_DEBUG("JTAG RESET %s TRST, %s SRST", + reset_str[cmd->cmd.reset->trst + 1], + reset_str[cmd->cmd.reset->srst + 1]); +#endif + LOG_DEBUG("vvv jtag_reset(%d, %d);", + cmd->cmd.reset->trst, cmd->cmd.reset->srst); + } + break; + case JTAG_PATHMOVE: + LOG_DEBUG("JTAG PATHMOVE (TODO)"); + break; + case JTAG_SLEEP: + LOG_DEBUG("JTAG SLEEP (TODO)"); + break; + case JTAG_STABLECLOCKS: + LOG_DEBUG("JTAG STABLECLOCKS (TODO)"); + break; + case JTAG_TMS: + LOG_DEBUG("JTAG STABLECLOCKS (TODO)"); + break; + default: + LOG_ERROR("Unknown JTAG command: %d", cmd->type); + break; + } + cmd = cmd->next; + } +#endif + + return result; +#else return jtag->execute_queue(); +#endif } void jtag_execute_queue_noclear(void) @@ -894,6 +1010,8 @@ void jtag_sleep(uint32_t us) #define JTAG_MAX_AUTO_TAPS 20 +#define EXTRACT_JEP106_BANK(X) (((X) & 0xf00) >> 8) +#define EXTRACT_JEP106_ID(X) (((X) & 0xfe) >> 1) #define EXTRACT_MFG(X) (((X) & 0xffe) >> 1) #define EXTRACT_PART(X) (((X) & 0xffff000) >> 12) #define EXTRACT_VER(X) (((X) & 0xf0000000) >> 28) @@ -957,10 +1075,11 @@ static void jtag_examine_chain_display(enum log_levels level, const char *msg, { log_printf_lf(level, __FILE__, __LINE__, __func__, "JTAG tap: %s %16.16s: 0x%08x " - "(mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)", + "(mfg: 0x%3.3x (%s), part: 0x%4.4x, ver: 0x%1.1x)", name, msg, (unsigned int)idcode, (unsigned int)EXTRACT_MFG(idcode), + jep106_manufacturer(EXTRACT_JEP106_BANK(idcode), EXTRACT_JEP106_ID(idcode)), (unsigned int)EXTRACT_PART(idcode), (unsigned int)EXTRACT_VER(idcode)); } @@ -1105,7 +1224,12 @@ static int jtag_examine_chain(void) if ((idcode & 1) == 0) { /* Zero for LSB indicates a device in bypass */ +#if BUILD_RISCV == 1 + LOG_INFO("TAP %s does not have valid IDCODE (idcode=0x%x)", + tap->dotted_name, idcode); +#else LOG_INFO("TAP %s does not have IDCODE", tap->dotted_name); +#endif tap->hasidcode = false; tap->idcode = 0; @@ -1715,11 +1839,11 @@ void jtag_set_reset_config(enum reset_types type) int jtag_get_trst(void) { - return jtag_trst; + return jtag_trst == 1; } int jtag_get_srst(void) { - return jtag_srst; + return jtag_srst == 1; } void jtag_set_nsrst_delay(unsigned delay) diff --git a/src/jtag/driver.h b/src/jtag/driver.h index 5a7b4edf4..ae00414c4 100644 --- a/src/jtag/driver.h +++ b/src/jtag/driver.h @@ -13,16 +13,14 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_DRIVER_H -#define JTAG_DRIVER_H +#ifndef OPENOCD_JTAG_DRIVER_H +#define OPENOCD_JTAG_DRIVER_H struct command_context; int interface_register_commands(struct command_context *ctx); -#endif /* JTAG_DRIVER_H */ +#endif /* OPENOCD_JTAG_DRIVER_H */ diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index bbb15dd1e..7c79cc8b9 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -1,176 +1,182 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la +%C%_libocdjtagdrivers_la_LIBADD = -noinst_LTLIBRARIES = libocdjtagdrivers.la -libocdjtagdrivers_la_LIBADD = +%C%_libocdjtagdrivers_la_SOURCES = \ + $(DRIVERFILES) \ + $(DRIVERHEADERS) -libocdjtagdrivers_la_SOURCES = \ - $(DRIVERFILES) +%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) -libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ - $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS) +ULINK_FIRMWARE = %D%/OpenULINK -ULINK_FIRMWARE = $(srcdir)/OpenULINK - -EXTRA_DIST = $(ULINK_FIRMWARE) \ - usb_blaster/README.CheapClone \ - Makefile.rlink \ - rlink_call.m4 \ - rlink_init.m4 +EXTRA_DIST += $(ULINK_FIRMWARE) \ + %D%/usb_blaster/README.CheapClone \ + %D%/Makefile.rlink \ + %D%/rlink_call.m4 \ + %D%/rlink_init.m4 DRIVERFILES = -SUBDIRS= -if JLINK -if INTERNAL_LIBJAYLINK -SUBDIRS += libjaylink +# Standard Driver: common files +DRIVERFILES += %D%/driver.c -libjaylink_internal_la_SOURCES = jlink.c -libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la -libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \ - -I$(srcdir)/libjaylink $(AM_CPPFLAGS) +if USE_LIBUSB1 +DRIVERFILES += %D%/libusb1_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS) +endif -noinst_LTLIBRARIES += libjaylink_internal.la -libocdjtagdrivers_la_LIBADD += libjaylink_internal.la -else -DRIVERFILES += jlink.c +if USE_LIBUSB0 +DRIVERFILES += %D%/usb_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS) +if !USE_LIBUSB1 +DRIVERFILES += %D%/libusb0_common.c endif endif -# Standard Driver: common files -DRIVERFILES += driver.c +if USE_LIBFTDI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS) +endif -if USE_LIBUSB1 -DRIVERFILES += libusb1_common.c +if USE_HIDAPI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(HIDAPI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(HIDAPI_LIBS) endif -if USE_LIBUSB0 -DRIVERFILES += usb_common.c -if !USE_LIBUSB1 -DRIVERFILES += libusb0_common.c +if USE_LIBJAYLINK +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBJAYLINK_LIBS) +endif + +if JLINK +DRIVERFILES += %D%/jlink.c +if INTERNAL_LIBJAYLINK +SUBDIRS += %D%/libjaylink +DIST_SUBDIRS += %D%/libjaylink + +%C%_libocdjtagdrivers_la_LIBADD += %D%/libjaylink/libjaylink/libjaylink.la +%C%_libocdjtagdrivers_la_CPPFLAGS += -I$(builddir)/%D%/libjaylink/libjaylink -I$(srcdir)/%D%/libjaylink endif endif if BITBANG -DRIVERFILES += bitbang.c +DRIVERFILES += %D%/bitbang.c endif if PARPORT -DRIVERFILES += parport.c +DRIVERFILES += %D%/parport.c endif if DUMMY -DRIVERFILES += dummy.c -endif -if FT2232_DRIVER -DRIVERFILES += ft2232.c +DRIVERFILES += %D%/dummy.c endif if FTDI -DRIVERFILES += ftdi.c mpsse.c +DRIVERFILES += %D%/ftdi.c %D%/mpsse.c endif if W_JTAG_SJ -DRIVERFILES += w_jtag_sj.c w_jtag_sj_io.c +DRIVERFILES += %D%/w_jtag_sj.c %D%/w_jtag_sj_io.c endif if JTAG_VPI -DRIVERFILES += jtag_vpi.c +DRIVERFILES += %D%/jtag_vpi.c endif if USB_BLASTER_DRIVER -SUBDIRS += usb_blaster -libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la +%C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la +include %D%/usb_blaster/Makefile.am endif if AMTJTAGACCEL -DRIVERFILES += amt_jtagaccel.c +DRIVERFILES += %D%/amt_jtagaccel.c endif if EP93XX -DRIVERFILES += ep93xx.c +DRIVERFILES += %D%/ep93xx.c endif if AT91RM9200 -DRIVERFILES += at91rm9200.c +DRIVERFILES += %D%/at91rm9200.c endif if GW16012 -DRIVERFILES += gw16012.c +DRIVERFILES += %D%/gw16012.c endif if BITQ -DRIVERFILES += bitq.c +DRIVERFILES += %D%/bitq.c endif -if PRESTO_DRIVER -DRIVERFILES += presto.c +if PRESTO +DRIVERFILES += %D%/presto.c endif if USBPROG -DRIVERFILES += usbprog.c +DRIVERFILES += %D%/usbprog.c endif if RLINK -DRIVERFILES += rlink.c rlink_speed_table.c +DRIVERFILES += %D%/rlink.c %D%/rlink_speed_table.c endif if ULINK -DRIVERFILES += ulink.c +DRIVERFILES += %D%/ulink.c ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex +%C%_libocdjtagdrivers_la_LIBADD += -lm endif if VSLLINK -DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c -DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c -DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c -DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c -DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c -DRIVERFILES += versaloon/versaloon.c -DRIVERFILES += vsllink.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoswd.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtopwr.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoxxx.c +DRIVERFILES += %D%/versaloon/versaloon.c +DRIVERFILES += %D%/vsllink.c endif if ARMJTAGEW -DRIVERFILES += arm-jtag-ew.c +DRIVERFILES += %D%/arm-jtag-ew.c endif if BUSPIRATE -DRIVERFILES += buspirate.c +DRIVERFILES += %D%/buspirate.c endif if REMOTE_BITBANG -DRIVERFILES += remote_bitbang.c +DRIVERFILES += %D%/remote_bitbang.c endif if HLADAPTER -DRIVERFILES += stlink_usb.c -DRIVERFILES += ti_icdi_usb.c +DRIVERFILES += %D%/stlink_usb.c +DRIVERFILES += %D%/ti_icdi_usb.c endif if OSBDM -DRIVERFILES += osbdm.c +DRIVERFILES += %D%/osbdm.c endif if OPENDOUS -DRIVERFILES += opendous.c +DRIVERFILES += %D%/opendous.c endif if SYSFSGPIO -DRIVERFILES += sysfsgpio.c +DRIVERFILES += %D%/sysfsgpio.c endif if BCM2835GPIO -DRIVERFILES += bcm2835gpio.c +DRIVERFILES += %D%/bcm2835gpio.c endif - if OPENJTAG -DRIVERFILES += openjtag.c +DRIVERFILES += %D%/openjtag.c endif - if CMSIS_DAP -DRIVERFILES += cmsis_dap_usb.c -endif - -noinst_HEADERS = \ - bitbang.h \ - bitq.h \ - ftd2xx_common.h \ - libusb0_common.h \ - libusb1_common.h \ - libusb_common.h \ - minidriver_imp.h \ - mpsse.h \ - rlink.h \ - rlink_dtc_cmd.h \ - rlink_ep1_cmd.h \ - rlink_st7.h \ - usb_common.h \ - versaloon/usbtoxxx/usbtoxxx.h \ - versaloon/usbtoxxx/usbtoxxx_internal.h \ - versaloon/versaloon.h \ - versaloon/versaloon_include.h \ - versaloon/versaloon_internal.h - -DIST_SUBDIRS = usb_blaster - -if INTERNAL_LIBJAYLINK -DIST_SUBDIRS += libjaylink -endif +DRIVERFILES += %D%/cmsis_dap_usb.c +endif +if IMX_GPIO +DRIVERFILES += %D%/imx_gpio.c +endif + +if KITPROG +DRIVERFILES += %D%/kitprog.c +endif + +DRIVERHEADERS = \ + %D%/bitbang.h \ + %D%/bitq.h \ + %D%/libusb0_common.h \ + %D%/libusb1_common.h \ + %D%/libusb_common.h \ + %D%/minidriver_imp.h \ + %D%/mpsse.h \ + %D%/rlink.h \ + %D%/rlink_dtc_cmd.h \ + %D%/rlink_ep1_cmd.h \ + %D%/rlink_st7.h \ + %D%/usb_common.h \ + %D%/versaloon/usbtoxxx/usbtoxxx.h \ + %D%/versaloon/usbtoxxx/usbtoxxx_internal.h \ + %D%/versaloon/versaloon.h \ + %D%/versaloon/versaloon_include.h \ + %D%/versaloon/versaloon_internal.h -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/jtag/drivers/Makefile.rlink b/src/jtag/drivers/Makefile.rlink index 6a7638e7a..6168332c8 100644 --- a/src/jtag/drivers/Makefile.rlink +++ b/src/jtag/drivers/Makefile.rlink @@ -13,9 +13,7 @@ #* GNU General Public License for more details. * #* * #* You should have received a copy of the GNU General Public License * -#* along with this program; if not, write to the * -#* Free Software Foundation, Inc., * -#* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +#* along with this program. If not, see . * #*************************************************************************** TOP = ../../.. diff --git a/src/jtag/drivers/OpenULINK/Makefile b/src/jtag/drivers/OpenULINK/Makefile index 8ef2d03f9..9f6acc660 100644 --- a/src/jtag/drivers/OpenULINK/Makefile +++ b/src/jtag/drivers/OpenULINK/Makefile @@ -13,9 +13,7 @@ # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # -# along with this program; if not, write to the # -# Free Software Foundation, Inc., # -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +# along with this program. If not, see . # ############################################################################ # Define the name of our tools. Some distributions (e. g. Fedora) prefix diff --git a/src/jtag/drivers/OpenULINK/include/common.h b/src/jtag/drivers/OpenULINK/include/common.h index b4f6df9ab..56222fe6c 100644 --- a/src/jtag/drivers/OpenULINK/include/common.h +++ b/src/jtag/drivers/OpenULINK/include/common.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __COMMON_H diff --git a/src/jtag/drivers/OpenULINK/include/delay.h b/src/jtag/drivers/OpenULINK/include/delay.h index 59fb49fa9..ed454be9b 100644 --- a/src/jtag/drivers/OpenULINK/include/delay.h +++ b/src/jtag/drivers/OpenULINK/include/delay.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __DELAY_H diff --git a/src/jtag/drivers/OpenULINK/include/io.h b/src/jtag/drivers/OpenULINK/include/io.h index 8077d325f..a4a8b8acd 100644 --- a/src/jtag/drivers/OpenULINK/include/io.h +++ b/src/jtag/drivers/OpenULINK/include/io.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __IO_H diff --git a/src/jtag/drivers/OpenULINK/include/jtag.h b/src/jtag/drivers/OpenULINK/include/jtag.h index ee2457e1b..fa492b9ed 100644 --- a/src/jtag/drivers/OpenULINK/include/jtag.h +++ b/src/jtag/drivers/OpenULINK/include/jtag.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __JTAG_H diff --git a/src/jtag/drivers/OpenULINK/include/main.h b/src/jtag/drivers/OpenULINK/include/main.h index 5f7418f6c..9e7dd5a86 100644 --- a/src/jtag/drivers/OpenULINK/include/main.h +++ b/src/jtag/drivers/OpenULINK/include/main.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __MAIN_H diff --git a/src/jtag/drivers/OpenULINK/include/msgtypes.h b/src/jtag/drivers/OpenULINK/include/msgtypes.h index 9dbbeddde..f761a845f 100644 --- a/src/jtag/drivers/OpenULINK/include/msgtypes.h +++ b/src/jtag/drivers/OpenULINK/include/msgtypes.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** diff --git a/src/jtag/drivers/OpenULINK/include/protocol.h b/src/jtag/drivers/OpenULINK/include/protocol.h index fbc1996d0..0b6a7d67d 100644 --- a/src/jtag/drivers/OpenULINK/include/protocol.h +++ b/src/jtag/drivers/OpenULINK/include/protocol.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __PROTOCOL_H diff --git a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h index 82f9451ef..4988367db 100644 --- a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h +++ b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef REG_EZUSB_H diff --git a/src/jtag/drivers/OpenULINK/include/usb.h b/src/jtag/drivers/OpenULINK/include/usb.h index 182b79042..9a261fed0 100644 --- a/src/jtag/drivers/OpenULINK/include/usb.h +++ b/src/jtag/drivers/OpenULINK/include/usb.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef __USB_H diff --git a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 index 8ddd6801b..f10ad484f 100644 --- a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 +++ b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 @@ -13,9 +13,7 @@ ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; -; along with this program; if not, write to the ; -; Free Software Foundation, Inc., ; -; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ; +; along with this program. If not, see . ; ;--------------------------------------------------------------------------; .module JUMPTABLE diff --git a/src/jtag/drivers/OpenULINK/src/delay.c b/src/jtag/drivers/OpenULINK/src/delay.c index 82569e295..326056768 100644 --- a/src/jtag/drivers/OpenULINK/src/delay.c +++ b/src/jtag/drivers/OpenULINK/src/delay.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #include "delay.h" diff --git a/src/jtag/drivers/OpenULINK/src/jtag.c b/src/jtag/drivers/OpenULINK/src/jtag.c index 9f45ea78e..413945566 100644 --- a/src/jtag/drivers/OpenULINK/src/jtag.c +++ b/src/jtag/drivers/OpenULINK/src/jtag.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #include "jtag.h" diff --git a/src/jtag/drivers/OpenULINK/src/main.c b/src/jtag/drivers/OpenULINK/src/main.c index e4865f8a9..f331c9ebf 100644 --- a/src/jtag/drivers/OpenULINK/src/main.c +++ b/src/jtag/drivers/OpenULINK/src/main.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #include "main.h" diff --git a/src/jtag/drivers/OpenULINK/src/protocol.c b/src/jtag/drivers/OpenULINK/src/protocol.c index 5f7f98428..901f52482 100644 --- a/src/jtag/drivers/OpenULINK/src/protocol.c +++ b/src/jtag/drivers/OpenULINK/src/protocol.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #include "protocol.h" diff --git a/src/jtag/drivers/OpenULINK/src/usb.c b/src/jtag/drivers/OpenULINK/src/usb.c index 98ae67f70..fb77f6482 100644 --- a/src/jtag/drivers/OpenULINK/src/usb.c +++ b/src/jtag/drivers/OpenULINK/src/usb.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** diff --git a/src/jtag/drivers/amt_jtagaccel.c b/src/jtag/drivers/amt_jtagaccel.c index 5aacead4b..57c0ce600 100644 --- a/src/jtag/drivers/amt_jtagaccel.c +++ b/src/jtag/drivers/amt_jtagaccel.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/arm-jtag-ew.c b/src/jtag/drivers/arm-jtag-ew.c index 4c4cc6de1..d9ea367ce 100644 --- a/src/jtag/drivers/arm-jtag-ew.c +++ b/src/jtag/drivers/arm-jtag-ew.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/at91rm9200.c b/src/jtag/drivers/at91rm9200.c index d7e11df24..8f65413a2 100644 --- a/src/jtag/drivers/at91rm9200.c +++ b/src/jtag/drivers/at91rm9200.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index e1cc56c24..a41caf073 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -470,8 +468,8 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } - /* set 16mA drive strength */ - pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7; + /* set 4mA drive strength, slew rate limited, hysteresis on */ + pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1; tdo_gpio_mode = MODE_GPIO(tdo_gpio); tdi_gpio_mode = MODE_GPIO(tdi_gpio); diff --git a/src/jtag/drivers/bitbang.c b/src/jtag/drivers/bitbang.c index 1a0fa1c9d..c9ec9c9d6 100644 --- a/src/jtag/drivers/bitbang.c +++ b/src/jtag/drivers/bitbang.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* 2014-12: Addition of the SWD protocol support is based on the initial work diff --git a/src/jtag/drivers/bitbang.h b/src/jtag/drivers/bitbang.h index 1bdb8f5fc..c5b44bfd5 100644 --- a/src/jtag/drivers/bitbang.h +++ b/src/jtag/drivers/bitbang.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef BITBANG_H -#define BITBANG_H +#ifndef OPENOCD_JTAG_DRIVERS_BITBANG_H +#define OPENOCD_JTAG_DRIVERS_BITBANG_H #include @@ -47,4 +45,4 @@ extern struct bitbang_interface *bitbang_interface; void bitbang_switch_to_swd(void); int bitbang_swd_switch_seq(enum swd_special_seq seq); -#endif /* BITBANG_H */ +#endif /* OPENOCD_JTAG_DRIVERS_BITBANG_H */ diff --git a/src/jtag/drivers/bitq.c b/src/jtag/drivers/bitq.c index 1d0ff09b6..66285f700 100644 --- a/src/jtag/drivers/bitq.c +++ b/src/jtag/drivers/bitq.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/bitq.h b/src/jtag/drivers/bitq.h index f54de951f..df6a08d44 100644 --- a/src/jtag/drivers/bitq.h +++ b/src/jtag/drivers/bitq.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef BITQ_H -#define BITQ_H +#ifndef OPENOCD_JTAG_DRIVERS_BITQ_H +#define OPENOCD_JTAG_DRIVERS_BITQ_H #include @@ -44,4 +42,4 @@ int bitq_execute_queue(void); void bitq_cleanup(void); -#endif /* BITQ_H */ +#endif /* OPENOCD_JTAG_DRIVERS_BITQ_H */ diff --git a/src/jtag/drivers/buspirate.c b/src/jtag/drivers/buspirate.c index 554d3e0ef..aa0d8cc3f 100644 --- a/src/jtag/drivers/buspirate.c +++ b/src/jtag/drivers/buspirate.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index ff8b8ffaf..86f796877 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -1,4 +1,10 @@ /*************************************************************************** + * Copyright (C) 2016 by Maksym Hilliaka * + * oter@frozen-team.com * + * * + * Copyright (C) 2016 by Phillip Pearson * + * pp@myelin.co.nz * + * * * Copyright (C) 2014 by Paul Fertser * * fercerpav@gmail.com * * * @@ -19,9 +25,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -114,6 +118,13 @@ static bool swd_mode; * Bit 7: nRESET */ +#define SWJ_PIN_TCK (1<<0) +#define SWJ_PIN_TMS (1<<1) +#define SWJ_PIN_TDI (1<<2) +#define SWJ_PIN_TDO (1<<3) +#define SWJ_PIN_TRST (1<<5) +#define SWJ_PIN_SRST (1<<7) + /* CMSIS-DAP SWD Commands */ #define CMD_DAP_SWD_CONFIGURE 0x13 @@ -122,6 +133,15 @@ static bool swd_mode; #define CMD_DAP_JTAG_CONFIGURE 0x15 #define CMD_DAP_JTAG_IDCODE 0x16 +/* CMSIS-DAP JTAG sequence info masks */ +/* Number of bits to clock through (0 means 64) */ +#define DAP_JTAG_SEQ_TCK 0x3F +/* TMS will be set during the sequence if this bit is set */ +#define DAP_JTAG_SEQ_TMS 0x40 +/* TDO output will be captured if this bit is set */ +#define DAP_JTAG_SEQ_TDO 0x80 + + /* CMSIS-DAP Transfer Commands */ #define CMD_DAP_TFER_CONFIGURE 0x04 #define CMD_DAP_TFER 0x05 @@ -158,9 +178,32 @@ struct pending_transfer_result { void *buffer; }; +struct pending_scan_result { + /** Offset in bytes in the CMD_DAP_JTAG_SEQ response buffer. */ + unsigned first; + /** Number of bits to read. */ + unsigned length; + /** Location to store the result */ + uint8_t *buffer; + /** Offset in the destination buffer */ + unsigned buffer_offset; +}; + static int pending_transfer_count, pending_queue_len; static struct pending_transfer_result *pending_transfers; +/* pointers to buffers that will receive jtag scan results on the next flush */ +#define MAX_PENDING_SCAN_RESULTS 256 +static int pending_scan_result_count; +static struct pending_scan_result pending_scan_results[MAX_PENDING_SCAN_RESULTS]; + +/* queued JTAG sequences that will be executed on the next flush */ +#define QUEUED_SEQ_BUF_LEN (cmsis_dap_handle->packet_size - 3) +static int queued_seq_count; +static int queued_seq_buf_end; +static int queued_seq_tdo_ptr; +static uint8_t queued_seq_buf[1024]; /* TODO: make dynamic / move into cmsis object */ + static int queued_retval; static struct cmsis_dap *cmsis_dap_handle; @@ -214,12 +257,14 @@ static int cmsis_dap_usb_open(void) /* we have found an adapter, so exit further checks */ /* check serial number matches if given */ if (cmsis_dap_serial != NULL) { - if (wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) { + if ((cur_dev->serial_number != NULL) && wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) { serial_found = true; break; } } else break; + + found = false; } cur_dev = cur_dev->next; @@ -271,9 +316,11 @@ static int cmsis_dap_usb_open(void) int packet_size = PACKET_SIZE; /* atmel cmsis-dap uses 512 byte reports */ + /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained + * board */ /* TODO: HID report descriptor should be parsed instead of * hardcoding a match by VID */ - if (target_vid == 0x03eb) + if (target_vid == 0x03eb && target_pid != 0x2145) packet_size = 512 + 1; cmsis_dap_handle->packet_buffer = malloc(packet_size); @@ -306,6 +353,9 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap) /* Send a message and receive the reply */ static int cmsis_dap_usb_xfer(struct cmsis_dap *dap, int txlen) { +#ifdef CMSIS_DAP_JTAG_DEBUG + LOG_DEBUG("cmsis-dap usb xfer cmd=%02X", dap->packet_buffer[1]); +#endif /* Pad the rest of the TX buffer with 0's */ memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen); @@ -375,6 +425,33 @@ static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock) return ERROR_OK; } +/* clock a sequence of bits out on TMS, to change JTAG states */ +static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence) +{ + int retval; + uint8_t *buffer = cmsis_dap_handle->packet_buffer; + +#ifdef CMSIS_DAP_JTAG_DEBUG + LOG_DEBUG("cmsis-dap TMS sequence: len=%d", s_len); + for (int i = 0; i < DIV_ROUND_UP(s_len, 8); ++i) + printf("%02X ", sequence[i]); + + printf("\n"); +#endif + + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_SWJ_SEQ; + buffer[2] = s_len; + bit_copy(&buffer[3], 0, sequence, 0, s_len); + + retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); + + if (retval != ERROR_OK || buffer[1] != DAP_OK) + return ERROR_FAIL; + + return ERROR_OK; +} + static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data) { int retval; @@ -696,12 +773,12 @@ static int cmsis_dap_get_status(void) if (retval == ERROR_OK) { LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d", - (d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */ - (d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */ - (d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */ - (d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */ - (d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */ - (d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */ + (d & SWJ_PIN_TCK) ? 1 : 0, + (d & SWJ_PIN_TMS) ? 1 : 0, + (d & SWJ_PIN_TDI) ? 1 : 0, + (d & SWJ_PIN_TDO) ? 1 : 0, + (d & SWJ_PIN_TRST) ? 1 : 0, + (d & SWJ_PIN_SRST) ? 1 : 0); } return retval; @@ -709,7 +786,6 @@ static int cmsis_dap_get_status(void) static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) { - uint8_t *buffer = cmsis_dap_handle->packet_buffer; const uint8_t *s; unsigned int s_len; int retval; @@ -745,17 +821,13 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) return ERROR_FAIL; } - buffer[0] = 0; /* report number */ - buffer[1] = CMD_DAP_SWJ_SEQ; - buffer[2] = s_len; - bit_copy(&buffer[3], 0, s, 0, s_len); - - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); - - if (retval != ERROR_OK || buffer[1] != DAP_OK) - return ERROR_FAIL; + retval = cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); + if (retval != ERROR_OK) + return retval; - return ERROR_OK; + /* Atmel EDBG needs renew clock setting after SWJ_Sequence + * otherwise default frequency is used */ + return cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); } static int cmsis_dap_swd_open(void) @@ -933,8 +1005,17 @@ static int cmsis_dap_quit(void) static void cmsis_dap_execute_reset(struct jtag_command *cmd) { - int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \ - (1 << 7), 0, NULL); + /* Set both TRST and SRST even if they're not enabled as + * there's no way to tristate them */ + uint8_t pins = 0; + + if (!cmd->cmd.reset->srst) + pins |= SWJ_PIN_SRST; + if (!cmd->cmd.reset->trst) + pins |= SWJ_PIN_TRST; + + int retval = cmsis_dap_cmd_DAP_SWJ_Pins(pins, + SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL); if (retval != ERROR_OK) LOG_ERROR("CMSIS-DAP: Interface reset failed"); } @@ -948,17 +1029,456 @@ static void cmsis_dap_execute_sleep(struct jtag_command *cmd) jtag_sleep(cmd->cmd.sleep->us); } +/* Set TMS high for five TCK clocks, to move the TAP to the Test-Logic-Reset state */ +static int cmsis_dap_execute_tlr_reset(struct jtag_command *cmd) +{ + LOG_INFO("cmsis-dap JTAG TLR_RESET"); + uint8_t seq = 0xff; + int ret = cmsis_dap_cmd_DAP_SWJ_Sequence(8, &seq); + if (ret == ERROR_OK) + tap_set_state(TAP_RESET); + return ret; +} + +/* Set new end state */ +static void cmsis_dap_end_state(tap_state_t state) +{ + if (tap_is_state_stable(state)) + tap_set_end_state(state); + else { + LOG_ERROR("BUG: %i is not a valid end state", state); + exit(-1); + } +} + +#ifdef SPRINT_BINARY +static void sprint_binary(char *s, const uint8_t *buf, int offset, int len) +{ + if (!len) + return; + + /* + buf = { 0x18 } len=5 should result in: 11000 + buf = { 0xff 0x18 } len=13 should result in: 11111111 11000 + buf = { 0xc0 0x18 } offset=3 len=10 should result in: 11000 11000 + i=3 there means i/8 = 0 so c = 0xFF, and + */ + for (int i = offset; i < offset + len; ++i) { + uint8_t c = buf[i / 8], mask = 1 << (i % 8); + if ((i != offset) && !(i % 8)) + putchar(' '); + *s++ = (c & mask) ? '1' : '0'; + } + *s = 0; +} +#endif + +#ifdef CMSIS_DAP_JTAG_DEBUG +static void debug_parse_cmsis_buf(const uint8_t *cmd, int cmdlen) +{ + /* cmd is a usb packet to go to the cmsis-dap interface */ + printf("cmsis-dap buffer (%d b): ", cmdlen); + for (int i = 0; i < cmdlen; ++i) + printf(" %02x", cmd[i]); + printf("\n"); + switch (cmd[1]) { + case CMD_DAP_JTAG_SEQ: { + printf("cmsis-dap jtag sequence command %02x (n=%d)\n", cmd[1], cmd[2]); + /* + * #2 = number of sequences + * #3 = sequence info 1 + * #4...4+n_bytes-1 = sequence 1 + * #4+n_bytes = sequence info 2 + * #5+n_bytes = sequence 2 (single bit) + */ + int pos = 3; + for (int seq = 0; seq < cmd[2]; ++seq) { + uint8_t info = cmd[pos++]; + int len = info & DAP_JTAG_SEQ_TCK; + if (len == 0) + len = 64; + printf(" sequence %d starting %d: info %02x (len=%d tms=%d read_tdo=%d): ", + seq, pos, info, len, info & DAP_JTAG_SEQ_TMS, info & DAP_JTAG_SEQ_TDO); + for (int i = 0; i < DIV_ROUND_UP(len, 8); ++i) + printf(" %02x", cmd[pos+i]); + pos += DIV_ROUND_UP(len, 8); + printf("\n"); + } + if (pos != cmdlen) { + printf("BUFFER LENGTH MISMATCH looks like %d but %d specified", pos, cmdlen); + exit(-1); + } + + break; + } + default: + LOG_DEBUG("unknown cmsis-dap command %02x", cmd[1]); + break; + } +} +#endif + +static void cmsis_dap_flush(void) +{ + if (!queued_seq_count) + return; + + DEBUG_JTAG_IO("Flushing %d queued sequences (%d bytes) with %d pending scan results to capture", + queued_seq_count, queued_seq_buf_end, pending_scan_result_count); + + /* prep CMSIS-DAP packet */ + uint8_t *buffer = cmsis_dap_handle->packet_buffer; + buffer[0] = 0; /* report number */ + buffer[1] = CMD_DAP_JTAG_SEQ; + buffer[2] = queued_seq_count; + memcpy(buffer + 3, queued_seq_buf, queued_seq_buf_end); + +#ifdef CMSIS_DAP_JTAG_DEBUG + debug_parse_cmsis_buf(buffer, queued_seq_buf_end + 3); +#endif + + /* send command to USB device */ + int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, queued_seq_buf_end + 3); + if (retval != ERROR_OK || buffer[1] != DAP_OK) { + LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed."); + exit(-1); + } + +#ifdef CMSIS_DAP_JTAG_DEBUG + DEBUG_JTAG_IO("USB response buf:"); + for (int c = 0; c < queued_seq_buf_end + 3; ++c) + printf("%02X ", buffer[c]); + printf("\n"); +#endif + + /* copy scan results into client buffers */ + for (int i = 0; i < pending_scan_result_count; ++i) { + struct pending_scan_result *scan = &pending_scan_results[i]; + DEBUG_JTAG_IO("Copying pending_scan_result %d/%d: %d bits from byte %d -> buffer + %d bits", + i, pending_scan_result_count, scan->length, scan->first + 2, scan->buffer_offset); +#ifdef CMSIS_DAP_JTAG_DEBUG + for (uint32_t b = 0; b < DIV_ROUND_UP(scan->length, 8); ++b) + printf("%02X ", buffer[2+scan->first+b]); + printf("\n"); +#endif + bit_copy(scan->buffer, scan->buffer_offset, buffer + 2 + scan->first, 0, scan->length); + } + + /* reset */ + queued_seq_count = 0; + queued_seq_buf_end = 0; + queued_seq_tdo_ptr = 0; + pending_scan_result_count = 0; +} + +/* queue a sequence of bits to clock out TDI / in TDO, executing if the buffer is full. + * + * sequence=NULL means clock out zeros on TDI + * tdo_buffer=NULL means don't capture TDO + */ +static void cmsis_dap_add_jtag_sequence(int s_len, const uint8_t *sequence, int s_offset, + bool tms, uint8_t *tdo_buffer, int tdo_buffer_offset) +{ + DEBUG_JTAG_IO("[at %d] %d bits, tms %s, seq offset %d, tdo buf %p, tdo offset %d", + queued_seq_buf_end, + s_len, tms ? "HIGH" : "LOW", s_offset, tdo_buffer, tdo_buffer_offset); + + if (s_len == 0) + return; + + if (s_len > 64) { + DEBUG_JTAG_IO("START JTAG SEQ SPLIT"); + for (int offset = 0; offset < s_len; offset += 64) { + int len = s_len - offset; + if (len > 64) + len = 64; + DEBUG_JTAG_IO("Splitting long jtag sequence: %d-bit chunk starting at offset %d", len, offset); + cmsis_dap_add_jtag_sequence( + len, + sequence, + s_offset + offset, + tms, + tdo_buffer, + tdo_buffer == NULL ? 0 : (tdo_buffer_offset + offset) + ); + } + DEBUG_JTAG_IO("END JTAG SEQ SPLIT"); + return; + } + + int cmd_len = 1 + DIV_ROUND_UP(s_len, 8); + if (queued_seq_count >= 255 || queued_seq_buf_end + cmd_len > QUEUED_SEQ_BUF_LEN) + /* empty out the buffer */ + cmsis_dap_flush(); + + ++queued_seq_count; + + /* control byte */ + queued_seq_buf[queued_seq_buf_end] = + (tms ? DAP_JTAG_SEQ_TMS : 0) | + (tdo_buffer != NULL ? DAP_JTAG_SEQ_TDO : 0) | + (s_len == 64 ? 0 : s_len); + + if (sequence != NULL) + bit_copy(&queued_seq_buf[queued_seq_buf_end + 1], 0, sequence, s_offset, s_len); + else + memset(&queued_seq_buf[queued_seq_buf_end + 1], 0, DIV_ROUND_UP(s_len, 8)); + + queued_seq_buf_end += cmd_len; + + if (tdo_buffer != NULL) { + struct pending_scan_result *scan = &pending_scan_results[pending_scan_result_count++]; + scan->first = queued_seq_tdo_ptr; + queued_seq_tdo_ptr += DIV_ROUND_UP(s_len, 8); + scan->length = s_len; + scan->buffer = tdo_buffer; + scan->buffer_offset = tdo_buffer_offset; + } +} + +/* queue a sequence of bits to clock out TMS, executing if the buffer is full */ +static void cmsis_dap_add_tms_sequence(const uint8_t *sequence, int s_len) +{ + DEBUG_JTAG_IO("%d bits: %02X", s_len, *sequence); + /* we use a series of CMD_DAP_JTAG_SEQ commands to toggle TMS, + because even though it seems ridiculously inefficient, it + allows us to combine TMS and scan sequences into the same + USB packet. */ + /* TODO: combine runs of the same tms value */ + for (int i = 0; i < s_len; ++i) { + bool bit = (sequence[i / 8] & (1 << (i % 8))) != 0; + cmsis_dap_add_jtag_sequence(1, NULL, 0, bit, NULL, 0); + } +} + +/* Move to the end state by queuing a sequence to clock into TMS */ +static void cmsis_dap_state_move(void) +{ + uint8_t tms_scan; + uint8_t tms_scan_bits; + + tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); + tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); + + DEBUG_JTAG_IO("state move from %s to %s: %d clocks, %02X on tms", + tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()), + tms_scan_bits, tms_scan); + cmsis_dap_add_tms_sequence(&tms_scan, tms_scan_bits); + + tap_set_state(tap_get_end_state()); +} + + +/* Execute a JTAG scan operation by queueing TMS and TDI/TDO sequences */ +static void cmsis_dap_execute_scan(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", + jtag_scan_type(cmd->cmd.scan)); + + /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ + while (cmd->cmd.scan->num_fields > 0 + && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) { + cmd->cmd.scan->num_fields--; + LOG_DEBUG("discarding trailing empty field"); + } + + if (cmd->cmd.scan->num_fields == 0) { + LOG_DEBUG("empty scan, doing nothing"); + return; + } + + if (cmd->cmd.scan->ir_scan) { + if (tap_get_state() != TAP_IRSHIFT) { + cmsis_dap_end_state(TAP_IRSHIFT); + cmsis_dap_state_move(); + } + } else { + if (tap_get_state() != TAP_DRSHIFT) { + cmsis_dap_end_state(TAP_DRSHIFT); + cmsis_dap_state_move(); + } + } + + cmsis_dap_end_state(cmd->cmd.scan->end_state); + + struct scan_field *field = cmd->cmd.scan->fields; + unsigned scan_size = 0; + + for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + scan_size += field->num_bits; + DEBUG_JTAG_IO("%s%s field %d/%d %d bits", + field->in_value ? "in" : "", + field->out_value ? "out" : "", + i, + cmd->cmd.scan->num_fields, + field->num_bits); + + if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) { + DEBUG_JTAG_IO("Last field and have to move out of SHIFT state"); + /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap + * movement. This last field can't have length zero, it was checked above. */ + cmsis_dap_add_jtag_sequence( + field->num_bits - 1, /* number of bits to clock */ + field->out_value, /* output sequence */ + 0, /* output offset */ + false, /* TMS low */ + field->in_value, + 0); + + /* Clock the last bit out, with TMS high */ + uint8_t last_bit = 0; + if (field->out_value) + bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); + cmsis_dap_add_jtag_sequence( + 1, + &last_bit, + 0, + true, + field->in_value, + field->num_bits - 1); + tap_set_state(tap_state_transition(tap_get_state(), 1)); + + /* Now clock one more cycle, with TMS low, to get us into a PAUSE state */ + cmsis_dap_add_jtag_sequence( + 1, + &last_bit, + 0, + false, + NULL, + 0); + tap_set_state(tap_state_transition(tap_get_state(), 0)); + } else { + DEBUG_JTAG_IO("Internal field, staying in SHIFT state afterwards"); + /* Clocking part of a sequence into DR or IR with TMS=0, + leaving TMS=0 at the end so we can continue later */ + cmsis_dap_add_jtag_sequence( + field->num_bits, + field->out_value, + 0, + false, + field->in_value, + 0); + } + } + + if (tap_get_state() != tap_get_end_state()) { + cmsis_dap_end_state(tap_get_end_state()); + cmsis_dap_state_move(); + } + + DEBUG_JTAG_IO("%s scan, %i bits, end in %s", + (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, + tap_state_name(tap_get_end_state())); +} + +static void cmsis_dap_pathmove(int num_states, tap_state_t *path) +{ + int i; + uint8_t tms0 = 0x00; + uint8_t tms1 = 0xff; + + for (i = 0; i < num_states; i++) { + if (path[i] == tap_state_transition(tap_get_state(), false)) + cmsis_dap_add_tms_sequence(&tms0, 1); + else if (path[i] == tap_state_transition(tap_get_state(), true)) + cmsis_dap_add_tms_sequence(&tms1, 1); + else { + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.", + tap_state_name(tap_get_state()), tap_state_name(path[i])); + exit(-1); + } + + tap_set_state(path[i]); + } + + cmsis_dap_end_state(tap_get_state()); +} + +static void cmsis_dap_execute_pathmove(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("pathmove: %i states, end in %i", + cmd->cmd.pathmove->num_states, + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + + cmsis_dap_pathmove(cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path); +} + +static void cmsis_dap_stableclocks(int num_cycles) +{ + int i; + + uint8_t tms = tap_get_state() == TAP_RESET; + /* TODO: Perform optimizations? */ + /* Execute num_cycles. */ + for (i = 0; i < num_cycles; i++) + cmsis_dap_add_tms_sequence(&tms, 1); +} + +static void cmsis_dap_runtest(int num_cycles) +{ + tap_state_t saved_end_state = tap_get_end_state(); + + /* Only do a state_move when we're not already in IDLE. */ + if (tap_get_state() != TAP_IDLE) { + cmsis_dap_end_state(TAP_IDLE); + cmsis_dap_state_move(); + } + cmsis_dap_stableclocks(num_cycles); + + /* Finish in end_state. */ + cmsis_dap_end_state(saved_end_state); + + if (tap_get_state() != tap_get_end_state()) + cmsis_dap_state_move(); +} + +static void cmsis_dap_execute_runtest(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, + cmd->cmd.runtest->end_state); + + cmsis_dap_end_state(cmd->cmd.runtest->end_state); + cmsis_dap_runtest(cmd->cmd.runtest->num_cycles); +} + +static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles); +} + +/* TODO: Is there need to call cmsis_dap_flush() for the JTAG_PATHMOVE, + * JTAG_RUNTEST, JTAG_STABLECLOCKS? */ static void cmsis_dap_execute_command(struct jtag_command *cmd) { switch (cmd->type) { case JTAG_RESET: + cmsis_dap_flush(); cmsis_dap_execute_reset(cmd); break; case JTAG_SLEEP: + cmsis_dap_flush(); cmsis_dap_execute_sleep(cmd); break; + case JTAG_TLR_RESET: + cmsis_dap_flush(); + cmsis_dap_execute_tlr_reset(cmd); + break; + case JTAG_SCAN: + cmsis_dap_execute_scan(cmd); + break; + case JTAG_PATHMOVE: + cmsis_dap_execute_pathmove(cmd); + break; + case JTAG_RUNTEST: + cmsis_dap_execute_runtest(cmd); + break; + case JTAG_STABLECLOCKS: + cmsis_dap_execute_stableclocks(cmd); + break; + case JTAG_TMS: default: - LOG_ERROR("BUG: unknown JTAG command type encountered"); + LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type); exit(-1); } } @@ -972,18 +1492,18 @@ static int cmsis_dap_execute_queue(void) cmd = cmd->next; } + cmsis_dap_flush(); + return ERROR_OK; } static int cmsis_dap_speed(int speed) { - if (speed > DAP_MAX_CLOCK) { - LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK); - speed = DAP_MAX_CLOCK; - } + if (speed > DAP_MAX_CLOCK) + LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed); if (speed == 0) { - LOG_INFO("RTCK not supported"); + LOG_ERROR("RTCK not supported. Set nonzero adapter_khz."); return ERROR_JTAG_NOT_IMPLEMENTED; } @@ -1010,6 +1530,7 @@ static int_least32_t cmsis_dap_swd_frequency(int_least32_t hz) return hz; } + COMMAND_HANDLER(cmsis_dap_handle_info_command) { if (cmsis_dap_get_version_info() == ERROR_OK) @@ -1114,7 +1635,7 @@ static const struct swd_driver cmsis_dap_swd_driver = { .run = cmsis_dap_swd_run_queue, }; -static const char * const cmsis_dap_transport[] = { "swd", NULL }; +static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL }; struct jtag_interface cmsis_dap_interface = { .name = "cmsis-dap", diff --git a/src/jtag/drivers/driver.c b/src/jtag/drivers/driver.c index 75ec115ed..daf7cd426 100644 --- a/src/jtag/drivers/driver.c +++ b/src/jtag/drivers/driver.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/dummy.c b/src/jtag/drivers/dummy.c index ddba976d0..0f7c12dd4 100644 --- a/src/jtag/drivers/dummy.c +++ b/src/jtag/drivers/dummy.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/ep93xx.c b/src/jtag/drivers/ep93xx.c index 8e12e1728..ccd979502 100644 --- a/src/jtag/drivers/ep93xx.c +++ b/src/jtag/drivers/ep93xx.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/ftdi.c b/src/jtag/drivers/ftdi.c index d8c7d6422..26bc53d54 100644 --- a/src/jtag/drivers/ftdi.c +++ b/src/jtag/drivers/ftdi.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* along with this program. If not, see . * ***************************************************************************/ /** @@ -86,11 +84,14 @@ #include "mpsse.h" #define JTAG_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) +#define JTAG_MODE_ALT (LSB_FIRST | NEG_EDGE_IN | NEG_EDGE_OUT) #define SWD_MODE (LSB_FIRST | POS_EDGE_IN | NEG_EDGE_OUT) static char *ftdi_device_desc; static char *ftdi_serial; +static char *ftdi_location; static uint8_t ftdi_channel; +static uint8_t ftdi_jtag_mode = JTAG_MODE; static bool swd_mode; @@ -104,8 +105,10 @@ static struct mpsse_ctx *mpsse_ctx; struct signal { const char *name; uint16_t data_mask; + uint16_t input_mask; uint16_t oe_mask; bool invert_data; + bool invert_input; bool invert_oe; struct signal *next; }; @@ -210,6 +213,32 @@ static int ftdi_set_signal(const struct signal *s, char value) return ERROR_OK; } +static int ftdi_get_signal(const struct signal *s, uint16_t * value_out) +{ + uint8_t data_low = 0; + uint8_t data_high = 0; + + if (s->input_mask == 0) { + LOG_ERROR("interface doesn't provide signal '%s'", s->name); + return ERROR_FAIL; + } + + if (s->input_mask & 0xff) + mpsse_read_data_bits_low_byte(mpsse_ctx, &data_low); + if (s->input_mask >> 8) + mpsse_read_data_bits_high_byte(mpsse_ctx, &data_high); + + mpsse_flush(mpsse_ctx); + + *value_out = (((uint16_t)data_high) << 8) | data_low; + + if (s->invert_input) + *value_out = ~(*value_out); + + *value_out &= s->input_mask; + + return ERROR_OK; +} /** * Function move_to_state @@ -244,7 +273,7 @@ static void move_to_state(tap_state_t goal_state) 0, tms_count, false, - JTAG_MODE); + ftdi_jtag_mode); } static int ftdi_speed(int speed) @@ -257,6 +286,9 @@ static int ftdi_speed(int speed) return retval; } + if (!swd_mode && speed >= 10000000 && ftdi_jtag_mode != JTAG_MODE_ALT) + LOG_INFO("ftdi: if you experience problems at higher adapter clocks, try " + "the command \"ftdi_tdo_sample_edge falling\""); return ERROR_OK; } @@ -304,7 +336,7 @@ static void ftdi_execute_runtest(struct jtag_command *cmd) while (i > 0) { /* there are no state transitions in this code, so omit state tracking */ unsigned this_len = i > 7 ? 7 : i; - mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, JTAG_MODE); + mpsse_clock_tms_cs_out(mpsse_ctx, &zero, 0, this_len, false, ftdi_jtag_mode); i -= this_len; } @@ -344,7 +376,7 @@ static void ftdi_execute_tms(struct jtag_command *cmd) 0, cmd->cmd.tms->num_bits, false, - JTAG_MODE); + ftdi_jtag_mode); } static void ftdi_execute_pathmove(struct jtag_command *cmd) @@ -391,17 +423,51 @@ static void ftdi_execute_pathmove(struct jtag_command *cmd) 0, bit_count, false, - JTAG_MODE); + ftdi_jtag_mode); bit_count = 0; } } tap_set_end_state(tap_get_state()); } +#if BUILD_RISCV == 1 +#ifdef _DEBUG_JTAG_IO_ +static void debug_jtag_io_value(const char *prefix, const uint8_t *value, + unsigned int num_bits) +{ + if (!value) { + return; + } + + char buf[33]; + char *bufp = buf; + unsigned int chars = (num_bits + 3) / 4; + for (unsigned int i = 0; i < chars; i++) { + if (i && (i % 32) == 0) { + DEBUG_JTAG_IO(" %s%s", prefix, buf); + bufp = buf; + } + int start_bit = 4 * (chars - i - 1); + sprintf(bufp, "%01x", buf_get_u32(value, start_bit, 4)); + bufp++; + } + if (bufp != buf) { + DEBUG_JTAG_IO(" %s%s", prefix, buf); + } +} +#endif +#endif + static void ftdi_execute_scan(struct jtag_command *cmd) { DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", jtag_scan_type(cmd->cmd.scan)); +#if BUILD_RISCV == 1 +#ifdef _DEBUG_JTAG_IO_ + debug_jtag_io_value(" out=", cmd->cmd.scan->fields->out_value, + cmd->cmd.scan->fields->num_bits); +#endif +#endif /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ while (cmd->cmd.scan->num_fields > 0 @@ -446,7 +512,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) field->in_value, 0, field->num_bits - 1, - JTAG_MODE); + ftdi_jtag_mode); uint8_t last_bit = 0; if (field->out_value) bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); @@ -458,14 +524,14 @@ static void ftdi_execute_scan(struct jtag_command *cmd) field->num_bits - 1, 1, last_bit, - JTAG_MODE); + ftdi_jtag_mode); tap_set_state(tap_state_transition(tap_get_state(), 1)); mpsse_clock_tms_cs_out(mpsse_ctx, &tms_bits, 1, 1, last_bit, - JTAG_MODE); + ftdi_jtag_mode); tap_set_state(tap_state_transition(tap_get_state(), 0)); } else mpsse_clock_data(mpsse_ctx, @@ -474,7 +540,7 @@ static void ftdi_execute_scan(struct jtag_command *cmd) field->in_value, 0, field->num_bits, - JTAG_MODE); + ftdi_jtag_mode); } if (tap_get_state() != tap_get_end_state()) @@ -483,6 +549,13 @@ static void ftdi_execute_scan(struct jtag_command *cmd) DEBUG_JTAG_IO("%s scan, %i bits, end in %s", (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, tap_state_name(tap_get_end_state())); + +#if BUILD_RISCV == 1 +#ifdef _DEBUG_JTAG_IO_ + debug_jtag_io_value(" in=", cmd->cmd.scan->fields->in_value, + cmd->cmd.scan->fields->num_bits); +#endif +#endif } static void ftdi_execute_reset(struct jtag_command *cmd) @@ -553,7 +626,7 @@ static void ftdi_execute_stableclocks(struct jtag_command *cmd) while (num_cycles > 0) { /* there are no state transitions in this code, so omit state tracking */ unsigned this_len = num_cycles > 7 ? 7 : num_cycles; - mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, JTAG_MODE); + mpsse_clock_tms_cs_out(mpsse_ctx, &tms, 0, this_len, false, ftdi_jtag_mode); num_cycles -= this_len; } @@ -626,7 +699,7 @@ static int ftdi_initialize(void) for (int i = 0; ftdi_vid[i] || ftdi_pid[i]; i++) { mpsse_ctx = mpsse_open(&ftdi_vid[i], &ftdi_pid[i], ftdi_device_desc, - ftdi_serial, ftdi_channel); + ftdi_serial, ftdi_location, ftdi_channel); if (mpsse_ctx) break; } @@ -693,6 +766,21 @@ COMMAND_HANDLER(ftdi_handle_serial_command) return ERROR_OK; } +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS +COMMAND_HANDLER(ftdi_handle_location_command) +{ + if (CMD_ARGC == 1) { + if (ftdi_location) + free(ftdi_location); + ftdi_location = strdup(CMD_ARGV[0]); + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return ERROR_OK; +} +#endif + COMMAND_HANDLER(ftdi_handle_channel_command) { if (CMD_ARGC == 1) @@ -721,6 +809,8 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) bool invert_data = false; uint16_t data_mask = 0; + bool invert_input = false; + uint16_t input_mask = 0; bool invert_oe = false; uint16_t oe_mask = 0; for (unsigned i = 1; i < CMD_ARGC; i += 2) { @@ -730,6 +820,12 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) } else if (strcmp("-ndata", CMD_ARGV[i]) == 0) { invert_data = true; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], data_mask); + } else if (strcmp("-input", CMD_ARGV[i]) == 0) { + invert_input = false; + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask); + } else if (strcmp("-ninput", CMD_ARGV[i]) == 0) { + invert_input = true; + COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], input_mask); } else if (strcmp("-oe", CMD_ARGV[i]) == 0) { invert_oe = false; COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask); @@ -738,15 +834,19 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], oe_mask); } else if (!strcmp("-alias", CMD_ARGV[i]) || !strcmp("-nalias", CMD_ARGV[i])) { - if (!strcmp("-nalias", CMD_ARGV[i])) + if (!strcmp("-nalias", CMD_ARGV[i])) { invert_data = true; + invert_input = true; + } struct signal *sig = find_signal_by_name(CMD_ARGV[i + 1]); if (!sig) { LOG_ERROR("signal %s is not defined", CMD_ARGV[i + 1]); return ERROR_FAIL; } data_mask = sig->data_mask; + input_mask = sig->input_mask; oe_mask = sig->oe_mask; + invert_input ^= sig->invert_input; invert_oe = sig->invert_oe; invert_data ^= sig->invert_data; } else { @@ -766,6 +866,8 @@ COMMAND_HANDLER(ftdi_handle_layout_signal_command) sig->invert_data = invert_data; sig->data_mask = data_mask; + sig->invert_input = invert_input; + sig->input_mask = input_mask; sig->invert_oe = invert_oe; sig->oe_mask = oe_mask; @@ -802,6 +904,28 @@ COMMAND_HANDLER(ftdi_handle_set_signal_command) return mpsse_flush(mpsse_ctx); } +COMMAND_HANDLER(ftdi_handle_get_signal_command) +{ + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct signal *sig; + uint16_t sig_data = 0; + sig = find_signal_by_name(CMD_ARGV[0]); + if (!sig) { + LOG_ERROR("interface configuration doesn't define signal '%s'", CMD_ARGV[0]); + return ERROR_FAIL; + } + + int ret = ftdi_get_signal(sig, &sig_data); + if (ret != ERROR_OK) + return ret; + + LOG_USER("Signal %s = %#06x", sig->name, sig_data); + + return ERROR_OK; +} + COMMAND_HANDLER(ftdi_handle_vid_pid_command) { if (CMD_ARGC > MAX_USB_IDS * 2) { @@ -832,6 +956,29 @@ COMMAND_HANDLER(ftdi_handle_vid_pid_command) return ERROR_OK; } +COMMAND_HANDLER(ftdi_handle_tdo_sample_edge_command) +{ + Jim_Nvp *n; + static const Jim_Nvp nvp_ftdi_jtag_modes[] = { + { .name = "rising", .value = JTAG_MODE }, + { .name = "falling", .value = JTAG_MODE_ALT }, + { .name = NULL, .value = -1 }, + }; + + if (CMD_ARGC > 0) { + n = Jim_Nvp_name2value_simple(nvp_ftdi_jtag_modes, CMD_ARGV[0]); + if (n->name == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + ftdi_jtag_mode = n->value; + + } + + n = Jim_Nvp_value2name_simple(nvp_ftdi_jtag_modes, ftdi_jtag_mode); + command_print(CMD_CTX, "ftdi samples TDO on %s edge of TCK", n->name); + + return ERROR_OK; +} + static const struct command_registration ftdi_command_handlers[] = { { .name = "ftdi_device_desc", @@ -847,6 +994,15 @@ static const struct command_registration ftdi_command_handlers[] = { .help = "set the serial number of the FTDI device", .usage = "serial_string", }, +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS + { + .name = "ftdi_location", + .handler = &ftdi_handle_location_command, + .mode = COMMAND_CONFIG, + .help = "set the USB bus location of the FTDI device", + .usage = ":port[,port]...", + }, +#endif { .name = "ftdi_channel", .handler = &ftdi_handle_channel_command, @@ -877,6 +1033,13 @@ static const struct command_registration ftdi_command_handlers[] = { .help = "control a layout-specific signal", .usage = "name (1|0|z)", }, + { + .name = "ftdi_get_signal", + .handler = &ftdi_handle_get_signal_command, + .mode = COMMAND_EXEC, + .help = "read the value of a layout-specific signal", + .usage = "name", + }, { .name = "ftdi_vid_pid", .handler = &ftdi_handle_vid_pid_command, @@ -884,6 +1047,15 @@ static const struct command_registration ftdi_command_handlers[] = { .help = "the vendor ID and product ID of the FTDI device", .usage = "(vid pid)* ", }, + { + .name = "ftdi_tdo_sample_edge", + .handler = &ftdi_handle_tdo_sample_edge_command, + .mode = COMMAND_ANY, + .help = "set which TCK clock edge is used for sampling TDO " + "- default is rising-edge (Setting to falling-edge may " + "allow signalling speed increase)", + .usage = "(rising|falling)", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/drivers/gw16012.c b/src/jtag/drivers/gw16012.c index 6f79f0cce..f6689969a 100644 --- a/src/jtag/drivers/gw16012.c +++ b/src/jtag/drivers/gw16012.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 84127ab54..bd3c5e03c 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -11,6 +11,9 @@ * Copyright (C) 2015 by Marc Schink * * openocd-dev@marcschink.de * * * + * Copyright (C) 2015 by Paul Fertser * + * fercerpav@gmail.com * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -22,8 +25,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -48,9 +50,9 @@ static uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE]; static uint32_t serial_number; static bool use_serial_number; -static uint8_t usb_address; +static enum jaylink_usb_address usb_address; static bool use_usb_address; -static uint8_t iface = JAYLINK_TIF_JTAG; +static enum jaylink_target_interface iface = JAYLINK_TIF_JTAG; static bool trace_enabled; #define JLINK_MAX_SPEED 12000 @@ -83,9 +85,8 @@ static struct device_config tmp_config; static void jlink_end_state(tap_state_t state); static void jlink_state_move(void); static void jlink_path_move(int num_states, tap_state_t *path); +static void jlink_stableclocks(int num_cycles); static void jlink_runtest(int num_cycles); -static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, - int scan_size, struct scan_command *command); static void jlink_reset(int trst, int srst); static int jlink_swd_run_queue(void); static void jlink_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data, uint32_t ap_delay_clk); @@ -93,11 +94,25 @@ static int jlink_swd_switch_seq(enum swd_special_seq seq); /* J-Link tap buffer functions */ static void jlink_tap_init(void); -static int jlink_tap_execute(void); -static void jlink_tap_ensure_space(int scans, int bits); -static void jlink_tap_append_step(int tms, int tdi); -static void jlink_tap_append_scan(int length, uint8_t *buffer, - struct scan_command *command); +static int jlink_flush(void); +/** + * Queue data to go out and in, flushing the queue as many times as + * necessary. + * + * @param out A pointer to TDI data, if NULL, old stale data will be used. + * @param out_offset A bit offset for TDI data. + * @param tms_out A pointer to TMS data, if NULL, zeroes will be emitted. + * @param tms_offset A bit offset for TMS data. + * @param in A pointer to store TDO data to, if NULL the data will be discarded. + * @param in_offset A bit offset for TDO data. + * @param length Amount of bits to transfer out and in. + * + * @retval This function doesn't return any value. + */ +static void jlink_clock_data(const uint8_t *out, unsigned out_offset, + const uint8_t *tms_out, unsigned tms_offset, + uint8_t *in, unsigned in_offset, + unsigned length); static enum tap_state jlink_last_state = TAP_RESET; static int queued_retval; @@ -105,6 +120,12 @@ static int queued_retval; /***************************************************************************/ /* External interface implementation */ +static void jlink_execute_stableclocks(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("stableclocks %i cycles", cmd->cmd.runtest->num_cycles); + jlink_stableclocks(cmd->cmd.runtest->num_cycles); +} + static void jlink_execute_runtest(struct jtag_command *cmd) { DEBUG_JTAG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, @@ -133,19 +154,95 @@ static void jlink_execute_pathmove(struct jtag_command *cmd) static void jlink_execute_scan(struct jtag_command *cmd) { - int scan_size; - enum scan_type type; - uint8_t *buffer; + DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", + jtag_scan_type(cmd->cmd.scan)); + + /* Make sure there are no trailing fields with num_bits == 0, or the logic below will fail. */ + while (cmd->cmd.scan->num_fields > 0 + && cmd->cmd.scan->fields[cmd->cmd.scan->num_fields - 1].num_bits == 0) { + cmd->cmd.scan->num_fields--; + LOG_DEBUG("discarding trailing empty field"); + } - DEBUG_JTAG_IO("scan end in %s", tap_state_name(cmd->cmd.scan->end_state)); + if (cmd->cmd.scan->num_fields == 0) { + LOG_DEBUG("empty scan, doing nothing"); + return; + } + + if (cmd->cmd.scan->ir_scan) { + if (tap_get_state() != TAP_IRSHIFT) { + jlink_end_state(TAP_IRSHIFT); + jlink_state_move(); + } + } else { + if (tap_get_state() != TAP_DRSHIFT) { + jlink_end_state(TAP_DRSHIFT); + jlink_state_move(); + } + } jlink_end_state(cmd->cmd.scan->end_state); - scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); - DEBUG_JTAG_IO("scan input, length = %d", scan_size); + struct scan_field *field = cmd->cmd.scan->fields; + unsigned scan_size = 0; + + for (int i = 0; i < cmd->cmd.scan->num_fields; i++, field++) { + scan_size += field->num_bits; + DEBUG_JTAG_IO("%s%s field %d/%d %d bits", + field->in_value ? "in" : "", + field->out_value ? "out" : "", + i, + cmd->cmd.scan->num_fields, + field->num_bits); + + if (i == cmd->cmd.scan->num_fields - 1 && tap_get_state() != tap_get_end_state()) { + /* Last field, and we're leaving IRSHIFT/DRSHIFT. Clock last bit during tap + * movement. This last field can't have length zero, it was checked above. */ + jlink_clock_data(field->out_value, + 0, + NULL, + 0, + field->in_value, + 0, + field->num_bits - 1); + uint8_t last_bit = 0; + if (field->out_value) + bit_copy(&last_bit, 0, field->out_value, field->num_bits - 1, 1); + uint8_t tms_bits = 0x01; + jlink_clock_data(&last_bit, + 0, + &tms_bits, + 0, + field->in_value, + field->num_bits - 1, + 1); + tap_set_state(tap_state_transition(tap_get_state(), 1)); + jlink_clock_data(NULL, + 0, + &tms_bits, + 1, + NULL, + 0, + 1); + tap_set_state(tap_state_transition(tap_get_state(), 0)); + } else + jlink_clock_data(field->out_value, + 0, + NULL, + 0, + field->in_value, + 0, + field->num_bits); + } + + if (tap_get_state() != tap_get_end_state()) { + jlink_end_state(tap_get_end_state()); + jlink_state_move(); + } - type = jtag_scan_type(cmd->cmd.scan); - jlink_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size, cmd->cmd.scan); + DEBUG_JTAG_IO("%s scan, %i bits, end in %s", + (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, + tap_state_name(tap_get_end_state())); } static void jlink_execute_reset(struct jtag_command *cmd) @@ -153,21 +250,24 @@ static void jlink_execute_reset(struct jtag_command *cmd) DEBUG_JTAG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); - jlink_tap_execute(); + jlink_flush(); jlink_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - jlink_tap_execute(); + jlink_flush(); } static void jlink_execute_sleep(struct jtag_command *cmd) { DEBUG_JTAG_IO("sleep %" PRIi32 "", cmd->cmd.sleep->us); - jlink_tap_execute(); + jlink_flush(); jtag_sleep(cmd->cmd.sleep->us); } static int jlink_execute_command(struct jtag_command *cmd) { switch (cmd->type) { + case JTAG_STABLECLOCKS: + jlink_execute_stableclocks(cmd); + break; case JTAG_RUNTEST: jlink_execute_runtest(cmd); break; @@ -208,18 +308,17 @@ static int jlink_execute_queue(void) cmd = cmd->next; } - return jlink_tap_execute(); + return jlink_flush(); } static int jlink_speed(int speed) { int ret; - uint32_t freq; - uint16_t divider; + struct jaylink_speed tmp; int max_speed; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { - ret = jaylink_get_speeds(devh, &freq, ÷r); + ret = jaylink_get_speeds(devh, &tmp); if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_speeds() failed: %s.", @@ -227,8 +326,8 @@ static int jlink_speed(int speed) return ERROR_JTAG_DEVICE_ERROR; } - freq = freq / 1000; - max_speed = freq / divider; + tmp.freq /= 1000; + max_speed = tmp.freq / tmp.div; } else { max_speed = JLINK_MAX_SPEED; } @@ -319,7 +418,7 @@ static int select_interface(void) return ERROR_JTAG_INIT_FAILED; } - ret = jaylink_select_interface(devh, iface); + ret = jaylink_select_interface(devh, iface, NULL); if (ret < 0) { LOG_ERROR("jaylink_select_interface() failed: %s.", @@ -333,15 +432,16 @@ static int select_interface(void) static int jlink_register(void) { int ret; - int i; + size_t i; bool handle_found; + size_t count; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) return ERROR_OK; - ret = jaylink_register(devh, &conn, connlist, NULL, NULL); + ret = jaylink_register(devh, &conn, connlist, &count); - if (ret < 0) { + if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_register() failed: %s.", jaylink_strerror_name(ret)); return ERROR_FAIL; @@ -349,7 +449,7 @@ static int jlink_register(void) handle_found = false; - for (i = 0; i < ret; i++) { + for (i = 0; i < count; i++) { if (connlist[i].handle == conn.handle) { handle_found = true; break; @@ -402,6 +502,36 @@ static bool adjust_swd_buffer_size(void) return true; } +static int jaylink_log_handler(const struct jaylink_context *ctx, + enum jaylink_log_level level, const char *format, va_list args, + void *user_data) +{ + enum log_levels tmp; + + switch (level) { + case JAYLINK_LOG_LEVEL_ERROR: + tmp = LOG_LVL_ERROR; + break; + case JAYLINK_LOG_LEVEL_WARNING: + tmp = LOG_LVL_WARNING; + break; + /* + * Forward info messages to the debug output because they are more verbose + * than info messages of OpenOCD. + */ + case JAYLINK_LOG_LEVEL_INFO: + case JAYLINK_LOG_LEVEL_DEBUG: + tmp = LOG_LVL_DEBUG; + break; + default: + tmp = LOG_LVL_WARNING; + } + + log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args); + + return 0; +} + static int jlink_init(void) { int ret; @@ -412,6 +542,11 @@ static int jlink_init(void) char *firmware_version; struct jaylink_hardware_version hwver; struct jaylink_hardware_status hwstatus; + enum jaylink_usb_address address; + size_t length; + + LOG_DEBUG("Using libjaylink %s (compiled with %s).", + jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING); ret = jaylink_init(&jayctx); @@ -421,10 +556,28 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } - ret = jaylink_get_device_list(jayctx, &devs); + ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL); - if (ret < 0) { - LOG_ERROR("jaylink_get_device_list() failed: %s.", + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_log_set_callback() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_discovery_scan(jayctx, 0); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_discovery_scan() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_get_devices(jayctx, &devs, NULL); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror_name(ret)); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -436,27 +589,45 @@ static int jlink_init(void) LOG_INFO("No device selected, using first device."); for (i = 0; devs[i]; i++) { - jaylink_device_get_serial_number(devs[i], &tmp); - ret = jaylink_device_get_usb_address(devs[i]); + if (use_serial_number) { + ret = jaylink_device_get_serial_number(devs[i], &tmp); + + if (ret == JAYLINK_ERR_NOT_AVAILABLE) { + continue; + } else if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_serial_number() failed: %s.", + jaylink_strerror_name(ret)); + continue; + } + + if (serial_number != tmp) + continue; + } - if (use_usb_address && usb_address != ret) - continue; + if (use_usb_address) { + ret = jaylink_device_get_usb_address(devs[i], &address); - if (use_serial_number && tmp != serial_number) - continue; + if (ret != JAYLINK_OK) { + LOG_WARNING("jaylink_device_get_usb_address() failed: %s.", + jaylink_strerror_name(ret)); + continue; + } + + if (usb_address != address) + continue; + } ret = jaylink_open(devs[i], &devh); - if (ret != JAYLINK_OK) { - LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); - continue; + if (ret == JAYLINK_OK) { + found_device = true; + break; } - found_device = true; - break; + LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); } - jaylink_free_device_list(devs, 1); + jaylink_free_devices(devs, true); if (!found_device) { LOG_ERROR("No J-Link device found."); @@ -469,19 +640,19 @@ static int jlink_init(void) * some devices are known to be sensitive regarding the order. */ - ret = jaylink_get_firmware_version(devh, &firmware_version); + ret = jaylink_get_firmware_version(devh, &firmware_version, &length); - if (ret > 0) { - LOG_INFO("%s", firmware_version); - free(firmware_version); - } else if (!ret) { - LOG_WARNING("Device responds empty firmware version string."); - } else { + if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_firmware_version() failed: %s.", jaylink_strerror_name(ret)); jaylink_close(devh); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; + } else if (length > 0) { + LOG_INFO("%s", firmware_version); + free(firmware_version); + } else { + LOG_WARNING("Device responds empty firmware version string."); } memset(caps, 0, JAYLINK_DEV_EXT_CAPS_SIZE); @@ -506,7 +677,7 @@ static int jlink_init(void) } } - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) { ret = jaylink_get_hardware_version(devh, &hwver); @@ -522,7 +693,7 @@ static int jlink_init(void) LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor); if (hwver.major >= 5) - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; } if (iface == JAYLINK_TIF_SWD) { @@ -565,7 +736,7 @@ static int jlink_init(void) conn.handle = 0; conn.pid = 0; - conn.hid = 0; + strcpy(conn.hid, "0.0.0.0"); conn.iid = 0; conn.cid = 0; @@ -597,10 +768,10 @@ static int jlink_init(void) * if the first tap move is not divisible by 8, so we send a TLR on * first power up. */ - for (i = 0; i < 8; i++) - jlink_tap_append_step(1, 0); + uint8_t tms = 0xff; + jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 8); - jlink_tap_execute(); + jlink_flush(); } return ERROR_OK; @@ -609,6 +780,7 @@ static int jlink_init(void) static int jlink_quit(void) { int ret; + size_t count; if (trace_enabled) { ret = jaylink_swo_stop(devh); @@ -619,9 +791,9 @@ static int jlink_quit(void) } if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) { - ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL); + ret = jaylink_unregister(devh, &conn, connlist, &count); - if (ret < 0) + if (ret != JAYLINK_OK) LOG_ERROR("jaylink_unregister() failed: %s.", jaylink_strerror_name(ret)); } @@ -648,18 +820,13 @@ static void jlink_end_state(tap_state_t state) /* Goes to the end state. */ static void jlink_state_move(void) { - int i; - int tms = 0; uint8_t tms_scan; uint8_t tms_scan_bits; tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state()); tms_scan_bits = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - for (i = 0; i < tms_scan_bits; i++) { - tms = (tms_scan >> i) & 1; - jlink_tap_append_step(tms, 0); - } + jlink_clock_data(NULL, 0, &tms_scan, 0, NULL, 0, tms_scan_bits); tap_set_state(tap_get_end_state()); } @@ -667,12 +834,13 @@ static void jlink_state_move(void) static void jlink_path_move(int num_states, tap_state_t *path) { int i; + uint8_t tms = 0xff; for (i = 0; i < num_states; i++) { if (path[i] == tap_state_transition(tap_get_state(), false)) - jlink_tap_append_step(0, 0); + jlink_clock_data(NULL, 0, NULL, 0, NULL, 0, 1); else if (path[i] == tap_state_transition(tap_get_state(), true)) - jlink_tap_append_step(1, 0); + jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1); else { LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition.", tap_state_name(tap_get_state()), tap_state_name(path[i])); @@ -685,13 +853,19 @@ static void jlink_path_move(int num_states, tap_state_t *path) tap_set_end_state(tap_get_state()); } -static void jlink_runtest(int num_cycles) +static void jlink_stableclocks(int num_cycles) { int i; - tap_state_t saved_end_state = tap_get_end_state(); + uint8_t tms = tap_get_state() == TAP_RESET; + /* Execute num_cycles. */ + for (i = 0; i < num_cycles; i++) + jlink_clock_data(NULL, 0, &tms, 0, NULL, 0, 1); +} - jlink_tap_ensure_space(1, num_cycles + 16); +static void jlink_runtest(int num_cycles) +{ + tap_state_t saved_end_state = tap_get_end_state(); /* Only do a state_move when we're not already in IDLE. */ if (tap_get_state() != TAP_IDLE) { @@ -700,9 +874,7 @@ static void jlink_runtest(int num_cycles) /* num_cycles--; */ } - /* Execute num_cycles. */ - for (i = 0; i < num_cycles; i++) - jlink_tap_append_step(0, 0); + jlink_stableclocks(num_cycles); /* Finish in end_state. */ jlink_end_state(saved_end_state); @@ -711,36 +883,6 @@ static void jlink_runtest(int num_cycles) jlink_state_move(); } -static void jlink_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, - int scan_size, struct scan_command *command) -{ - tap_state_t saved_end_state; - - jlink_tap_ensure_space(1, scan_size + 16); - - saved_end_state = tap_get_end_state(); - - /* Move to appropriate scan state. */ - jlink_end_state(ir_scan ? TAP_IRSHIFT : TAP_DRSHIFT); - - /* Only move if we're not already there. */ - if (tap_get_state() != tap_get_end_state()) - jlink_state_move(); - - jlink_end_state(saved_end_state); - - /* Scan. */ - jlink_tap_append_scan(scan_size, buffer, command); - - /* We are in Exit1, go to Pause. */ - jlink_tap_append_step(0, 0); - - tap_set_state(ir_scan ? TAP_IRPAUSE : TAP_DRPAUSE); - - if (tap_get_state() != tap_get_end_state()) - jlink_state_move(); -} - static void jlink_reset(int trst, int srst) { LOG_DEBUG("TRST: %i, SRST: %i.", trst, srst); @@ -761,21 +903,25 @@ static void jlink_reset(int trst, int srst) COMMAND_HANDLER(jlink_usb_command) { + int tmp; + if (CMD_ARGC != 1) { command_print(CMD_CTX, "Need exactly one argument for jlink usb."); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(CMD_ARGV[0], "%" SCNd8, &usb_address) != 1) { + if (sscanf(CMD_ARGV[0], "%i", &tmp) != 1) { command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]); return ERROR_FAIL; } - if (usb_address > JAYLINK_USB_ADDRESS_3) { + if (tmp < JAYLINK_USB_ADDRESS_0 || tmp > JAYLINK_USB_ADDRESS_3) { command_print(CMD_CTX, "Invalid USB address: %s.", CMD_ARGV[0]); return ERROR_FAIL; } + usb_address = tmp; + use_serial_number = false; use_usb_address = true; @@ -784,14 +930,22 @@ COMMAND_HANDLER(jlink_usb_command) COMMAND_HANDLER(jlink_serial_command) { + int ret; + if (CMD_ARGC != 1) { command_print(CMD_CTX, "Need exactly one argument for jlink serial."); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) { + ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number); + + if (ret == JAYLINK_ERR) { command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]); return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; } use_serial_number = true; @@ -857,10 +1011,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) if (!CMD_ARGC) { switch (jtag_command_version) { - case JAYLINK_JTAG_V2: + case JAYLINK_JTAG_VERSION_2: version = 2; break; - case JAYLINK_JTAG_V3: + case JAYLINK_JTAG_VERSION_3: version = 3; break; default: @@ -876,10 +1030,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) switch (tmp) { case 2: - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; break; case 3: - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; break; default: command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); @@ -1062,15 +1216,17 @@ static uint32_t calculate_trace_buffer_size(void) return tmp & 0xffffff00; } -static bool check_trace_freq(uint32_t freq, uint32_t divider, uint32_t trace_freq) +static bool check_trace_freq(struct jaylink_swo_speed speed, + uint32_t trace_freq) { double min; double deviation; + uint32_t divider; - min = fabs(1.0 - (freq / ((double)trace_freq * divider))); + min = fabs(1.0 - (speed.freq / ((double)trace_freq * speed.min_div))); - while (freq / divider > 0) { - deviation = fabs(1.0 - (freq / ((double)trace_freq * divider))); + for (divider = speed.min_div; divider < speed.max_div; divider++) { + deviation = fabs(1.0 - (speed.freq / ((double)trace_freq * divider))); if (deviation < 0.03) { LOG_DEBUG("Found suitable frequency divider %u with deviation of " @@ -1080,8 +1236,6 @@ static bool check_trace_freq(uint32_t freq, uint32_t divider, uint32_t trace_fre if (deviation < min) min = deviation; - - divider++; } LOG_ERROR("Selected trace frequency is not supported by the device. " @@ -1097,8 +1251,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, { int ret; uint32_t buffer_size; - uint32_t freq; - uint32_t divider; + struct jaylink_swo_speed speed; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SWO)) { LOG_ERROR("Trace capturing is not supported by the device."); @@ -1137,7 +1290,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, return ERROR_FAIL; } - ret = jaylink_swo_get_speeds(devh, JAYLINK_SWO_MODE_UART, &freq, ÷r); + ret = jaylink_swo_get_speeds(devh, JAYLINK_SWO_MODE_UART, &speed); if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_swo_get_speeds() failed: %s.", @@ -1146,9 +1299,9 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, } if (!*trace_freq) - *trace_freq = freq / divider; + *trace_freq = speed.freq / speed.min_div; - if (!check_trace_freq(freq, divider, *trace_freq)) + if (!check_trace_freq(speed, *trace_freq)) return ERROR_FAIL; LOG_DEBUG("Using %u bytes device memory for trace capturing.", buffer_size); @@ -1452,6 +1605,125 @@ COMMAND_HANDLER(jlink_handle_config_command) return ERROR_OK; } +COMMAND_HANDLER(jlink_handle_emucom_write_command) +{ + int ret; + size_t tmp; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t dummy; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + + tmp = strlen(CMD_ARGV[1]); + + if (tmp % 2 != 0) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + buf = malloc(tmp / 2); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + dummy = unhexify(buf, CMD_ARGV[1], tmp / 2); + + if (dummy != (tmp / 2)) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + free(buf); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + length = tmp / 2; + ret = jaylink_emucom_write(devh, channel, buf, &length); + + free(buf); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel not supported by the device."); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to write to channel: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; + } + + if (length != (tmp / 2)) + LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length); + + return ERROR_OK; +} + +COMMAND_HANDLER(jlink_handle_emucom_read_command) +{ + int ret; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t tmp; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + + buf = malloc(length * 3 + 1); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + ret = jaylink_emucom_read(devh, channel, buf, &length); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel is not supported by the device."); + free(buf); + return ERROR_FAIL; + } else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) { + LOG_ERROR("Channel is not available for the requested amount of data. " + "%" PRIu32 " bytes are avilable.", length); + free(buf); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to read from channel: %s.", + jaylink_strerror_name(ret)); + free(buf); + return ERROR_FAIL; + } + + tmp = hexify((char *)buf + length, buf, length, 2 * length + 1); + + if (tmp != 2 * length) { + LOG_ERROR("Failed to convert data into hexadecimal string."); + free(buf); + return ERROR_FAIL; + } + + command_print(CMD_CTX, "%s", buf + length); + free(buf); + + return ERROR_OK; +} + static const struct command_registration jlink_config_subcommand_handlers[] = { { .name = "usb", @@ -1497,6 +1769,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration jlink_emucom_subcommand_handlers[] = { + { + .name = "write", + .handler = &jlink_handle_emucom_write_command, + .mode = COMMAND_EXEC, + .help = "write to a channel", + .usage = " ", + }, + { + .name = "read", + .handler = &jlink_handle_emucom_read_command, + .mode = COMMAND_EXEC, + .help = "read from a channel", + .usage = " " + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration jlink_subcommand_handlers[] = { { .name = "jtag", @@ -1546,6 +1836,12 @@ static const struct command_registration jlink_subcommand_handlers[] = { "this will show the device configuration", .chain = jlink_config_subcommand_handlers, }, + { + .name = "emucom", + .mode = COMMAND_EXEC, + .help = "access EMUCOM channel", + .chain = jlink_emucom_subcommand_handlers + }, COMMAND_REGISTRATION_DONE }; @@ -1596,10 +1892,14 @@ static uint8_t tdi_buffer[JLINK_TAP_BUFFER_SIZE]; static uint8_t tdo_buffer[JLINK_TAP_BUFFER_SIZE]; struct pending_scan_result { - int first; /* First bit position in tdo_buffer to read. */ - int length; /* Number of bits to read. */ - struct scan_command *command; /* Corresponding scan command. */ + /** First bit position in tdo_buffer to read. */ + unsigned first; + /** Number of bits to read. */ + unsigned length; + /** Location to store the result */ void *buffer; + /** Offset in the destination buffer */ + unsigned buffer_offset; }; #define MAX_PENDING_SCAN_RESULTS 256 @@ -1611,69 +1911,53 @@ static void jlink_tap_init(void) { tap_length = 0; pending_scan_results_length = 0; + memset(tms_buffer, 0, sizeof(tms_buffer)); + memset(tdi_buffer, 0, sizeof(tdi_buffer)); } -static void jlink_tap_ensure_space(int scans, int bits) -{ - int available_scans = MAX_PENDING_SCAN_RESULTS - pending_scan_results_length; - int available_bits = JLINK_TAP_BUFFER_SIZE * 8 - tap_length - 32; - - if (scans > available_scans || bits > available_bits) - jlink_tap_execute(); -} - -static void jlink_tap_append_step(int tms, int tdi) +static void jlink_clock_data(const uint8_t *out, unsigned out_offset, + const uint8_t *tms_out, unsigned tms_offset, + uint8_t *in, unsigned in_offset, + unsigned length) { - int index_var = tap_length / 8; - - assert(index_var < JLINK_TAP_BUFFER_SIZE); - - int bit_index = tap_length % 8; - uint8_t bit = 1 << bit_index; - - /* We do not pad TMS, so be sure to initialize all bits. */ - if (0 == bit_index) - tms_buffer[index_var] = tdi_buffer[index_var] = 0; - - if (tms) - tms_buffer[index_var] |= bit; - else - tms_buffer[index_var] &= ~bit; - - if (tdi) - tdi_buffer[index_var] |= bit; - else - tdi_buffer[index_var] &= ~bit; + do { + unsigned available_length = JLINK_TAP_BUFFER_SIZE - tap_length / 8; + + if (!available_length || + (in && pending_scan_results_length == MAX_PENDING_SCAN_RESULTS)) { + if (jlink_flush() != ERROR_OK) + return; + available_length = JLINK_TAP_BUFFER_SIZE; + } - tap_length++; -} + struct pending_scan_result *pending_scan_result = + &pending_scan_results_buffer[pending_scan_results_length]; -static void jlink_tap_append_scan(int length, uint8_t *buffer, - struct scan_command *command) -{ - struct pending_scan_result *pending_scan_result = - &pending_scan_results_buffer[pending_scan_results_length]; - int i; + unsigned scan_length = length > available_length ? + available_length : length; - pending_scan_result->first = tap_length; - pending_scan_result->length = length; - pending_scan_result->command = command; - pending_scan_result->buffer = buffer; + if (out) + buf_set_buf(out, out_offset, tdi_buffer, tap_length, scan_length); + if (tms_out) + buf_set_buf(tms_out, tms_offset, tms_buffer, tap_length, scan_length); - for (i = 0; i < length; i++) { - int tms = (i < (length - 1)) ? 0 : 1; - int tdi = (buffer[i / 8] & (1 << (i % 8))) != 0; - jlink_tap_append_step(tms, tdi); - } + if (in) { + pending_scan_result->first = tap_length; + pending_scan_result->length = scan_length; + pending_scan_result->buffer = in; + pending_scan_result->buffer_offset = in_offset; + pending_scan_results_length++; + } - pending_scan_results_length++; + tap_length += scan_length; + out_offset += scan_length; + tms_offset += scan_length; + in_offset += scan_length; + length -= scan_length; + } while (length > 0); } -/* - * Pad and send a tap sequence to the device, and receive the answer. For the - * purpose of padding we assume that we are in idle or pause state. - */ -static int jlink_tap_execute(void) +static int jlink_flush(void) { int i; int ret; @@ -1684,9 +1968,6 @@ static int jlink_tap_execute(void) jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer, tap_length, jlink_last_state); - jlink_last_state = jtag_debug_state_machine(tms_buffer, tdi_buffer, - tap_length, jlink_last_state); - ret = jaylink_jtag_io(devh, tms_buffer, tdi_buffer, tdo_buffer, tap_length, jtag_command_version); @@ -1697,24 +1978,12 @@ static int jlink_tap_execute(void) } for (i = 0; i < pending_scan_results_length; i++) { - struct pending_scan_result *pending_scan_result = &pending_scan_results_buffer[i]; - uint8_t *buffer = pending_scan_result->buffer; - int length = pending_scan_result->length; - int first = pending_scan_result->first; - struct scan_command *command = pending_scan_result->command; - - /* Copy to buffer. */ - buf_set_buf(tdo_buffer, first, buffer, 0, length); + struct pending_scan_result *p = &pending_scan_results_buffer[i]; - DEBUG_JTAG_IO("Pending scan result, length = %d.", length); - - if (jtag_read_buffer(buffer, command) != ERROR_OK) { - jlink_tap_init(); - return ERROR_JTAG_QUEUE_FAILED; - } + buf_set_buf(tdo_buffer, p->first, p->buffer, + p->buffer_offset, p->length); - if (pending_scan_result->buffer != NULL) - free(pending_scan_result->buffer); + DEBUG_JTAG_IO("Pending scan result, length = %d.", p->length); } jlink_tap_init(); diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 7c42220d6..746e14751 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -16,6 +16,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H @@ -316,7 +318,11 @@ static int jtag_vpi_runtest(int cycles, tap_state_t state) if (retval != ERROR_OK) return retval; +#if BUILD_RISCV == 1 + retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT); +#else retval = jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT); +#endif if (retval != ERROR_OK) return retval; diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c index 5b1248d26..1825543e2 100644 --- a/src/jtag/drivers/libusb0_common.c +++ b/src/jtag/drivers/libusb0_common.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -148,7 +146,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct usb_interface *iface = udev->config->interface; @@ -159,7 +157,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, for (int i = 0; i < desc->bNumEndpoints; i++) { if ((bclass > 0 && desc->bInterfaceClass != bclass) || (subclass > 0 && desc->bInterfaceSubClass != subclass) || - (protocol > 0 && desc->bInterfaceProtocol != protocol)) + (protocol > 0 && desc->bInterfaceProtocol != protocol) || + (trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type)) continue; uint8_t epnum = desc->endpoint[i].bEndpointAddress; diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h index ca372a080..baa9e3c5a 100644 --- a/src/jtag/drivers/libusb0_common.h +++ b/src/jtag/drivers/libusb0_common.h @@ -14,13 +14,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_LIBUSB_COMMON_H -#define JTAG_LIBUSB_COMMON_H +#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H +#define OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H #include @@ -69,7 +67,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); -#endif /* JTAG_USB_COMMON_H */ +#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */ diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index bda91ffbc..89f809271 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -189,7 +187,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); const struct libusb_interface *inter; @@ -212,6 +210,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, continue; epdesc = &interdesc->endpoint[k]; + if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type) + continue; uint8_t epnum = epdesc->bEndpointAddress; bool is_input = epnum & 0x80; diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h index 4ef6bf730..7c73d29a4 100644 --- a/src/jtag/drivers/libusb1_common.h +++ b/src/jtag/drivers/libusb1_common.h @@ -14,13 +14,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_LIBUSB_COMMON_H -#define JTAG_LIBUSB_COMMON_H +#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H +#define OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H #include @@ -71,12 +69,13 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, * @param bclass `bInterfaceClass` to match, or -1 to ignore this field. * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. + * @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field. * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. */ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); -#endif /* JTAG_USB_COMMON_H */ +#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */ diff --git a/src/jtag/drivers/libusb_common.h b/src/jtag/drivers/libusb_common.h index bad6c8cc9..599a0a9b0 100644 --- a/src/jtag/drivers/libusb_common.h +++ b/src/jtag/drivers/libusb_common.h @@ -12,13 +12,16 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H +#define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H + #ifdef HAVE_LIBUSB1 -#include +#include "libusb1_common.h" #else -#include +#include "libusb0_common.h" #endif + +#endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */ diff --git a/src/jtag/drivers/minidriver_imp.h b/src/jtag/drivers/minidriver_imp.h index b81368bd6..cd59a74fb 100644 --- a/src/jtag/drivers/minidriver_imp.h +++ b/src/jtag/drivers/minidriver_imp.h @@ -14,12 +14,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MINIDRIVER_IMP_H -#define MINIDRIVER_IMP_H + +#ifndef OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H +#define OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H #include @@ -39,4 +38,4 @@ void jtag_add_callback4(jtag_callback_t f, jtag_callback_data_t data0, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3); -#endif /* MINIDRIVER_IMP_H */ +#endif /* OPENOCD_JTAG_DRIVERS_MINIDRIVER_IMP_H */ diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index d9f73a2a7..924c97450 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -104,12 +102,67 @@ static bool string_descriptor_equal(libusb_device_handle *device, uint8_t str_in return strncmp(string, desc_string, sizeof(desc_string)) == 0; } +static bool device_location_equal(libusb_device *device, const char *location) +{ + bool result = false; +#ifdef HAVE_LIBUSB_GET_PORT_NUMBERS + char *loc = strdup(location); + uint8_t port_path[7]; + int path_step, path_len; + uint8_t dev_bus = libusb_get_bus_number(device); + char *ptr; + + path_len = libusb_get_port_numbers(device, port_path, 7); + if (path_len == LIBUSB_ERROR_OVERFLOW) { + LOG_ERROR("cannot determine path to usb device! (more than 7 ports in path)"); + goto done; + } + + LOG_DEBUG("device path has %i steps", path_len); + + ptr = strtok(loc, ":"); + if (ptr == NULL) { + LOG_DEBUG("no ':' in path"); + goto done; + } + if (atoi(ptr) != dev_bus) { + LOG_DEBUG("bus mismatch"); + goto done; + } + + path_step = 0; + while (path_step < 7) { + ptr = strtok(NULL, ","); + if (ptr == NULL) { + LOG_DEBUG("no more tokens in path at step %i", path_step); + break; + } + + if (path_step < path_len + && atoi(ptr) != port_path[path_step]) { + LOG_DEBUG("path mismatch at step %i", path_step); + break; + } + + path_step++; + }; + + /* walked the full path, all elements match */ + if (path_step == path_len) + result = true; + + done: + free(loc); +#endif + return result; +} + /* Helper to open a libusb device that matches vid, pid, product string and/or serial string. * Set any field to 0 as a wildcard. If the device is found true is returned, with ctx containing * the already opened handle. ctx->interface must be set to the desired interface (channel) number * prior to calling this function. */ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, const uint16_t *pid, - const char *product, const char *serial) + const char *product, const char *serial, const char *location) { libusb_device **list; struct libusb_device_descriptor desc; @@ -141,6 +194,11 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con continue; } + if (location && !device_location_equal(device, location)) { + libusb_close(ctx->usb_dev); + continue; + } + if (product && !string_descriptor_equal(ctx->usb_dev, desc.iProduct, product)) { libusb_close(ctx->usb_dev); continue; @@ -189,8 +247,8 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface); if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_NOT_SUPPORTED) { - LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err)); - goto error; + LOG_WARNING("libusb_detach_kernel_driver() failed with %s, trying to continue anyway", + libusb_error_name(err)); } err = libusb_claim_interface(ctx->usb_dev, ctx->interface); @@ -263,7 +321,7 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con } struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, - const char *serial, int channel) + const char *serial, const char *location, int channel) { struct mpsse_ctx *ctx = calloc(1, sizeof(*ctx)); int err; @@ -292,16 +350,17 @@ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const cha goto error; } - if (!open_matching_device(ctx, vid, pid, description, serial)) { + if (!open_matching_device(ctx, vid, pid, description, serial, location)) { /* Four hex digits plus terminating zero each */ char vidstr[5]; char pidstr[5]; - LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s' and " - "serial '%s'", + LOG_ERROR("unable to open ftdi device with vid %s, pid %s, description '%s', " + "serial '%s' at bus location '%s'", vid ? sprintf(vidstr, "%04x", *vid), vidstr : "*", pid ? sprintf(pidstr, "%04x", *pid), pidstr : "*", description ? description : "*", - serial ? serial : "*"); + serial ? serial : "*", + location ? location : "*"); ctx->usb_dev = 0; goto error; } @@ -813,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx) libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer, ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout); retval = libusb_submit_transfer(write_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; if (ctx->read_count) { read_transfer = libusb_alloc_transfer(0); @@ -820,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx) ctx->read_chunk_size, read_cb, &read_result, ctx->usb_read_timeout); retval = libusb_submit_transfer(read_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; } /* Polling loop, more or less taken from libftdi */ while (!write_result.done || !read_result.done) { - retval = libusb_handle_events(ctx->usb_ctx); + struct timeval timeout_usb; + + timeout_usb.tv_sec = 1; + timeout_usb.tv_usec = 0; + + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL); keep_alive(); - if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) { + if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED) + break; + + if (retval != LIBUSB_SUCCESS) { libusb_cancel_transfer(write_transfer); if (read_transfer) libusb_cancel_transfer(read_transfer); - while (!write_result.done || !read_result.done) - if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS) + while (!write_result.done || !read_result.done) { + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, + &timeout_usb, NULL); + if (retval != LIBUSB_SUCCESS) break; + } } } +error_check: if (retval != LIBUSB_SUCCESS) { LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval)); retval = ERROR_FAIL; diff --git a/src/jtag/drivers/mpsse.h b/src/jtag/drivers/mpsse.h index 3e287f75a..651eef940 100644 --- a/src/jtag/drivers/mpsse.h +++ b/src/jtag/drivers/mpsse.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MPSSE_H_ -#define MPSSE_H_ +#ifndef OPENOCD_JTAG_DRIVERS_MPSSE_H +#define OPENOCD_JTAG_DRIVERS_MPSSE_H #include #include "helper/binarybuffer.h" @@ -43,7 +41,7 @@ struct mpsse_ctx; /* Device handling */ struct mpsse_ctx *mpsse_open(const uint16_t *vid, const uint16_t *pid, const char *description, - const char *serial, int channel); + const char *serial, const char *location, int channel); void mpsse_close(struct mpsse_ctx *ctx); bool mpsse_is_high_speed(struct mpsse_ctx *ctx); @@ -77,4 +75,4 @@ int mpsse_set_frequency(struct mpsse_ctx *ctx, int frequency); int mpsse_flush(struct mpsse_ctx *ctx); void mpsse_purge(struct mpsse_ctx *ctx); -#endif /* MPSSE_H_ */ +#endif /* OPENOCD_JTAG_DRIVERS_MPSSE_H */ diff --git a/src/jtag/drivers/opendous.c b/src/jtag/drivers/opendous.c index deb6c7a80..458df34a7 100644 --- a/src/jtag/drivers/opendous.c +++ b/src/jtag/drivers/opendous.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 85d17938e..8f11b4ba1 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -2,6 +2,10 @@ * Driver for OpenJTAG Project (www.openjtag.org) * * Compatible with libftdi and ftd2xx drivers. * * * + * Cypress CY7C65215 support * + * Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV * + * * + * * * Copyright (C) 2010 by Ivan Meleca * * * * Copyright (C) 2013 by Ryan Corbin, GlueLogix Inc. * @@ -26,13 +30,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /*************************************************************************** - * Version 1.0 Tested on a MCBSTM32 board using a Cortex M3 (stm32f103x), * + * Version 1.0 Tested on a MCBSTM32 board using a Cortex-M3 (stm32f103x), * * GDB and Eclipse under Linux (Ubuntu 10.04) * * * ***************************************************************************/ @@ -43,7 +45,18 @@ #include #include -#include "usb_common.h" +#include "libusb_common.h" + +static enum { + OPENJTAG_VARIANT_STANDARD, + OPENJTAG_VARIANT_CY7C65215, +} openjtag_variant = OPENJTAG_VARIANT_STANDARD; + +static const char * const openjtag_variant_names[] = { + "standard", + "cy7c65215", + NULL +}; /* * OpenJTAG-OpenOCD state conversion @@ -68,19 +81,8 @@ typedef enum openjtag_tap_state { OPENJTAG_TAP_UPDATE_IR = 15, } openjtag_tap_state_t; -#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1) -#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI " - "are mutually exclusive" -#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1) -#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen" -#endif - /* OPENJTAG access library includes */ -#if BUILD_OPENJTAG_FTD2XX == 1 -#include -#elif BUILD_OPENJTAG_LIBFTDI == 1 #include -#endif /* OpenJTAG vid/pid */ static uint16_t openjtag_vid = 0x0403; @@ -88,12 +90,7 @@ static uint16_t openjtag_pid = 0x6001; static char *openjtag_device_desc; -#if BUILD_OPENJTAG_FTD2XX == 1 -static FT_HANDLE ftdih; - -#elif BUILD_OPENJTAG_LIBFTDI == 1 static struct ftdi_context ftdic; -#endif #define OPENJTAG_BUFFER_SIZE 504 #define OPENJTAG_MAX_PENDING_RESULTS 256 @@ -114,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE]; static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS]; static int openjtag_scan_result_count; -/* Openocd usb handler */ -struct openocd { - struct usb_dev_handle *usb_handle; -}; +static jtag_libusb_device_handle *usbh; + +/* CY7C65215 model only */ +#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */ +#define CY7C65215_JTAG_ENABLE 0xD0 /* bRequest: enable JTAG */ +#define CY7C65215_JTAG_DISABLE 0xD1 /* bRequest: disable JTAG */ +#define CY7C65215_JTAG_READ 0xD2 /* bRequest: read buffer */ +#define CY7C65215_JTAG_WRITE 0xD3 /* bRequest: write buffer */ + +#define CY7C65215_USB_TIMEOUT 100 + +static const uint16_t cy7c65215_vids[] = {0x04b4, 0}; +static const uint16_t cy7c65215_pids[] = {0x0007, 0}; + +#define CY7C65215_JTAG_CLASS 0xff +#define CY7C65215_JTAG_SUBCLASS 0x04 + +static unsigned int ep_in, ep_out; #ifdef _DEBUG_USB_COMMS_ @@ -203,26 +214,9 @@ static int8_t openjtag_get_tap_state(int8_t state) } } -static int openjtag_buf_write( +static int openjtag_buf_write_standard( uint8_t *buf, int size, uint32_t *bytes_written) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written; - -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); -#endif - - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); @@ -238,36 +232,56 @@ static int openjtag_buf_write( *bytes_written += retval; return ERROR_OK; -#endif } -static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +static int openjtag_buf_write_cy7c65215( + uint8_t *buf, int size, uint32_t *bytes_written) { + int ret; -#if BUILD_OPENJTAG_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 50; +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); +#endif - *bytes_read = 0; - while (qty && (*bytes_read < qty) && timeout--) { + if (size == 0) { + *bytes_written = 0; + return ERROR_OK; + } - status = FT_Read(ftdih, buf + *bytes_read, - qty - *bytes_read, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_WRITE, size, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; } -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); -#endif + ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk write failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_written = ret; return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 +} + +static int openjtag_buf_write( + uint8_t *buf, int size, uint32_t *bytes_written) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_write_cy7c65215(buf, size, bytes_written); + default: + return openjtag_buf_write_standard(buf, size, bytes_written); + } +} + +static int openjtag_buf_read_standard( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + int retval; int timeout = 5; @@ -289,10 +303,53 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif + return ERROR_OK; +} + +static int openjtag_buf_read_cy7c65215( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + int ret; + + if (qty == 0) { + *bytes_read = 0; + goto out; + } + + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_READ, qty, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + + ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk read failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read = ret; + +out: +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif + return ERROR_OK; } +static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_read_cy7c65215(buf, qty, bytes_read); + default: + return openjtag_buf_read_standard(buf, qty, bytes_read); + } +} + static int openjtag_sendcommand(uint8_t cmd) { uint32_t written; @@ -337,109 +394,17 @@ static int openjtag_speed(int speed) return ERROR_OK; } -static int openjtag_init(void) +static int openjtag_init_standard(void) { uint8_t latency_timer; -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; -#endif - -usb_tx_buf_offs = 0; -usb_rx_buf_len = 0; -openjtag_scan_result_count = 0; - -#if BUILD_OPENJTAG_FTD2XX == 1 - LOG_DEBUG("'openjtag' interface using FTD2XX"); -#elif BUILD_OPENJTAG_LIBFTDI == 1 - LOG_DEBUG("'openjtag' interface using libftdi"); -#endif - -/* Open by device description */ -if (openjtag_device_desc == NULL) { - LOG_WARNING("no openjtag device description specified, " + /* Open by device description */ + if (openjtag_device_desc == NULL) { + LOG_WARNING("no openjtag device description specified, " "using default 'Open JTAG Project'"); - openjtag_device_desc = "Open JTAG Project"; -} - -#if BUILD_OPENJTAG_FTD2XX == 1 - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(openjtag_vid, openjtag_pid); - if (status != FT_OK) { - LOG_WARNING("couldn't add %4.4x:%4.4x", - openjtag_vid, openjtag_pid); + openjtag_device_desc = "Open JTAG Project"; } -#endif - status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION, - &ftdih); - if (status != FT_OK) { - DWORD num_devices; - - LOG_ERROR("unable to open ftdi device: %u", status); - status = FT_ListDevices(&num_devices, NULL, - FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = malloc(sizeof(char *) - * (num_devices + 1)); - unsigned int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, - FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %u\n", num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } else { - LOG_ERROR("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(ftdih, 2); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(ftdih, &latency_timer); - if (status != FT_OK) { - LOG_ERROR("unable to get latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetBitMode(ftdih, 0x00, 0x40); - if (status != FT_OK) { - LOG_ERROR("unable to disable bit i/o mode: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetTimeouts(ftdih, 50, 0); - if (status != FT_OK) { - LOG_ERROR("unable to set timeouts: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) { - LOG_ERROR("unable to FT_Purge() %u", status); - return ERROR_JTAG_INIT_FAILED; - } - -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; @@ -471,41 +436,110 @@ if (openjtag_device_desc == NULL) { LOG_ERROR("Can't set baud rate to max: %s", ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; - }; -#endif + } -#if BUILD_OPENJTAG_FTD2XX == 1 - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) - return ERROR_JTAG_INIT_FAILED; -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_usb_purge_buffers(&ftdic) < 0) { LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } -#endif - /* OpenJTAG speed */ - openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ + return ERROR_OK; +} + +static int openjtag_init_cy7c65215(void) +{ + int ret; + + usbh = NULL; + ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh); + if (ret != ERROR_OK) { + LOG_ERROR("unable to open cy7c65215 device"); + goto err; + } + + ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out, + CY7C65215_JTAG_CLASS, + CY7C65215_JTAG_SUBCLASS, -1, LIBUSB_TRANSFER_TYPE_BULK); + if (ret != ERROR_OK) { + LOG_ERROR("unable to claim JTAG interface"); + goto err; + } - /* MSB */ - openjtag_sendcommand(0x75); + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_ENABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("could not enable JTAG module"); + goto err; + } return ERROR_OK; + +err: + if (usbh != NULL) + jtag_libusb_close(usbh); + return ERROR_JTAG_INIT_FAILED; } -static int openjtag_quit(void) +static int openjtag_init(void) +{ + int ret; + + usb_tx_buf_offs = 0; + usb_rx_buf_len = 0; + openjtag_scan_result_count = 0; + + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + ret = openjtag_init_cy7c65215(); + break; + default: + ret = openjtag_init_standard(); + } + if (ret != ERROR_OK) + return ret; + + openjtag_speed(375); /* Start at slowest adapter speed */ + openjtag_sendcommand(0x75); /* MSB */ + + return ERROR_OK; +} + +static int openjtag_quit_standard(void) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_Close(ftdih); -#elif BUILD_OPENJTAG_LIBFTDI == 1 ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); -#endif return ERROR_OK; } +static int openjtag_quit_cy7c65215(void) +{ + int ret; + + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_DISABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) + LOG_WARNING("could not disable JTAG module"); + + jtag_libusb_close(usbh); + + return ERROR_OK; +} + +static int openjtag_quit(void) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_quit_cy7c65215(); + default: + return openjtag_quit_standard(); + } +} + static void openjtag_write_tap_buffer(void) { uint32_t written; @@ -538,8 +572,8 @@ static int openjtag_execute_tap_queue(void) uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer; - while (len) { - if (len <= 8) { + while (len > 0) { + if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) { DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X", usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len)); buffer[count] = usb_rx_buf[rx_offs] >> (8 - len); @@ -726,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd) if (cmd->cmd.runtest->num_cycles > 16) LOG_WARNING("num_cycles > 16 on run test"); - uint8_t command; - command = 7; - command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; + if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 || + cmd->cmd.runtest->num_cycles) { + uint8_t command; + command = 7; + command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; - openjtag_add_byte(command); + openjtag_add_byte(command); + } tap_set_end_state(end_state); if (tap_get_end_state() != tap_get_state()) { @@ -818,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command) return ERROR_OK; } +COMMAND_HANDLER(openjtag_handle_variant_command) +{ + if (CMD_ARGC == 1) { + const char * const *name = openjtag_variant_names; + int variant = 0; + for (; *name; name++, variant++) { + if (strcasecmp(CMD_ARGV[0], *name) == 0) { + openjtag_variant = variant; + return ERROR_OK; + } + } + LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]); + } else { + LOG_ERROR("require exactly one argument to " + "openjtag_variant "); + } + return ERROR_OK; +} static const struct command_registration openjtag_command_handlers[] = { { @@ -827,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = { .help = "set the USB device description of the OpenJTAG", .usage = "description-string", }, + { + .name = "openjtag_variant", + .handler = openjtag_handle_variant_command, + .mode = COMMAND_CONFIG, + .help = "set the OpenJTAG variant", + .usage = "variant-string", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/drivers/osbdm.c b/src/jtag/drivers/osbdm.c index d1eeedb33..5db36a122 100644 --- a/src/jtag/drivers/osbdm.c +++ b/src/jtag/drivers/osbdm.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" diff --git a/src/jtag/drivers/parport.c b/src/jtag/drivers/parport.c index ff7585951..c9e331644 100644 --- a/src/jtag/drivers/parport.c +++ b/src/jtag/drivers/parport.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c index 45e434a14..49caa679f 100644 --- a/src/jtag/drivers/presto.c +++ b/src/jtag/drivers/presto.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** @@ -36,14 +34,7 @@ #include "bitq.h" /* PRESTO access library includes */ -#if BUILD_PRESTO_FTD2XX == 1 -#include -#include "ftd2xx_common.h" -#elif BUILD_PRESTO_LIBFTDI == 1 #include -#else -#error "BUG: either FTD2XX and LIBFTDI has to be used" -#endif /* -------------------------------------------------------------------------- */ @@ -57,13 +48,8 @@ #define BUFFER_SIZE (64*62) struct presto { -#if BUILD_PRESTO_FTD2XX == 1 - FT_HANDLE handle; - FT_STATUS status; -#elif BUILD_PRESTO_LIBFTDI == 1 struct ftdi_context ftdic; int retval; -#endif char serial[FT_DEVICE_SERNUM_LEN]; @@ -97,15 +83,6 @@ static uint8_t presto_init_seq[] = { static int presto_write(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Write(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes; presto->retval = ftdi_write_data(&presto->ftdic, buf, size); if (presto->retval < 0) { @@ -113,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size) return ERROR_JTAG_DEVICE_ERROR; } ftbytes = presto->retval; -#endif if (ftbytes != size) { LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", @@ -126,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size) static int presto_read(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Read(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes = 0; struct timeval timeout, now; @@ -154,7 +121,6 @@ static int presto_read(uint8_t *buf, uint32_t size) ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) break; } -#endif if (ftbytes != size) { /* this is just a warning, there might have been timeout when detecting PRESTO, @@ -167,150 +133,6 @@ static int presto_read(uint8_t *buf, uint32_t size) return ERROR_OK; } -#if BUILD_PRESTO_FTD2XX == 1 -static int presto_open_ftd2xx(char *req_serial) -{ - uint32_t i; - DWORD numdevs; - DWORD vidpid; - char devname[FT_DEVICE_NAME_LEN]; - FT_DEVICE device; - - BYTE presto_data; - DWORD ftbytes; - - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID); - if (presto->status != FT_OK) { - LOG_ERROR("couldn't add PRESTO VID/PID"); - exit(-1); - } -#endif - - presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY); - if (presto->status != FT_OK) { - LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs); - for (i = 0; i < numdevs; i++) { - presto->status = FT_Open(i, &(presto->handle)); - if (presto->status != FT_OK) { - /* this is not fatal, the device may be legitimately open by other process, - *hence debug message only */ - LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status)); - continue; - } - LOG_DEBUG("FTDI device %i open", (int)i); - - presto->status = FT_GetDeviceInfo(presto->handle, &device, - &vidpid, presto->serial, devname, NULL); - if (presto->status == FT_OK) { - if (vidpid == PRESTO_VID_PID && (req_serial == NULL || - !strcmp(presto->serial, req_serial))) - break; - } else - LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string( - presto->status)); - - LOG_DEBUG("FTDI device %i does not match, closing", (int)i); - FT_Close(presto->handle); - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - } - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */ - - presto->status = FT_SetLatencyTimer(presto->handle, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetTimeouts(presto->handle, 100, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary - * under Linux for unknown reason, - * probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO reset"); - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBitMode(presto->handle, 0x80, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBaudRate(presto->handle, 9600); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0; - for (i = 0; i < 4 * 62; i++) { - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - } - usleep(100000); - - presto->status = FT_SetBitMode(presto->handle, 0x00, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason, - probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO not responding"); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - presto->status = FT_SetTimeouts(presto->handle, 0, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, &presto_init_seq, - sizeof(presto_init_seq), &ftbytes); - - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - return ERROR_JTAG_DEVICE_ERROR; - - return ERROR_OK; -} - -#elif BUILD_PRESTO_LIBFTDI == 1 static int presto_open_libftdi(char *req_serial) { uint8_t presto_data; @@ -373,7 +195,6 @@ static int presto_open_libftdi(char *req_serial) return ERROR_OK; } -#endif /* BUILD_PRESTO_LIBFTDI == 1 */ static int presto_open(char *req_serial) { @@ -393,11 +214,7 @@ static int presto_open(char *req_serial) presto->jtag_speed = 0; -#if BUILD_PRESTO_FTD2XX == 1 - return presto_open_ftd2xx(req_serial); -#elif BUILD_PRESTO_LIBFTDI == 1 return presto_open_libftdi(req_serial); -#endif } static int presto_close(void) @@ -405,35 +222,6 @@ static int presto_close(void) int result = ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return result; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, - &presto_init_seq, - sizeof(presto_init_seq), - &ftbytes); - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetLatencyTimer(presto->handle, 16); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Close(presto->handle); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - else - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#elif BUILD_PRESTO_LIBFTDI == 1 - presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq)); if (presto->retval != sizeof(presto_init_seq)) result = ERROR_JTAG_DEVICE_ERROR; @@ -447,7 +235,6 @@ static int presto_close(void) result = ERROR_JTAG_DEVICE_ERROR; else ftdi_deinit(&presto->ftdic); -#endif return result; } @@ -457,11 +244,7 @@ static int presto_flush(void) if (presto->buff_out_pos == 0) return ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->status != FT_OK) { -#elif BUILD_PRESTO_LIBFTDI == 1 if (presto->retval < 0) { -#endif LOG_DEBUG("error in previous communication, canceling I/O operation"); return ERROR_JTAG_DEVICE_ERROR; } @@ -504,13 +287,9 @@ static int presto_sendbyte(int data) } else return ERROR_JTAG_DEVICE_ERROR; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->buff_out_pos >= BUFFER_SIZE) -#elif BUILD_PRESTO_LIBFTDI == 1 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 *bytes only!) */ if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128) -#endif return presto_flush(); return ERROR_OK; diff --git a/src/jtag/drivers/remote_bitbang.c b/src/jtag/drivers/remote_bitbang.c index a1c11b244..b898e957d 100644 --- a/src/jtag/drivers/remote_bitbang.c +++ b/src/jtag/drivers/remote_bitbang.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -133,7 +131,7 @@ static int remote_bitbang_init_tcp(void) { struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM }; struct addrinfo *result, *rp; - int fd; + int fd = 0; LOG_INFO("Connecting to %s:%s", remote_bitbang_host ? remote_bitbang_host : "localhost", diff --git a/src/jtag/drivers/rlink.c b/src/jtag/drivers/rlink.c index 3587a9d53..3f9e33268 100644 --- a/src/jtag/drivers/rlink.c +++ b/src/jtag/drivers/rlink.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/rlink.h b/src/jtag/drivers/rlink.h index 8f09f8ce6..74b62580c 100644 --- a/src/jtag/drivers/rlink.h +++ b/src/jtag/drivers/rlink.h @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_RLINK_H +#define OPENOCD_JTAG_DRIVERS_RLINK_H + struct rlink_speed_table { uint8_t const *dtc; uint16_t dtc_size; @@ -27,3 +28,5 @@ struct rlink_speed_table { extern const struct rlink_speed_table rlink_speed_table[]; extern const size_t rlink_speed_table_size; + +#endif /* OPENOCD_JTAG_DRIVERS_RLINK_H */ diff --git a/src/jtag/drivers/rlink_call.m4 b/src/jtag/drivers/rlink_call.m4 index 13e0fc2d2..b27f39238 100644 --- a/src/jtag/drivers/rlink_call.m4 +++ b/src/jtag/drivers/rlink_call.m4 @@ -14,9 +14,7 @@ m4_divert(`-1') * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ m4_dnl Setup and hold times depend on SHIFTER_PRESCALER diff --git a/src/jtag/drivers/rlink_dtc_cmd.h b/src/jtag/drivers/rlink_dtc_cmd.h index faf41ce5f..ff9e8b25f 100644 --- a/src/jtag/drivers/rlink_dtc_cmd.h +++ b/src/jtag/drivers/rlink_dtc_cmd.h @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H +#define OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H + /* A command position with the high nybble of 0x0 is reserved for an error condition. * If executed, it stops the DTC and raises the ERROR flag */ @@ -71,3 +72,5 @@ /* A shared status byte is updated with bit 0 set when this has happened, * and it is cleared when a new command buffer becomes ready. * The host can poll that byte to see when it is safe to read a reply. */ + +#endif /* OPENOCD_JTAG_DRIVERS_RLINK_DTC_CMD_H */ diff --git a/src/jtag/drivers/rlink_ep1_cmd.h b/src/jtag/drivers/rlink_ep1_cmd.h index 00b19eee6..3f9f2b381 100644 --- a/src/jtag/drivers/rlink_ep1_cmd.h +++ b/src/jtag/drivers/rlink_ep1_cmd.h @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H +#define OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H + /* * Command opcodes that can be sent over endpoint 1. * This codifies information provided by Rob Brown . @@ -55,3 +56,5 @@ #define EP1_CMD_MEMORY_WRITE (0x29) #define EP1_CMD_GET_FWREV (0xfe) #define EP1_CMD_GET_SERIAL (0xff) + +#endif /* OPENOCD_JTAG_DRIVERS_RLINK_EP1_CMD_H */ diff --git a/src/jtag/drivers/rlink_init.m4 b/src/jtag/drivers/rlink_init.m4 index b13400462..8ad2f51d8 100644 --- a/src/jtag/drivers/rlink_init.m4 +++ b/src/jtag/drivers/rlink_init.m4 @@ -14,9 +14,7 @@ m4_divert(`-1') * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ m4_undefine(`CTRL_MPEG_L') diff --git a/src/jtag/drivers/rlink_st7.h b/src/jtag/drivers/rlink_st7.h index a30acb470..3d573e72c 100644 --- a/src/jtag/drivers/rlink_st7.h +++ b/src/jtag/drivers/rlink_st7.h @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_RLINK_ST7_H +#define OPENOCD_JTAG_DRIVERS_RLINK_ST7_H + #define ST7_FOSC (12 * 1000000) /* This is not a complete enumeration of ST7 registers, but it is sufficient for this interface driver. */ @@ -112,3 +113,5 @@ #define ST7_PF5 (1 << 5) #define ST7_PF6 (1 << 6) #define ST7_PF7 (1 << 7) + +#endif /* OPENOCD_JTAG_DRIVERS_RLINK_ST7_H */ diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index a4847abd6..0bdcd316b 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -18,9 +18,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -135,9 +133,19 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_ERR_OK 0x80 #define STLINK_DEBUG_ERR_FAULT 0x81 #define STLINK_SWD_AP_WAIT 0x10 +#define STLINK_SWD_AP_FAULT 0x11 +#define STLINK_SWD_AP_ERROR 0x12 +#define STLINK_SWD_AP_PARITY_ERROR 0x13 #define STLINK_JTAG_WRITE_ERROR 0x0c #define STLINK_JTAG_WRITE_VERIF_ERROR 0x0d #define STLINK_SWD_DP_WAIT 0x14 +#define STLINK_SWD_DP_FAULT 0x15 +#define STLINK_SWD_DP_ERROR 0x16 +#define STLINK_SWD_DP_PARITY_ERROR 0x17 + +#define STLINK_SWD_AP_WDATA_ERROR 0x18 +#define STLINK_SWD_AP_STICKY_ERROR 0x19 +#define STLINK_SWD_AP_STICKYORUN_ERROR 0x1a #define STLINK_CORE_RUNNING 0x80 #define STLINK_CORE_HALTED 0x81 @@ -208,7 +216,7 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 -#define STLINK_TRACE_SIZE 1024 +#define STLINK_TRACE_SIZE 4096 #define STLINK_TRACE_MAX_HZ 2000000 #define STLINK_TRACE_MIN_VERSION 13 @@ -398,6 +406,38 @@ static int stlink_usb_error_check(void *handle) case STLINK_JTAG_WRITE_VERIF_ERROR: LOG_DEBUG("Verify error"); return ERROR_FAIL; + case STLINK_SWD_AP_FAULT: + /* git://git.ac6.fr/openocd commit 657e3e885b9ee10 + * returns ERROR_OK with the comment: + * Change in error status when reading outside RAM. + * This fix allows CDT plugin to visualize memory. + */ + LOG_DEBUG("STLINK_SWD_AP_FAULT"); + return ERROR_FAIL; + case STLINK_SWD_AP_ERROR: + LOG_DEBUG("STLINK_SWD_AP_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_AP_PARITY_ERROR: + LOG_DEBUG("STLINK_SWD_AP_PARITY_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_DP_FAULT: + LOG_DEBUG("STLINK_SWD_DP_FAULT"); + return ERROR_FAIL; + case STLINK_SWD_DP_ERROR: + LOG_DEBUG("STLINK_SWD_DP_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_DP_PARITY_ERROR: + LOG_DEBUG("STLINK_SWD_DP_PARITY_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_AP_WDATA_ERROR: + LOG_DEBUG("STLINK_SWD_AP_WDATA_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_AP_STICKY_ERROR: + LOG_DEBUG("STLINK_SWD_AP_STICKY_ERROR"); + return ERROR_FAIL; + case STLINK_SWD_AP_STICKYORUN_ERROR: + LOG_DEBUG("STLINK_SWD_AP_STICKYORUN_ERROR"); + return ERROR_FAIL; default: LOG_DEBUG("unknown/unexpected STLINK status code 0x%x", h->databuf[0]); return ERROR_FAIL; @@ -1122,7 +1162,7 @@ static int stlink_usb_step(void *handle) if (h->jtag_api == STLINK_JTAG_API_V2) { /* TODO: this emulates the v1 api, it should really use a similar auto mask isr - * that the cortex-m3 currently does. */ + * that the Cortex-M3 currently does. */ stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_MASKINTS|C_DEBUGEN); stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_MASKINTS|C_DEBUGEN); return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index fd613c2d4..77b727c27 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* 2014-12: Addition of the SWD protocol support is based on the initial work diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index ac4566232..171ac66c4 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -244,7 +242,8 @@ static int icdi_send_remote_cmd(void *handle, const char *data) struct icdi_usb_handle_s *h = handle; size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); - cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len); + cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data, + strlen(data), h->max_packet - cmd_len); return icdi_send_packet(handle, cmd_len); } @@ -268,7 +267,7 @@ static int icdi_get_cmd_result(void *handle) if (h->read_buffer[offset] == 'E') { /* get error code */ - char result; + uint8_t result; if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1) return ERROR_FAIL; return result; @@ -330,7 +329,7 @@ static int icdi_usb_version(void *handle) } /* convert reply */ - if (unhexify(version, h->read_buffer + 2, 4) != 4) { + if (unhexify((uint8_t *)version, h->read_buffer + 2, 4) != 4) { LOG_WARNING("unable to get ICDI version"); return ERROR_OK; } @@ -497,7 +496,7 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) /* convert result */ uint8_t buf[4]; - if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) { + if (unhexify(buf, h->read_buffer + 2, 4) != 4) { LOG_ERROR("failed to convert result"); return ERROR_FAIL; } @@ -514,7 +513,7 @@ static int icdi_usb_write_reg(void *handle, int num, uint32_t val) h_u32_to_le(buf, val); int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); - hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd)); + hexify(cmd + cmd_len, buf, 4, sizeof(cmd)); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index cfd693a60..550df1c93 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -193,6 +191,7 @@ int ulink_execute_queued_commands(struct ulink *device, int timeout); const char *ulink_cmd_id_string(uint8_t id); void ulink_print_command(struct ulink_cmd *ulink_cmd); void ulink_print_queue(struct ulink *device); +static int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f); #endif int ulink_append_scan_cmd(struct ulink *device, @@ -225,7 +224,6 @@ int ulink_append_test_cmd(struct ulink *device); /* OpenULINK TCK frequency helper functions */ int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay); -int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f); /* Interface between OpenULINK and OpenOCD */ static void ulink_set_end_state(tap_state_t endstate); @@ -1369,6 +1367,7 @@ int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay) return ERROR_OK; } +#ifdef _DEBUG_JTAG_IO_ /** * Calculate frequency for a given delay value. * @@ -1383,7 +1382,7 @@ int ulink_calculate_delay(enum ulink_delay_type type, long f, int *delay) * @return on success: ERROR_OK * @return on failure: ERROR_FAIL */ -int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f) +static int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f) { float t, f_float, f_rounded; @@ -1432,6 +1431,7 @@ int ulink_calculate_frequency(enum ulink_delay_type type, int delay, long *f) return ERROR_OK; } +#endif /******************* Interface between OpenULINK and OpenOCD ******************/ @@ -2066,7 +2066,7 @@ static int ulink_khz(int khz, int *jtag_speed) } #ifdef _DEBUG_JTAG_IO_ - long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io; + long f_tck = 0, f_tms = 0, f_scan_in = 0, f_scan_out = 0, f_scan_io = 0; ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck, &f_tck); diff --git a/src/jtag/drivers/usb_blaster/Makefile.am b/src/jtag/drivers/usb_blaster/Makefile.am index 0fb470051..a6694c543 100644 --- a/src/jtag/drivers/usb_blaster/Makefile.am +++ b/src/jtag/drivers/usb_blaster/Makefile.am @@ -1,24 +1,13 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdusbblaster.la +%C%_libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) +%C%_libocdusbblaster_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) +USB_BLASTER_SRC = %D%/usb_blaster.c %D%/ublast_access.h -noinst_LTLIBRARIES = libocdusbblaster.la -libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) - -USB_BLASTER_SRC = usb_blaster.c - -if USB_BLASTER_LIBFTDI -USB_BLASTER_SRC += ublast_access_ftdi.c -endif - -if USB_BLASTER_FTD2XX -USB_BLASTER_SRC += ublast_access_ftd2xx.c +if USB_BLASTER +USB_BLASTER_SRC += %D%/ublast_access_ftdi.c endif if USB_BLASTER_2 -USB_BLASTER_SRC += ublast2_access_libusb.c +USB_BLASTER_SRC += %D%/ublast2_access_libusb.c endif - -noinst_HEADERS = ublast_access.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index ac863918c..d99173369 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -13,6 +13,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index 5bdc2573a..252f003a9 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -20,10 +20,13 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ -#ifndef JTAG_UBLAST_ACCESS_H -#define JTAG_UBLAST_ACCESS_H +#ifndef OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H +#define OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H #include @@ -53,19 +56,16 @@ struct ublast_lowlevel { /** * ublast_register_ftdi - get a lowlevel USB Blaster driver - * ublast_register_ftd2xx - get a lowlevel USB Blaster driver * ublast2_register_libusb - get a lowlevel USB Blaster II driver * - * Get a lowlevel USB-Blaster driver. In the current implementation, there are 3 + * Get a lowlevel USB-Blaster driver. In the current implementation, there are 2 * possible lowlevel drivers : - * - one based on libftdi from ftdichip.com - * - one based on libftdxx, the free alternative + * - one based on libftdi, * - one based on libusb, specific to the USB-Blaster II * * Returns the lowlevel driver structure. */ extern struct ublast_lowlevel *ublast_register_ftdi(void); -extern struct ublast_lowlevel *ublast_register_ftd2xx(void); extern struct ublast_lowlevel *ublast2_register_libusb(void); -#endif /* JTAG_UBLAST_ACCESS_H */ +#endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */ diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c index 2527fe9a6..cb442f2b5 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c +++ b/src/jtag/drivers/usb_blaster/ublast_access_ftdi.c @@ -19,6 +19,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 82e5537f5..a975bd1e2 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -20,6 +20,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * */ /* @@ -144,12 +147,9 @@ struct drvs_map { }; static struct drvs_map lowlevel_drivers_map[] = { -#if BUILD_USB_BLASTER_LIBFTDI +#if BUILD_USB_BLASTER { .name = "ftdi", .drv_register = ublast_register_ftdi }, #endif -#if BUILD_USB_BLASTER_FTD2XX - { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx }, -#endif #if BUILD_USB_BLASTER_2 { .name = "ublast2", .drv_register = ublast2_register_libusb }, #endif @@ -1045,8 +1045,8 @@ static const struct command_registration ublast_command_handlers[] = { .name = "usb_blaster_lowlevel_driver", .handler = ublast_handle_lowlevel_drv_command, .mode = COMMAND_CONFIG, - .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)", - .usage = "(ftdi|ftd2xx|ublast2)", + .help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)", + .usage = "(ftdi|ublast2)", }, { .name = "usb_blaster_pin", diff --git a/src/jtag/drivers/usb_common.c b/src/jtag/drivers/usb_common.c index 4f6a72296..54be6a624 100644 --- a/src/jtag/drivers/usb_common.c +++ b/src/jtag/drivers/usb_common.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/usb_common.h b/src/jtag/drivers/usb_common.h index d34c20b9b..4d2bd2686 100644 --- a/src/jtag/drivers/usb_common.h +++ b/src/jtag/drivers/usb_common.h @@ -12,17 +12,15 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_USB_COMMON_H -#define JTAG_USB_COMMON_H +#ifndef OPENOCD_JTAG_DRIVERS_USB_COMMON_H +#define OPENOCD_JTAG_DRIVERS_USB_COMMON_H #include int jtag_usb_open(const uint16_t vids[], const uint16_t pids[], struct usb_dev_handle **out); -#endif /* JTAG_USB_COMMON_H */ +#endif /* OPENOCD_JTAG_DRIVERS_USB_COMMON_H */ diff --git a/src/jtag/drivers/usbprog.c b/src/jtag/drivers/usbprog.c index 156edf022..d81c329d4 100644 --- a/src/jtag/drivers/usbprog.c +++ b/src/jtag/drivers/usbprog.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c index c3a09a2ae..0d60725a6 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtogpio.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c index c8684a77a..f2ea175ad 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtojtagraw.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c index a0dfb996e..16433aff5 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtopwr.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c index cd9d51c03..ef1b675f7 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoswd.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c index 65e54e4e6..53a7e989b 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h index fa53062bd..98a056a8b 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __USBTOXXX_H_INCLUDED__ -#define __USBTOXXX_H_INCLUDED__ +#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H +#define OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H RESULT usbtoxxx_init(void); RESULT usbtoxxx_fini(void); @@ -236,4 +234,4 @@ RESULT usbtopwm_config(uint8_t interface_index, uint16_t kHz, uint8_t mode); RESULT usbtopwm_out(uint8_t interface_index, uint16_t count, uint16_t *rate); RESULT usbtopwm_in(uint8_t interface_index, uint16_t count, uint16_t *rate); -#endif /* __USBTOXXX_H_INCLUDED__ */ +#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_H */ diff --git a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h index 4d8dfcf8a..e40667e91 100644 --- a/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h +++ b/src/jtag/drivers/versaloon/usbtoxxx/usbtoxxx_internal.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __USBTOXXX_INTERNAL_H_INCLUDED__ -#define __USBTOXXX_INTERNAL_H_INCLUDED__ +#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H +#define OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H /* USB_TO_XXX USB Commands */ /* Page0 */ @@ -160,4 +158,4 @@ RESULT usbtoxxx_add_command(uint8_t type, uint8_t cmd, uint8_t *cmdbuf, /* USB_TO_GPIO */ #define USB_TO_GPIO_DIR_MSK 0x01 -#endif /* __USBTOXXX_INTERNAL_H_INCLUDED__ */ +#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_USBTOXXX_USBTOXXX_INTERNAL_H */ diff --git a/src/jtag/drivers/versaloon/versaloon.c b/src/jtag/drivers/versaloon/versaloon.c index 04d73cf38..146383961 100644 --- a/src/jtag/drivers/versaloon/versaloon.c +++ b/src/jtag/drivers/versaloon/versaloon.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/drivers/versaloon/versaloon.h b/src/jtag/drivers/versaloon/versaloon.h index 46f5c3191..9d92bcaa1 100644 --- a/src/jtag/drivers/versaloon/versaloon.h +++ b/src/jtag/drivers/versaloon/versaloon.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __VERSALOON_H_INCLUDED__ -#define __VERSALOON_H_INCLUDED__ +#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H +#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H #include @@ -111,5 +109,4 @@ struct versaloon_interface_t { extern struct versaloon_interface_t versaloon_interface; extern libusb_device_handle *versaloon_usb_device_handle; -#endif /* __VERSALOON_H_INCLUDED__ */ - +#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_H */ diff --git a/src/jtag/drivers/versaloon/versaloon_include.h b/src/jtag/drivers/versaloon/versaloon_include.h index 2eb374a7e..089056d02 100644 --- a/src/jtag/drivers/versaloon/versaloon_include.h +++ b/src/jtag/drivers/versaloon/versaloon_include.h @@ -12,11 +12,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H +#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H + /* This file is used to include different header and macros */ /* according to different platform */ #include @@ -97,3 +98,5 @@ #define SET_LE_U32(p, v) SET_U32_LSBFIRST(p, v) #define SET_BE_U16(p, v) SET_U16_MSBFIRST(p, v) #define SET_BE_U32(p, v) SET_U32_MSBFIRST(p, v) + +#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INCLUDE_H */ diff --git a/src/jtag/drivers/versaloon/versaloon_internal.h b/src/jtag/drivers/versaloon/versaloon_internal.h index 66712dba5..497b6b9ce 100644 --- a/src/jtag/drivers/versaloon/versaloon_internal.h +++ b/src/jtag/drivers/versaloon/versaloon_internal.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __VERSALOON_INTERNAL_H_INCLUDED__ -#define __VERSALOON_INTERNAL_H_INCLUDED__ +#ifndef OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H +#define OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H #define VERSALOON_PRODUCTSTRING_INDEX 2 #define VERSALOON_SERIALSTRING_INDEX 3 @@ -109,4 +107,4 @@ extern uint8_t *versaloon_buf; extern uint8_t *versaloon_cmd_buf; extern uint16_t versaloon_buf_size; -#endif /* __VERSALOON_INTERNAL_H_INCLUDED__ */ +#endif /* OPENOCD_JTAG_DRIVERS_VERSALOON_VERSALOON_INTERNAL_H */ diff --git a/src/jtag/drivers/vsllink.c b/src/jtag/drivers/vsllink.c index 801de650b..6f7e9cadf 100644 --- a/src/jtag/drivers/vsllink.c +++ b/src/jtag/drivers/vsllink.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* Versaloon is a programming tool for multiple MCUs. diff --git a/src/jtag/drivers/w_jtag_sj.c b/src/jtag/drivers/w_jtag_sj.c index 68c7cf43b..d1e43d564 100644 --- a/src/jtag/drivers/w_jtag_sj.c +++ b/src/jtag/drivers/w_jtag_sj.c @@ -389,7 +389,7 @@ static void wjtagsj_execute_stableclocks(struct jtag_command *cmd) /* 7 bits of either ones or zeros. */ uint8_t tms = tap_get_state() == TAP_RESET ? 0x7f : 0x00; - //Ö±½ÓÊä³ö + //Ö±\BD\D3\CA\E4\B3\F6 wjtagsj_clock_tms_cs_out(wjtagsj_ctx1,&tms, 0,num_cycles); @@ -535,11 +535,11 @@ static int wjtagsj_config_trace(bool enabled, enum tpio_pin_protocol pin_protoco return ERROR_FAIL; } - if(enabled) - if (pin_protocol != ASYNC_UART) { + if(enabled) { + if (pin_protocol != ASYNC_UART) { LOG_ERROR("Selected pin protocol is not supported."); return ERROR_FAIL; - + } if(*trace_freq > swo_max_freq) { LOG_ERROR("Frequency exceed the limit of max swo baudrate"); return ERROR_FAIL; @@ -584,7 +584,7 @@ static int wjtagsj_initialize(void) else LOG_DEBUG("interface using shortest path jtag state transitions"); - //³¢ÊÔ´ò¿ªµÚÒ»¸ö + //\B3\A2\CAÔ´ò¿ªµ\DAÒ»\B8\F6 for (int i = 0; wjtagsj_vid[i] || wjtagsj_pid[i]; i++) { wjtagsj_ctx1 = wjtagsj_open(&wjtagsj_vid[i], &wjtagsj_pid[i], wjtagsj_device_desc, wjtagsj_serial, wjtagsj_channel); diff --git a/src/jtag/hla/Makefile.am b/src/jtag/hla/Makefile.am index 4fbc70e9c..6bb2960eb 100644 --- a/src/jtag/hla/Makefile.am +++ b/src/jtag/hla/Makefile.am @@ -1,23 +1,11 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libocdhla.la - -libocdhla_la_SOURCES = \ - $(HLFILES) - -HLFILES = - -if HLADAPTER -HLFILES += hla_transport.c -HLFILES += hla_tcl.c -HLFILES += hla_interface.c -HLFILES += hla_layout.c -endif - -noinst_HEADERS = \ - hla_interface.h \ - hla_layout.h \ - hla_tcl.h \ - hla_transport.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdhla.la + +%C%_libocdhla_la_SOURCES = \ + %D%/hla_transport.c \ + %D%/hla_tcl.c \ + %D%/hla_interface.c \ + %D%/hla_layout.c \ + %D%/hla_transport.h \ + %D%/hla_interface.h \ + %D%/hla_layout.h \ + %D%/hla_tcl.h diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index a208e9fd0..9217631b0 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/hla/hla_interface.h b/src/jtag/hla/hla_interface.h index a15592572..0992d1cad 100644 --- a/src/jtag/hla/hla_interface.h +++ b/src/jtag/hla/hla_interface.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _HL_INTERFACE -#define _HL_INTERFACE +#ifndef OPENOCD_JTAG_HLA_HLA_INTERFACE_H +#define OPENOCD_JTAG_HLA_HLA_INTERFACE_H /** */ struct target; @@ -67,4 +65,4 @@ int hl_interface_init_target(struct target *t); int hl_interface_init_reset(void); int hl_interface_override_target(const char **targetname); -#endif /* _HL_INTERFACE */ +#endif /* OPENOCD_JTAG_HLA_HLA_INTERFACE_H */ diff --git a/src/jtag/hla/hla_layout.c b/src/jtag/hla/hla_layout.c index 0a20fbd36..c5e35182d 100644 --- a/src/jtag/hla/hla_layout.c +++ b/src/jtag/hla/hla_layout.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h index 8833d6c80..40c1321ba 100644 --- a/src/jtag/hla/hla_layout.h +++ b/src/jtag/hla/hla_layout.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _HL_LAYOUT_H -#define _HL_LAYOUT_H +#ifndef OPENOCD_JTAG_HLA_HLA_LAYOUT_H +#define OPENOCD_JTAG_HLA_HLA_LAYOUT_H #include @@ -127,4 +125,4 @@ const struct hl_layout *hl_layout_get_list(void); /** */ int hl_layout_init(struct hl_interface_s *adapter); -#endif /* _HL_LAYOUT_H */ +#endif /* OPENOCD_JTAG_HLA_HLA_LAYOUT_H */ diff --git a/src/jtag/hla/hla_tcl.c b/src/jtag/hla/hla_tcl.c index 20082f385..9378427b0 100644 --- a/src/jtag/hla/hla_tcl.c +++ b/src/jtag/hla/hla_tcl.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -100,11 +98,13 @@ static int jim_hl_newtap_cmd(Jim_GetOptInfo *goi) free(pTap); return JIM_ERR; } - Jim_GetOpt_String(goi, &cp, NULL); - pTap->chip = strdup(cp); - Jim_GetOpt_String(goi, &cp, NULL); - pTap->tapname = strdup(cp); + const char *tmp; + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->chip = strdup(tmp); + + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->tapname = strdup(tmp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; diff --git a/src/jtag/hla/hla_tcl.h b/src/jtag/hla/hla_tcl.h index 3ce3effab..ac00add51 100644 --- a/src/jtag/hla/hla_tcl.h +++ b/src/jtag/hla/hla_tcl.h @@ -16,15 +16,13 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _HL_TCL_ -#define _HL_TCL_ +#ifndef OPENOCD_JTAG_HLA_HLA_TCL_H +#define OPENOCD_JTAG_HLA_HLA_TCL_H /** */ int jim_hl_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv); -#endif /* _HL_TCL_ */ +#endif /* OPENOCD_JTAG_HLA_HLA_TCL_H */ diff --git a/src/jtag/hla/hla_transport.c b/src/jtag/hla/hla_transport.c index ae7cbb1ac..5a5671db6 100644 --- a/src/jtag/hla/hla_transport.c +++ b/src/jtag/hla/hla_transport.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/hla/hla_transport.h b/src/jtag/hla/hla_transport.h index 09eece282..07eb751e2 100644 --- a/src/jtag/hla/hla_transport.h +++ b/src/jtag/hla/hla_transport.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _HL_TRANSPORT -#define _HL_TRANSPORT +#ifndef OPENOCD_JTAG_HLA_HLA_TRANSPORT_H +#define OPENOCD_JTAG_HLA_HLA_TRANSPORT_H enum hl_transports { HL_TRANSPORT_UNKNOWN = 0, @@ -31,4 +29,4 @@ enum hl_transports { HL_TRANSPORT_SWIM }; -#endif /* _HL_TRANSPORT */ +#endif /* OPENOCD_JTAG_HLA_HLA_TRANSPORT_H */ diff --git a/src/jtag/interface.c b/src/jtag/interface.c index 19a0b052c..e12b2aebb 100644 --- a/src/jtag/interface.c +++ b/src/jtag/interface.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/interface.h b/src/jtag/interface.h index e7b20148e..cdfc676ee 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef OPENOCD_JTAG_INTERFACE_H diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 9a331485d..6960f4c29 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -53,19 +51,13 @@ extern struct jtag_interface parport_interface; #if BUILD_DUMMY == 1 extern struct jtag_interface dummy_interface; #endif -#if BUILD_FT2232_FTD2XX == 1 -extern struct jtag_interface ft2232_interface; -#endif -#if BUILD_FT2232_LIBFTDI == 1 -extern struct jtag_interface ft2232_interface; -#endif #if BUILD_FTDI == 1 extern struct jtag_interface ftdi_interface; #endif #if BUILD_W_JTAG_SJ == 1 extern struct jtag_interface w_jtag_sj_interface; #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1 extern struct jtag_interface usb_blaster_interface; #endif #if BUILD_JTAG_VPI == 1 @@ -83,7 +75,7 @@ extern struct jtag_interface at91rm9200_interface; #if BUILD_GW16012 == 1 extern struct jtag_interface gw16012_interface; #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO extern struct jtag_interface presto_interface; #endif #if BUILD_USBPROG == 1 @@ -134,6 +126,12 @@ extern struct jtag_interface bcm2835gpio_interface; #if BUILD_CMSIS_DAP == 1 extern struct jtag_interface cmsis_dap_interface; #endif +#if BUILD_KITPROG == 1 +extern struct jtag_interface kitprog_interface; +#endif +#if BUILD_IMX_GPIO == 1 +extern struct jtag_interface imx_gpio_interface; +#endif #endif /* standard drivers */ /** @@ -155,19 +153,13 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_DUMMY == 1 &dummy_interface, #endif -#if BUILD_FT2232_FTD2XX == 1 - &ft2232_interface, -#endif -#if BUILD_FT2232_LIBFTDI == 1 - &ft2232_interface, -#endif #if BUILD_FTDI == 1 &ftdi_interface, #endif #if BUILD_W_JTAG_SJ == 1 &w_jtag_sj_interface, #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1 &usb_blaster_interface, #endif #if BUILD_JTAG_VPI == 1 @@ -185,7 +177,7 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_GW16012 == 1 &gw16012_interface, #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO &presto_interface, #endif #if BUILD_USBPROG == 1 @@ -236,6 +228,12 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_CMSIS_DAP == 1 &cmsis_dap_interface, #endif +#if BUILD_KITPROG == 1 + &kitprog_interface, +#endif +#if BUILD_IMX_GPIO == 1 + &imx_gpio_interface, +#endif #endif /* standard drivers */ NULL, }; diff --git a/src/jtag/interfaces.h b/src/jtag/interfaces.h index e17420f53..02d201b1f 100644 --- a/src/jtag/interfaces.h +++ b/src/jtag/interfaces.h @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifndef OPENOCD_JTAG_INTERFACES_H diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index eda4ccdd5..7702d6ca8 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * +* along with this program. If not, see . * ***************************************************************************/ -#ifndef JTAG_H -#define JTAG_H +#ifndef OPENOCD_JTAG_JTAG_H +#define OPENOCD_JTAG_JTAG_H #include #include @@ -107,7 +105,7 @@ extern tap_state_t cmd_queue_cur_state; * jtag_add_dr_scan_check() to validate the value that was scanned out. */ struct scan_field { - /** The number of bits this field specifies (up to 32) */ + /** The number of bits this field specifies */ int num_bits; /** A pointer to value to be scanned into the device */ const uint8_t *out_value; @@ -648,4 +646,4 @@ bool transport_is_jtag(void); int jim_jtag_newtap(Jim_Interp *interp, int argc, Jim_Obj *const *argv); -#endif /* JTAG_H */ +#endif /* OPENOCD_JTAG_JTAG_H */ diff --git a/src/jtag/minidriver.h b/src/jtag/minidriver.h index 0de870926..688c39630 100644 --- a/src/jtag/minidriver.h +++ b/src/jtag/minidriver.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MINIDRIVER_H -#define MINIDRIVER_H +#ifndef OPENOCD_JTAG_MINIDRIVER_H +#define OPENOCD_JTAG_MINIDRIVER_H /** * @page jtagminidriver JTAG Mini-Driver @@ -89,4 +87,4 @@ int interface_jtag_execute_queue(void); */ int default_interface_jtag_execute_queue(void); -#endif /* MINIDRIVER_H */ +#endif /* OPENOCD_JTAG_MINIDRIVER_H */ diff --git a/src/jtag/minidriver/minidriver_imp.h b/src/jtag/minidriver/minidriver_imp.h index 8ad992c1d..11d0fae72 100644 --- a/src/jtag/minidriver/minidriver_imp.h +++ b/src/jtag/minidriver/minidriver_imp.h @@ -14,13 +14,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MINIDRIVER_IMP_H -#define MINIDRIVER_IMP_H +#ifndef OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H +#define OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H #include @@ -29,4 +27,4 @@ #define jtag_add_callback4(callback, in, data1, data2, data3) \ interface_jtag_add_callback4(callback, in, data1, data2, data3) -#endif /* MINIDRIVER_IMP_H */ +#endif /* OPENOCD_JTAG_MINIDRIVER_MINIDRIVER_IMP_H */ diff --git a/src/jtag/minidummy/jtag_minidriver.h b/src/jtag/minidummy/jtag_minidriver.h index 452fbc8bb..1708356a5 100644 --- a/src/jtag/minidummy/jtag_minidriver.h +++ b/src/jtag/minidummy/jtag_minidriver.h @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #define interface_jtag_add_callback(callback, in) callback(in) diff --git a/src/jtag/minidummy/minidummy.c b/src/jtag/minidummy/minidummy.c index 4f04acdeb..b7c989fc0 100644 --- a/src/jtag/minidummy/minidummy.c +++ b/src/jtag/minidummy/minidummy.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/jtag/swd.h b/src/jtag/swd.h index d208f393b..c888cc07d 100644 --- a/src/jtag/swd.h +++ b/src/jtag/swd.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef SWD_H -#define SWD_H +#ifndef OPENOCD_JTAG_SWD_H +#define OPENOCD_JTAG_SWD_H #include @@ -215,4 +213,4 @@ void swd_add_reset(int req_srst); bool transport_is_swd(void); -#endif /* SWD_H */ +#endif /* OPENOCD_JTAG_SWD_H */ diff --git a/src/jtag/tcl.c b/src/jtag/tcl.c index c916fb1ca..bc6bbf204 100644 --- a/src/jtag/tcl.c +++ b/src/jtag/tcl.c @@ -23,9 +23,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -533,11 +531,13 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi) free(pTap); return JIM_ERR; } - Jim_GetOpt_String(goi, &cp, NULL); - pTap->chip = strdup(cp); - Jim_GetOpt_String(goi, &cp, NULL); - pTap->tapname = strdup(cp); + const char *tmp; + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->chip = strdup(tmp); + + Jim_GetOpt_String(goi, &tmp, NULL); + pTap->tapname = strdup(tmp); /* name + dot + name + null */ x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1; @@ -1247,7 +1247,7 @@ COMMAND_HANDLER(handle_wait_srst_deassert) LOG_USER("Waiting for srst assert + deassert for at most %dms", timeout_ms); int asserted_yet; - long long then = timeval_ms(); + int64_t then = timeval_ms(); while (jtag_srst_asserted(&asserted_yet) == ERROR_OK) { if ((timeval_ms() - then) > timeout_ms) { LOG_ERROR("Timed out"); diff --git a/src/jtag/tcl.h b/src/jtag/tcl.h index 95dea13c0..932b47ac8 100644 --- a/src/jtag/tcl.h +++ b/src/jtag/tcl.h @@ -23,17 +23,15 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _JTAG_TCL_H_ -#define _JTAG_TCL_H_ +#ifndef OPENOCD_JTAG_TCL_H +#define OPENOCD_JTAG_TCL_H int jim_jtag_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv); int jim_jtag_tap_enabler(Jim_Interp *interp, int argc, Jim_Obj * const *argv); -#endif +#endif /* OPENOCD_JTAG_TCL_H */ diff --git a/src/jtag/zy1000/jtag_minidriver.h b/src/jtag/zy1000/jtag_minidriver.h index d7fa43761..7d1ede5d4 100644 --- a/src/jtag/zy1000/jtag_minidriver.h +++ b/src/jtag/zy1000/jtag_minidriver.h @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* used to test manual mode */ diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c index 16c3e5d0f..67d990700 100644 --- a/src/jtag/zy1000/zy1000.c +++ b/src/jtag/zy1000/zy1000.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* This file supports the zy1000 debugger: @@ -147,8 +145,8 @@ static int zy1000_power_dropout(int *dropout) static void waitSRST(bool asserted) { bool first = true; - long long start = 0; - long total = 0; + int64_t start = 0; + int64_t total = 0; const char *mode = asserted ? "assert" : "deassert"; for (;; ) { @@ -169,7 +167,7 @@ static void waitSRST(bool asserted) keep_alive(); if (total > 5000) { - LOG_ERROR("SRST took too long to %s: %dms", mode, (int)total); + LOG_ERROR("SRST took too long to %s: %" PRId64 "ms", mode, total); break; } } diff --git a/src/main.c b/src/main.c index f3ff51b66..83e60d8e0 100644 --- a/src/main.c +++ b/src/main.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/openocd.c b/src/openocd.c index 7d5cad171..1b72448a7 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -47,7 +45,10 @@ #include #endif -#define OPENOCD_BRANDING "" +// [GNU MCU Eclipse] +// Add --enable-branding='GNU MCU Eclipse' at build time +#if defined(BUILD_BRANDING) + #if INTPTR_MAX == INT32_MAX #define OPENOCD_WORDSIZE "32-bits " #elif INTPTR_MAX == INT64_MAX @@ -56,8 +57,25 @@ #define OPENOCD_WORDSIZE "" #endif -#define OPENOCD_VERSION OPENOCD_BRANDING OPENOCD_WORDSIZE \ +#ifdef PKGBLDDATE +#define OPENOCD_VERSION BUILD_BRANDING " " OPENOCD_WORDSIZE \ "Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")" +#else +#define OPENOCD_VERSION BUILD_BRANDING " " OPENOCD_WORDSIZE \ + "Open On-Chip Debugger " VERSION RELSTR +#endif + +#else + +#ifdef PKGBLDDATE +#define OPENOCD_VERSION \ + "Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")" +#else +#define OPENOCD_VERSION \ + "Open On-Chip Debugger " VERSION RELSTR +#endif + +#endif static const char openocd_startup_tcl[] = { #include "startup_tcl.inc" @@ -303,8 +321,10 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct if (init_at_startup) { ret = command_run_line(cmd_ctx, "init"); - if (ERROR_OK != ret) + if (ERROR_OK != ret) { + server_quit(); return ERROR_FAIL; + } } ret = server_loop(cmd_ctx); diff --git a/src/openocd.h b/src/openocd.h index 6d87c2af9..543ac3c23 100644 --- a/src/openocd.h +++ b/src/openocd.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef OPENOCD_H -#define OPENOCD_H +#ifndef OPENOCD_OPENOCD_H +#define OPENOCD_OPENOCD_H /** * Different applications can define this entry point to override @@ -31,4 +29,4 @@ */ int openocd_main(int argc, char *argv[]); -#endif +#endif /* OPENOCD_OPENOCD_H */ diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am index 93b79f4a1..7f3a55423 100644 --- a/src/pld/Makefile.am +++ b/src/pld/Makefile.am @@ -1,8 +1,8 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libpld.la -noinst_HEADERS = pld.h xilinx_bit.h virtex2.h -libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libpld.la +%C%_libpld_la_SOURCES = \ + %D%/pld.c \ + %D%/xilinx_bit.c \ + %D%/virtex2.c \ + %D%/pld.h \ + %D%/xilinx_bit.h \ + %D%/virtex2.h diff --git a/src/pld/pld.c b/src/pld/pld.c index fb5d32ed6..5210b97b7 100644 --- a/src/pld/pld.c +++ b/src/pld/pld.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/pld/pld.h b/src/pld/pld.h index c089fe635..3178fd459 100644 --- a/src/pld/pld.h +++ b/src/pld/pld.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef PLD_H -#define PLD_H +#ifndef OPENOCD_PLD_PLD_H +#define OPENOCD_PLD_PLD_H #include @@ -51,4 +49,4 @@ struct pld_device *get_pld_device_by_num(int num); #define ERROR_PLD_DEVICE_INVALID (-1000) #define ERROR_PLD_FILE_LOAD_FAILED (-1001) -#endif /* PLD_H */ +#endif /* OPENOCD_PLD_PLD_H */ diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index 82eb788f9..4e385e97b 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/pld/virtex2.h b/src/pld/virtex2.h index 8ed1c1c77..d6d922e79 100644 --- a/src/pld/virtex2.h +++ b/src/pld/virtex2.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef VIRTEX2_H -#define VIRTEX2_H +#ifndef OPENOCD_PLD_VIRTEX2_H +#define OPENOCD_PLD_VIRTEX2_H #include @@ -28,4 +26,4 @@ struct virtex2_pld_device { int no_jstart; }; -#endif /* VIRTEX2_H */ +#endif /* OPENOCD_PLD_VIRTEX2_H */ diff --git a/src/pld/xilinx_bit.c b/src/pld/xilinx_bit.c index cd414ba8a..a975a7a0c 100644 --- a/src/pld/xilinx_bit.c +++ b/src/pld/xilinx_bit.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/pld/xilinx_bit.h b/src/pld/xilinx_bit.h index d507dfcf8..1a35c3be2 100644 --- a/src/pld/xilinx_bit.h +++ b/src/pld/xilinx_bit.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef XILINX_BIT_H -#define XILINX_BIT_H +#ifndef OPENOCD_PLD_XILINX_BIT_H +#define OPENOCD_PLD_XILINX_BIT_H struct xilinx_bit_file { uint8_t unknown_header[13]; @@ -33,4 +31,4 @@ struct xilinx_bit_file { int xilinx_read_bit_file(struct xilinx_bit_file *bit_file, const char *filename); -#endif /* XILINX_BIT_H */ +#endif /* OPENOCD_PLD_XILINX_BIT_H */ diff --git a/src/rtos/ChibiOS.c b/src/rtos/ChibiOS.c index 84393860c..1bc1af8fc 100644 --- a/src/rtos/ChibiOS.c +++ b/src/rtos/ChibiOS.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -130,15 +128,13 @@ struct rtos_type ChibiOS_rtos = { enum ChibiOS_symbol_values { ChibiOS_VAL_rlist = 0, ChibiOS_VAL_ch = 1, - ChibiOS_VAL_ch_debug = 2, - ChibiOS_VAL_chSysInit = 3 + ChibiOS_VAL_ch_debug = 2 }; static symbol_table_elem_t ChibiOS_symbol_list[] = { { "rlist", 0, true}, /* Thread ready list */ { "ch", 0, true}, /* System data structure */ { "ch_debug", 0, false}, /* Memory Signature containing offsets of fields in rlist */ - { "chSysInit", 0, false}, /* Necessary part of API, used for ChibiOS detection */ { NULL, 0, false} }; @@ -226,7 +222,7 @@ static int ChibiOS_update_stacking(struct rtos *rtos) /* Sometimes the stacking can not be determined only by looking at the * target name but only a runtime. * - * For example, this is the case for cortex-m4 targets and ChibiOS which + * For example, this is the case for Cortex-M4 targets and ChibiOS which * only stack the FPU registers if it is enabled during ChibiOS build. * * Terminating which stacking is used is target depending. @@ -248,7 +244,7 @@ static int ChibiOS_update_stacking(struct rtos *rtos) struct ChibiOS_params *param; param = (struct ChibiOS_params *) rtos->rtos_specific_params; - /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4 */ + /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4 */ struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); if (is_armv7m(armv7m_target)) { if (armv7m_target->fp_feature == FPv4_SP) { @@ -361,7 +357,6 @@ static int ChibiOS_update_threads(struct rtos *rtos) sizeof(struct thread_detail)); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; - rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = malloc( sizeof(tmp_thread_extra_info)); @@ -445,14 +440,13 @@ static int ChibiOS_update_threads(struct rtos *rtos) if (threadState < CHIBIOS_NUM_STATES) state_desc = ChibiOS_thread_states[threadState]; else - state_desc = "Unknown state"; + state_desc = "Unknown"; curr_thrd_details->extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(curr_thrd_details->extra_info_str, state_desc); + state_desc)+8); + sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc); curr_thrd_details->exists = true; - curr_thrd_details->display_str = NULL; curr_thrd_details++; } @@ -520,12 +514,11 @@ static int ChibiOS_detect_rtos(struct target *target) { if ((target->rtos->symbols != NULL) && ((target->rtos->symbols[ChibiOS_VAL_rlist].address != 0) || - (target->rtos->symbols[ChibiOS_VAL_ch].address != 0)) && - (target->rtos->symbols[ChibiOS_VAL_chSysInit].address != 0)) { + (target->rtos->symbols[ChibiOS_VAL_ch].address != 0))) { if (target->rtos->symbols[ChibiOS_VAL_ch_debug].address == 0) { - LOG_INFO("It looks like the target is running ChibiOS without " - "ch_debug."); + LOG_INFO("It looks like the target may be running ChibiOS " + "without ch_debug."); return 0; } diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 1ce680724..83961eb95 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -30,6 +28,10 @@ #include "helper/log.h" #include "helper/types.h" #include "rtos_standard_stackings.h" +#include "target/armv7m.h" +#include "target/cortex_m.h" + + #define FREERTOS_MAX_PRIORITIES 63 @@ -45,7 +47,9 @@ struct FreeRTOS_params { const unsigned char list_elem_content_offset; const unsigned char thread_stack_offset; const unsigned char thread_name_offset; - const struct rtos_register_stacking *stacking_info; + const struct rtos_register_stacking *stacking_info_cm3; + const struct rtos_register_stacking *stacking_info_cm4f; + const struct rtos_register_stacking *stacking_info_cm4f_fpu; }; static const struct FreeRTOS_params FreeRTOS_params_list[] = { @@ -60,6 +64,8 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_Cortex_M3_stacking, /* stacking_info */ + &rtos_standard_Cortex_M4F_stacking, + &rtos_standard_Cortex_M4F_FPU_stacking, }, { "hla_target", /* target_name */ @@ -72,6 +78,8 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_Cortex_M3_stacking, /* stacking_info */ + &rtos_standard_Cortex_M4F_stacking, + &rtos_standard_Cortex_M4F_FPU_stacking, }, { "nds32_v3", /* target_name */ @@ -84,6 +92,8 @@ static const struct FreeRTOS_params FreeRTOS_params_list[] = { 0, /* thread_stack_offset; */ 52, /* thread_name_offset; */ &rtos_standard_NDS32_N1068_stacking, /* stacking_info */ + &rtos_standard_Cortex_M4F_stacking, + &rtos_standard_Cortex_M4F_FPU_stacking, }, }; @@ -211,7 +221,6 @@ static int FreeRTOS_update_threads(struct rtos *rtos) } rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; - rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); @@ -350,11 +359,10 @@ static int FreeRTOS_update_threads(struct rtos *rtos) rtos->thread_details[tasks_found].thread_name_str = malloc(strlen(tmp_str)+1); strcpy(rtos->thread_details[tasks_found].thread_name_str, tmp_str); - rtos->thread_details[tasks_found].display_str = NULL; rtos->thread_details[tasks_found].exists = true; if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) { - char running_str[] = "Running"; + char running_str[] = "State: Running"; rtos->thread_details[tasks_found].extra_info_str = malloc( sizeof(running_str)); strcpy(rtos->thread_details[tasks_found].extra_info_str, @@ -418,7 +426,45 @@ static int FreeRTOS_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, ch thread_id + param->thread_stack_offset, stack_ptr); - return rtos_generic_stack_read(rtos->target, param->stacking_info, stack_ptr, hex_reg_list); + /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */ + int cm4_fpu_enabled = 0; + struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); + if (is_armv7m(armv7m_target)) { + if (armv7m_target->fp_feature == FPv4_SP) { + /* Found ARM v7m target which includes a FPU */ + uint32_t cpacr; + + retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read CPACR register to check FPU state"); + return -1; + } + + /* Check if CP10 and CP11 are set to full access. */ + if (cpacr & 0x00F00000) { + /* Found target with enabled FPU */ + cm4_fpu_enabled = 1; + } + } + } + + if (cm4_fpu_enabled == 1) { + /* Read the LR to decide between stacking with or without FPU */ + uint32_t LR_svc = 0; + retval = target_read_buffer(rtos->target, + stack_ptr + 0x20, + param->pointer_width, + (uint8_t *)&LR_svc); + if (retval != ERROR_OK) { + LOG_OUTPUT("Error reading stack frame from FreeRTOS thread\r\n"); + return retval; + } + if ((LR_svc & 0x10) == 0) + return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f_fpu, stack_ptr, hex_reg_list); + else + return rtos_generic_stack_read(rtos->target, param->stacking_info_cm4f, stack_ptr, hex_reg_list); + } else + return rtos_generic_stack_read(rtos->target, param->stacking_info_cm3, stack_ptr, hex_reg_list); } static int FreeRTOS_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 62293ec66..27d9cd66a 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -1,34 +1,34 @@ -# *************************************************************************** -# * Copyright (C) 2011 by Broadcom Corporation * -# * Evan Hunter - ehunter@broadcom.com * -# * * -# * This program is free software; you can redistribute it and/or modify * -# * it under the terms of the GNU General Public License as published by * -# * the Free Software Foundation; either version 2 of the License, or * -# * (at your option) any later version. * -# * * -# * This program is distributed in the hope that it will be useful, * -# * but WITHOUT ANY WARRANTY; without even the implied warranty of * -# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -# * GNU General Public License for more details. * -# * * -# * You should have received a copy of the GNU General Public License * -# * along with this program; if not, write to the * -# * Free Software Foundation, Inc., * -# * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * -# *************************************************************************** +noinst_LTLIBRARIES += %D%/librtos.la +%C%_librtos_la_SOURCES = \ + %D%/rtos.c \ + %D%/rtos_standard_stackings.c \ + %D%/rtos_ecos_stackings.c \ + %D%/rtos_chibios_stackings.c \ + %D%/rtos_embkernel_stackings.c \ + %D%/rtos_mqx_stackings.c \ + %D%/rtos_ucos_iii_stackings.c \ + %D%/FreeRTOS.c \ + %D%/ThreadX.c \ + %D%/eCos.c \ + %D%/linux.c \ + %D%/ChibiOS.c \ + %D%/embKernel.c \ + %D%/mqx.c \ + %D%/uCOS-III.c \ + %D%/riscv_debug.c \ + %D%/rtos.h \ + %D%/rtos_standard_stackings.h \ + %D%/rtos_ecos_stackings.h \ + %D%/linux_header.h \ + %D%/rtos_chibios_stackings.h \ + %D%/rtos_embkernel_stackings.h \ + %D%/rtos_mqx_stackings.h \ + %D%/rtos_ucos_iii_stackings.h \ + %D%/riscv_debug.h -include $(top_srcdir)/common.mk +%C%_librtos_la_CFLAGS = $(AM_CFLAGS) -METASOURCES = AUTO -noinst_LTLIBRARIES = librtos.la -noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h -librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c - -librtos_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -librtos_la_CFLAGS += -Wno-sign-compare +%C%_librtos_la_CFLAGS += -Wno-sign-compare endif - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c index 16df7a4b7..ab8a66e93 100644 --- a/src/rtos/ThreadX.c +++ b/src/rtos/ThreadX.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -321,7 +319,6 @@ static int ThreadX_update_threads(struct rtos *rtos) sizeof(struct thread_detail) * thread_list_size); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; - rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); @@ -411,13 +408,11 @@ static int ThreadX_update_threads(struct rtos *rtos) state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); + state_desc)+8); + sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc); rtos->thread_details[tasks_found].exists = true; - rtos->thread_details[tasks_found].display_str = NULL; - tasks_found++; prev_thread_ptr = thread_ptr; @@ -598,8 +593,6 @@ static int ThreadX_get_thread_detail(struct rtos *rtos, detail->exists = true; - detail->display_str = NULL; - return 0; } diff --git a/src/rtos/eCos.c b/src/rtos/eCos.c index 746172d6c..edc3d8b51 100644 --- a/src/rtos/eCos.c +++ b/src/rtos/eCos.c @@ -11,9 +11,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -174,7 +172,6 @@ static int eCos_update_threads(struct rtos *rtos) sizeof(struct thread_detail) * thread_list_size); rtos->thread_details->threadid = 1; rtos->thread_details->exists = true; - rtos->thread_details->display_str = NULL; rtos->thread_details->extra_info_str = NULL; rtos->thread_details->thread_name_str = malloc(sizeof(tmp_str)); strcpy(rtos->thread_details->thread_name_str, tmp_str); @@ -264,13 +261,11 @@ static int eCos_update_threads(struct rtos *rtos) state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); + state_desc)+8); + sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc); rtos->thread_details[tasks_found].exists = true; - rtos->thread_details[tasks_found].display_str = NULL; - tasks_found++; prev_thread_ptr = thread_index; diff --git a/src/rtos/embKernel.c b/src/rtos/embKernel.c index a8b07c398..e515383ac 100644 --- a/src/rtos/embKernel.c +++ b/src/rtos/embKernel.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -145,7 +143,6 @@ static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, cons return retval; details->threadid = (threadid_t) task; details->exists = true; - details->display_str = NULL; int64_t name_ptr = 0; retval = target_read_buffer(rtos->target, task + param->thread_name_offset, param->pointer_width, @@ -171,11 +168,11 @@ static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, cons return retval; details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE); if (task == rtos->current_thread) { - snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running", + snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u", (unsigned int) priority); } else { - snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority, - state_str); + snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u", + state_str, (unsigned int) priority); } LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable, diff --git a/src/rtos/linux.c b/src/rtos/linux.c index c28236d37..3efaab133 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -107,11 +105,11 @@ static int linux_os_dummy_update(struct rtos *rtos) return 0; } -static int linux_compute_virt2phys(struct target *target, uint32_t address) +static int linux_compute_virt2phys(struct target *target, target_addr_t address) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; - uint32_t pa = 0; + target_addr_t pa = 0; int retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) { LOG_ERROR("Cannot compute linux virt2phys translation"); @@ -1215,7 +1213,7 @@ int linux_thread_extra_info(struct target *target, if (temp->threadid == threadid) { char *pid = " PID: "; char *pid_current = "*PID: "; - char *name = "NAME: "; + char *name = "Name: "; int str_size = strlen(pid) + strlen(name); char *tmp_str = calloc(1, str_size + 50); char *tmp_str_ptr = tmp_str; @@ -1227,13 +1225,12 @@ int linux_thread_extra_info(struct target *target, else tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); - tmp_str_ptr += - sprintf(tmp_str_ptr, "%d", (int)temp->pid); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | "); + tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid); sprintf(tmp_str_ptr, "%s", name); sprintf(tmp_str_ptr, "%s", temp->name); char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); - int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); + size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, + strlen(tmp_str), strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); diff --git a/src/rtos/linux_header.h b/src/rtos/linux_header.h index faaf319b1..a2b408efd 100644 --- a/src/rtos/linux_header.h +++ b/src/rtos/linux_header.h @@ -1,3 +1,6 @@ +#ifndef OPENOCD_RTOS_LINUX_HEADER_H +#define OPENOCD_RTOS_LINUX_HEADER_H + /* gdb script to update the header file according to kernel version and build option before executing function awareness @@ -30,3 +33,5 @@ define awareness #define CPU_CONT 0x1c #define PREEMPT 0x4 #define MM_CTX 0x160 + +#endif /* OPENOCD_RTOS_LINUX_HEADER_H */ diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index 272658c8a..63a48c54b 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -13,8 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -109,7 +108,7 @@ static int mqx_valid_address_check( enum mqx_arch arch_type = ((struct mqx_params *)rtos->rtos_specific_params)->target_arch; const char * targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name; - /* Cortex M address range */ + /* Cortex-M address range */ if (arch_type == mqx_arch_cortexm) { if ( /* code and sram area */ @@ -354,7 +353,7 @@ static int mqx_update_threads( uint32_t task_name_addr = 0, task_id = 0, task_errno = 0; uint32_t state_index = 0, state_max = 0; uint32_t extra_info_length = 0; - char *state_name = "unknown state"; + char *state_name = "Unknown"; /* set current taskpool address */ if (ERROR_OK != mqx_get_member( @@ -424,7 +423,6 @@ static int mqx_update_threads( /* setup thread details struct */ rtos->thread_details[i].threadid = task_id; rtos->thread_details[i].exists = true; - rtos->thread_details[i].display_str = NULL; /* set thread name */ rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1); if (NULL == rtos->thread_details[i].thread_name_str) @@ -437,13 +435,13 @@ static int mqx_update_threads( * calculate length as: * state length + address length + errno length + formatter length */ - extra_info_length += strlen((void *)state_name) + 8 + 8 + 8; + extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8; rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1); if (NULL == rtos->thread_details[i].extra_info_str) return ERROR_FAIL; - snprintf( - rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32, - state_name, task_addr, task_errno + snprintf(rtos->thread_details[i].extra_info_str, extra_info_length, + "State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32, + state_name, task_addr, task_errno ); /* set active thread */ if (active_td_addr == task_addr) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 528546eaa..804ecc9ef 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -36,6 +34,10 @@ extern struct rtos_type Linux_os; extern struct rtos_type ChibiOS_rtos; extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; +extern struct rtos_type uCOS_III_rtos; +#if BUILD_RISCV == 1 +extern struct rtos_type riscv_rtos; +#endif static struct rtos_type *rtos_types[] = { &ThreadX_rtos, @@ -45,7 +47,11 @@ static struct rtos_type *rtos_types[] = { &ChibiOS_rtos, &embKernel_rtos, &mqx_rtos, - NULL + &uCOS_III_rtos, +#if BUILD_RISCV == 1 + &riscv_rtos, +#endif + NULL }; int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); @@ -72,6 +78,9 @@ static int os_alloc(struct target *target, struct rtos_type *ostype) /* RTOS drivers can override the packet handler in _create(). */ os->gdb_thread_packet = rtos_thread_packet; +#if BUILD_RISCV == 1 + os->gdb_v_packet = NULL; +#endif return JIM_OK; } @@ -104,8 +113,9 @@ static int os_alloc_create(struct target *target, struct rtos_type *ostype) int rtos_create(Jim_GetOptInfo *goi, struct target *target) { int x; - char *cp; + const char *cp; struct Jim_Obj *res; + int e; if (!goi->isconfigure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); @@ -114,7 +124,9 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) os_free(target); - Jim_GetOpt_String(goi, &cp, NULL); + e = Jim_GetOpt_String(goi, &cp, NULL); + if (e != JIM_OK) + return e; if (0 == strcmp(cp, "auto")) { /* Auto detect tries to look up all symbols for each RTOS, @@ -215,7 +227,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s goto done; /* Decode any symbol name in the packet*/ - int len = unhexify(cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1)); + size_t len = unhexify((uint8_t *)cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1)); cur_sym[len] = 0; if ((strcmp(packet, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */ @@ -263,7 +275,9 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s } reply_len = snprintf(reply, sizeof(reply), "qSymbol:"); - reply_len += hexify(reply + reply_len, next_sym->symbol_name, 0, sizeof(reply) - reply_len); + reply_len += hexify(reply + reply_len, + (const uint8_t *)next_sym->symbol_name, strlen(next_sym->symbol_name), + sizeof(reply) - reply_len); done: gdb_put_packet(connection, reply, reply_len); @@ -298,35 +312,28 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa struct thread_detail *detail = &target->rtos->thread_details[found]; int str_size = 0; - if (detail->display_str != NULL) - str_size += strlen(detail->display_str); if (detail->thread_name_str != NULL) str_size += strlen(detail->thread_name_str); if (detail->extra_info_str != NULL) str_size += strlen(detail->extra_info_str); - char *tmp_str = calloc(str_size + 7, sizeof(char)); + char *tmp_str = calloc(str_size + 9, sizeof(char)); char *tmp_str_ptr = tmp_str; - if (detail->display_str != NULL) - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->display_str); - if (detail->thread_name_str != NULL) { - if (tmp_str_ptr != tmp_str) - tmp_str_ptr += sprintf(tmp_str_ptr, " : "); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str); - } + if (detail->thread_name_str != NULL) + tmp_str_ptr += sprintf(tmp_str_ptr, "Name: %s", detail->thread_name_str); if (detail->extra_info_str != NULL) { if (tmp_str_ptr != tmp_str) - tmp_str_ptr += sprintf(tmp_str_ptr, " : "); - tmp_str_ptr += - sprintf(tmp_str_ptr, " : %s", detail->extra_info_str); + tmp_str_ptr += sprintf(tmp_str_ptr, ", "); + tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str); } assert(strlen(tmp_str) == (size_t) (tmp_str_ptr - tmp_str)); char *hex_str = malloc(strlen(tmp_str) * 2 + 1); - int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); + size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, + strlen(tmp_str), strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); @@ -407,9 +414,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for * all other operations ) */ if ((packet[1] == 'g') && (target->rtos != NULL)) { - sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid); - LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n", - target->rtos->current_threadid); + threadid_t threadid; + sscanf(packet, "Hg%16" SCNx64, &threadid); + LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64, threadid); + /* threadid of 0 indicates target should choose */ + if (threadid == 0) + target->rtos->current_threadid = target->rtos->current_thread; + else + target->rtos->current_threadid = threadid; } gdb_put_packet(connection, "OK", 2); return ERROR_OK; @@ -428,14 +440,25 @@ int rtos_get_gdb_reg_list(struct connection *connection) (target->smp))) { /* in smp several current thread are possible */ char *hex_reg_list; - LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64 +#if BUILD_RISCV == 1 + LOG_INFO("RTOS: getting register list for thread 0x%" PRIx64 ", target->rtos->current_thread=0x%" PRIx64 "\r\n", current_threadid, target->rtos->current_thread); +#else + LOG_DEBUG("RTOS: getting register list for thread 0x%" PRIx64 + ", target->rtos->current_thread=0x%" PRIx64 "\r\n", + current_threadid, + target->rtos->current_thread); +#endif - target->rtos->type->get_thread_reg_list(target->rtos, - current_threadid, - &hex_reg_list); + int retval = target->rtos->type->get_thread_reg_list(target->rtos, + current_threadid, + &hex_reg_list); + if (retval != ERROR_OK) { + LOG_ERROR("RTOS: failed to get register list"); + return retval; + } if (hex_reg_list != NULL) { gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list)); @@ -547,12 +570,13 @@ void rtos_free_threadlist(struct rtos *rtos) for (j = 0; j < rtos->thread_count; j++) { struct thread_detail *current_thread = &rtos->thread_details[j]; - free(current_thread->display_str); free(current_thread->thread_name_str); free(current_thread->extra_info_str); } free(rtos->thread_details); rtos->thread_details = NULL; rtos->thread_count = 0; + rtos->current_threadid = -1; + rtos->current_thread = 0; } } diff --git a/src/rtos/rtos.h b/src/rtos/rtos.h index d082fb7a7..6ff5f8575 100644 --- a/src/rtos/rtos.h +++ b/src/rtos/rtos.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef RTOS_H -#define RTOS_H +#ifndef OPENOCD_RTOS_RTOS_H +#define OPENOCD_RTOS_RTOS_H #include "server/server.h" #include @@ -41,7 +39,6 @@ typedef struct symbol_table_elem_struct { struct thread_detail { threadid_t threadid; bool exists; - char *display_str; char *thread_name_str; char *extra_info_str; }; @@ -57,6 +54,9 @@ struct rtos { struct thread_detail *thread_details; int thread_count; int (*gdb_thread_packet)(struct connection *connection, char const *packet, int packet_size); +#if BUILD_RISCV == 1 + int (*gdb_v_packet)(struct connection *connection, char const *packet, int packet_size); +#endif void *rtos_specific_params; }; @@ -111,4 +111,4 @@ int rtos_smp_init(struct target *target); /* function for handling symbol access */ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_size); -#endif /* RTOS_H */ +#endif /* OPENOCD_RTOS_RTOS_H */ diff --git a/src/rtos/rtos_chibios_stackings.c b/src/rtos/rtos_chibios_stackings.c index e138b0684..3651c49a9 100644 --- a/src/rtos/rtos_chibios_stackings.c +++ b/src/rtos/rtos_chibios_stackings.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/rtos/rtos_chibios_stackings.h b/src/rtos/rtos_chibios_stackings.h index 8ba2a6ca3..130aaa18f 100644 --- a/src/rtos/rtos_chibios_stackings.h +++ b/src/rtos/rtos_chibios_stackings.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ -#define INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ +#ifndef OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H +#define OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -30,4 +28,4 @@ extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking; extern const struct rtos_register_stacking rtos_chibios_arm_v7m_stacking_w_fpu; -#endif /* ifndef INCLUDED_RTOS_CHIBIOS_STACKINGS_H_ */ +#endif /* OPENOCD_RTOS_RTOS_CHIBIOS_STACKINGS_H */ diff --git a/src/rtos/rtos_ecos_stackings.c b/src/rtos/rtos_ecos_stackings.c index cc924ae22..43d97a605 100644 --- a/src/rtos/rtos_ecos_stackings.c +++ b/src/rtos/rtos_ecos_stackings.c @@ -11,9 +11,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/rtos/rtos_ecos_stackings.h b/src/rtos/rtos_ecos_stackings.h index 3bcd7cb05..951f7de50 100644 --- a/src/rtos/rtos_ecos_stackings.h +++ b/src/rtos/rtos_ecos_stackings.h @@ -11,13 +11,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ -#define INCLUDED_RTOS_STANDARD_STACKINGS_H_ +#ifndef OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H +#define OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -27,4 +25,4 @@ extern const struct rtos_register_stacking rtos_eCos_Cortex_M3_stacking; -#endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */ +#endif /* OPENOCD_RTOS_RTOS_ECOS_STACKINGS_H */ diff --git a/src/rtos/rtos_embkernel_stackings.c b/src/rtos/rtos_embkernel_stackings.c index 8171957fd..2a3062955 100644 --- a/src/rtos/rtos_embkernel_stackings.c +++ b/src/rtos/rtos_embkernel_stackings.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/rtos/rtos_embkernel_stackings.h b/src/rtos/rtos_embkernel_stackings.h index 5bbcb4615..89a0c2f12 100644 --- a/src/rtos/rtos_embkernel_stackings.h +++ b/src/rtos/rtos_embkernel_stackings.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ -#define INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ +#ifndef OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H +#define OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -29,4 +27,4 @@ extern const struct rtos_register_stacking rtos_embkernel_Cortex_M_stacking; -#endif /* ifndef INCLUDED_RTOS_EMBKERNEL_STACKINGS_H_ */ +#endif /* OPENOCD_RTOS_RTOS_EMBKERNEL_STACKINGS_H */ diff --git a/src/rtos/rtos_mqx_stackings.c b/src/rtos/rtos_mqx_stackings.c index fac18b606..5db2f8ec3 100644 --- a/src/rtos/rtos_mqx_stackings.c +++ b/src/rtos/rtos_mqx_stackings.c @@ -13,8 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/rtos/rtos_mqx_stackings.h b/src/rtos/rtos_mqx_stackings.h index 9536c400f..6ebd28789 100644 --- a/src/rtos/rtos_mqx_stackings.h +++ b/src/rtos/rtos_mqx_stackings.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef INCLUDED_RTOS_MQX_STACKINGS_H_ -#define INCLUDED_RTOS_MQX_STACKINGS_H_ +#ifndef OPENOCD_RTOS_RTOS_MQX_STACKINGS_H +#define OPENOCD_RTOS_RTOS_MQX_STACKINGS_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -28,5 +27,4 @@ extern const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking; -#endif /* ifndef INCLUDED_RTOS_MQX_STACKINGS_H_ */ - +#endif /* OPENOCD_RTOS_RTOS_MQX_STACKINGS_H */ diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c index 1a58870fc..0176c01ab 100644 --- a/src/rtos/rtos_standard_stackings.c +++ b/src/rtos/rtos_standard_stackings.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -45,6 +43,47 @@ static const struct stack_register_offset rtos_standard_Cortex_M3_stack_offsets[ { 0x3c, 32 }, /* xPSR */ }; +static const struct stack_register_offset rtos_standard_Cortex_M4F_stack_offsets[] = { + { 0x24, 32 }, /* r0 */ + { 0x28, 32 }, /* r1 */ + { 0x2c, 32 }, /* r2 */ + { 0x30, 32 }, /* r3 */ + { 0x00, 32 }, /* r4 */ + { 0x04, 32 }, /* r5 */ + { 0x08, 32 }, /* r6 */ + { 0x0c, 32 }, /* r7 */ + { 0x10, 32 }, /* r8 */ + { 0x14, 32 }, /* r9 */ + { 0x18, 32 }, /* r10 */ + { 0x1c, 32 }, /* r11 */ + { 0x34, 32 }, /* r12 */ + { -2, 32 }, /* sp */ + { 0x38, 32 }, /* lr */ + { 0x3c, 32 }, /* pc */ + { 0x40, 32 }, /* xPSR */ +}; + +static const struct stack_register_offset rtos_standard_Cortex_M4F_FPU_stack_offsets[] = { + { 0x64, 32 }, /* r0 */ + { 0x68, 32 }, /* r1 */ + { 0x6c, 32 }, /* r2 */ + { 0x70, 32 }, /* r3 */ + { 0x00, 32 }, /* r4 */ + { 0x04, 32 }, /* r5 */ + { 0x08, 32 }, /* r6 */ + { 0x0c, 32 }, /* r7 */ + { 0x10, 32 }, /* r8 */ + { 0x14, 32 }, /* r9 */ + { 0x18, 32 }, /* r10 */ + { 0x1c, 32 }, /* r11 */ + { 0x74, 32 }, /* r12 */ + { -2, 32 }, /* sp */ + { 0x78, 32 }, /* lr */ + { 0x7c, 32 }, /* pc */ + { 0x80, 32 }, /* xPSR */ +}; + + static const struct stack_register_offset rtos_standard_Cortex_R4_stack_offsets[] = { { 0x08, 32 }, /* r0 (a1) */ { 0x0c, 32 }, /* r1 (a2) */ @@ -141,7 +180,7 @@ int64_t rtos_generic_stack_align8(struct target *target, stacking, stack_ptr, 8); } -/* The Cortex M3 will indicate that an alignment adjustment +/* The Cortex-M3 will indicate that an alignment adjustment * has been done on the stack by setting bit 9 of the stacked xPSR * register. In this case, we can just add an extra 4 bytes to get * to the program stack. Note that some places in the ARM documentation @@ -198,6 +237,22 @@ const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking = { rtos_standard_Cortex_M3_stack_offsets /* register_offsets */ }; +const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking = { + 0x44, /* stack_registers_size 4 more for LR*/ + -1, /* stack_growth_direction */ + ARMV7M_NUM_CORE_REGS, /* num_output_registers */ + rtos_standard_Cortex_M3_stack_align, /* stack_alignment */ + rtos_standard_Cortex_M4F_stack_offsets /* register_offsets */ +}; + +const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking = { + 0xcc, /* stack_registers_size 4 more for LR + 48 more for FPU S0-S15 register*/ + -1, /* stack_growth_direction */ + ARMV7M_NUM_CORE_REGS, /* num_output_registers */ + rtos_standard_Cortex_M3_stack_align, /* stack_alignment */ + rtos_standard_Cortex_M4F_FPU_stack_offsets /* register_offsets */ +}; + const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking = { 0x48, /* stack_registers_size */ -1, /* stack_growth_direction */ diff --git a/src/rtos/rtos_standard_stackings.h b/src/rtos/rtos_standard_stackings.h index f931bb9f2..6971efd1e 100644 --- a/src/rtos/rtos_standard_stackings.h +++ b/src/rtos/rtos_standard_stackings.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ -#define INCLUDED_RTOS_STANDARD_STACKINGS_H_ +#ifndef OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H +#define OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -28,6 +26,8 @@ #include "rtos.h" extern const struct rtos_register_stacking rtos_standard_Cortex_M3_stacking; +extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_stacking; +extern const struct rtos_register_stacking rtos_standard_Cortex_M4F_FPU_stacking; extern const struct rtos_register_stacking rtos_standard_Cortex_R4_stacking; extern const struct rtos_register_stacking rtos_standard_NDS32_N1068_stacking; int64_t rtos_generic_stack_align8(struct target *target, @@ -37,4 +37,4 @@ int64_t rtos_Cortex_M_stack_align(struct target *target, const uint8_t *stack_data, const struct rtos_register_stacking *stacking, int64_t stack_ptr, size_t xpsr_offset); -#endif /* ifndef INCLUDED_RTOS_STANDARD_STACKINGS_H_ */ +#endif /* OPENOCD_RTOS_RTOS_STANDARD_STACKINGS_H */ diff --git a/src/server/Makefile.am b/src/server/Makefile.am index 04d3035f4..804efac16 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -1,23 +1,19 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libserver.la +%C%_libserver_la_SOURCES = \ + %D%/server.c \ + %D%/telnet_server.c \ + %D%/gdb_server.c \ + %D%/server.h \ + %D%/telnet_server.h \ + %D%/gdb_server.h \ + %D%/server_stubs.c \ + %D%/tcl_server.c \ + %D%/tcl_server.h -METASOURCES = AUTO -noinst_LTLIBRARIES = libserver.la -noinst_HEADERS = server.h telnet_server.h gdb_server.h -libserver_la_SOURCES = server.c telnet_server.c gdb_server.c - -libserver_la_SOURCES += server_stubs.c - -libserver_la_CFLAGS = +%C%_libserver_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -libserver_la_CFLAGS += -Wno-sign-compare +%C%_libserver_la_CFLAGS += -Wno-sign-compare endif -# tcl server addons -noinst_HEADERS += tcl_server.h -libserver_la_SOURCES += tcl_server.c - -EXTRA_DIST = \ - startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 780359ea4..f03bdb1eb 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -31,9 +31,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -92,6 +90,8 @@ struct gdb_connection { bool attached; /* temporarily used for target description support */ struct target_desc_format target_desc; + /* temporarily used for thread list support */ + char *thread_list; }; #if 0 @@ -697,7 +697,8 @@ static int gdb_output_con(struct connection *connection, const char *line) return ERROR_GDB_BUFFER_TOO_SMALL; hex_buffer[0] = 'O'; - int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1); + size_t pkt_len = hexify(hex_buffer + 1, (const uint8_t *)line, bin_size, + bin_size * 2 + 1); int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1); free(hex_buffer); @@ -734,22 +735,22 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio stop_reason[0] = '\0'; if (target->debug_reason == DBG_REASON_WATCHPOINT) { enum watchpoint_rw hit_wp_type; - uint32_t hit_wp_address; + target_addr_t hit_wp_address; if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) { switch (hit_wp_type) { case WPT_WRITE: snprintf(stop_reason, sizeof(stop_reason), - "watch:%08" PRIx32 ";", hit_wp_address); + "watch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; case WPT_READ: snprintf(stop_reason, sizeof(stop_reason), - "rwatch:%08" PRIx32 ";", hit_wp_address); + "rwatch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; case WPT_ACCESS: snprintf(stop_reason, sizeof(stop_reason), - "awatch:%08" PRIx32 ";", hit_wp_address); + "awatch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; default: break; @@ -936,6 +937,7 @@ static int gdb_new_connection(struct connection *connection) gdb_connection->attached = true; gdb_connection->target_desc.tdesc = NULL; gdb_connection->target_desc.tdesc_length = 0; + gdb_connection->thread_list = NULL; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); @@ -1165,8 +1167,20 @@ static int gdb_get_registers_packet(struct connection *connection, reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { +#if BUILD_RISCV == 1 + if (!reg_list[i]->valid) { + retval = reg_list[i]->type->get(reg_list[i]); + if (retval != ERROR_OK) { + LOG_DEBUG("Couldn't get register %s.", reg_list[i]->name); + free(reg_packet); + free(reg_list); + return gdb_error(connection, retval); + } + } +#else if (!reg_list[i]->valid) reg_list[i]->type->get(reg_list[i]); +#endif gdb_str_to_target(target, reg_packet_p, reg_list[i]); reg_packet_p += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1227,7 +1241,17 @@ static int gdb_set_registers_packet(struct connection *connection, bin_buf = malloc(DIV_ROUND_UP(reg_list[i]->size, 8)); gdb_target_to_reg(target, packet_p, chars, bin_buf); +#if BUILD_RISCV == 1 + retval = reg_list[i]->type->set(reg_list[i], bin_buf); + if (retval != ERROR_OK) { + LOG_DEBUG("Couldn't set register %s.", reg_list[i]->name); + free(reg_list); + free(bin_buf); + return gdb_error(connection, retval); + } +#else reg_list[i]->type->set(reg_list[i], bin_buf); +#endif /* advance packet pointer */ packet_p += chars; @@ -1267,8 +1291,19 @@ static int gdb_get_register_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } +#if BUILD_RISCV == 1 + if (!reg_list[reg_num]->valid) { + retval = reg_list[reg_num]->type->get(reg_list[reg_num]); + if (retval != ERROR_OK) { + LOG_DEBUG("Couldn't get register %s.", reg_list[reg_num]->name); + free (reg_list); + return gdb_error(connection, retval); + } + } +#else if (!reg_list[reg_num]->valid) reg_list[reg_num]->type->get(reg_list[reg_num]); +#endif reg_packet = malloc(DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2 + 1); /* plus one for string termination null */ @@ -1322,7 +1357,17 @@ static int gdb_set_register_packet(struct connection *connection, gdb_target_to_reg(target, separator + 1, chars, bin_buf); +#if BUILD_RISCV == 1 + retval = reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); + if (retval != ERROR_OK){ + LOG_DEBUG("Couldn't set register %s.", reg_list[reg_num]->name); + free(bin_buf); + free(reg_list); + return gdb_error(connection, retval); + } +#else reg_list[reg_num]->type->set(reg_list[reg_num], bin_buf); +#endif gdb_put_packet(connection, "OK", 2); @@ -1353,7 +1398,7 @@ static int gdb_read_memory_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; uint8_t *buffer; @@ -1364,7 +1409,7 @@ static int gdb_read_memory_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete read memory packet received, dropping connection"); @@ -1381,7 +1426,7 @@ static int gdb_read_memory_packet(struct connection *connection, buffer = malloc(len); - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_read_buffer(target, addr, len, buffer); @@ -1406,7 +1451,7 @@ static int gdb_read_memory_packet(struct connection *connection, if (retval == ERROR_OK) { hex_buffer = malloc(len * 2 + 1); - int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1); + size_t pkt_len = hexify(hex_buffer, buffer, len, len * 2 + 1); gdb_put_packet(connection, hex_buffer, pkt_len); @@ -1424,7 +1469,7 @@ static int gdb_write_memory_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; uint8_t *buffer; @@ -1433,7 +1478,7 @@ static int gdb_write_memory_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory packet received, dropping connection"); @@ -1449,9 +1494,9 @@ static int gdb_write_memory_packet(struct connection *connection, buffer = malloc(len); - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); - if (unhexify((char *)buffer, separator, len) != (int)len) + if (unhexify(buffer, separator, len) != len) LOG_ERROR("unable to decode memory packet"); retval = target_write_buffer(target, addr, len, buffer); @@ -1471,15 +1516,19 @@ static int gdb_write_memory_binary_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; int retval = ERROR_OK; + /* Packets larger than fast_limit bytes will be acknowledged instantly on + * the assumption that we're in a download and it's important to go as fast + * as possible. */ + uint32_t fast_limit = 8; /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory binary packet received, dropping connection"); @@ -1495,31 +1544,44 @@ static int gdb_write_memory_binary_packet(struct connection *connection, struct gdb_connection *gdb_connection = connection->priv; - if (gdb_connection->mem_write_error) { + if (gdb_connection->mem_write_error) retval = ERROR_FAIL; - /* now that we have reported the memory write error, we can clear the condition */ - gdb_connection->mem_write_error = false; - } - /* By replying the packet *immediately* GDB will send us a new packet - * while we write the last one to the target. - */ - if (retval == ERROR_OK) - gdb_put_packet(connection, "OK", 2); - else { + if (retval == ERROR_OK) { + if (len >= fast_limit) { + /* By replying the packet *immediately* GDB will send us a new packet + * while we write the last one to the target. + * We only do this for larger writes, so that users who do something like: + * p *((int*)0xdeadbeef)=8675309 + * will get immediate feedback that that write failed. + */ + gdb_put_packet(connection, "OK", 2); + } + } else { retval = gdb_error(connection, retval); + /* now that we have reported the memory write error, we can clear the condition */ + gdb_connection->mem_write_error = false; if (retval != ERROR_OK) return retval; } if (len) { - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_write_buffer(target, addr, len, (uint8_t *)separator); if (retval != ERROR_OK) gdb_connection->mem_write_error = true; } + if (len < fast_limit) { + if (retval != ERROR_OK) { + gdb_error(connection, retval); + gdb_connection->mem_write_error = false; + } else { + gdb_put_packet(connection, "OK", 2); + } + } + return ERROR_OK; } @@ -1528,13 +1590,13 @@ static int gdb_step_continue_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); int current = 0; - uint32_t address = 0x0; + uint64_t address = 0x0; int retval = ERROR_OK; LOG_DEBUG("-"); if (packet_size > 1) - address = strtoul(packet + 1, NULL, 16); + address = strtoull(packet + 1, NULL, 16); else current = 1; @@ -1558,7 +1620,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, int type; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */; - uint32_t address; + uint64_t address; uint32_t size; char *separator; int retval; @@ -1590,7 +1652,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - address = strtoul(separator + 1, &separator, 16); + address = strtoull(separator + 1, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); @@ -2268,6 +2330,95 @@ static int gdb_target_description_supported(struct target *target, int *supporte return retval; } +static int gdb_generate_thread_list(struct target *target, char **thread_list_out) +{ + struct rtos *rtos = target->rtos; + int retval = ERROR_OK; + char *thread_list = NULL; + int pos = 0; + int size = 0; + + xml_printf(&retval, &thread_list, &pos, &size, + "\n" + "\n"); + + if (rtos != NULL) { + for (int i = 0; i < rtos->thread_count; i++) { + struct thread_detail *thread_detail = &rtos->thread_details[i]; + + if (!thread_detail->exists) + continue; + + xml_printf(&retval, &thread_list, &pos, &size, + "", thread_detail->threadid); + + if (thread_detail->thread_name_str != NULL) + xml_printf(&retval, &thread_list, &pos, &size, + "Name: %s", thread_detail->thread_name_str); + + if (thread_detail->extra_info_str != NULL) { + if (thread_detail->thread_name_str != NULL) + xml_printf(&retval, &thread_list, &pos, &size, + ", "); + xml_printf(&retval, &thread_list, &pos, &size, + thread_detail->extra_info_str); + } + + xml_printf(&retval, &thread_list, &pos, &size, + "\n"); + } + } + + xml_printf(&retval, &thread_list, &pos, &size, + "\n"); + + if (retval == ERROR_OK) + *thread_list_out = thread_list; + else + free(thread_list); + + return retval; +} + +static int gdb_get_thread_list_chunk(struct target *target, char **thread_list, + char **chunk, int32_t offset, uint32_t length) +{ + if (*thread_list == NULL) { + int retval = gdb_generate_thread_list(target, thread_list); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to Generate Thread List"); + return ERROR_FAIL; + } + } + + size_t thread_list_length = strlen(*thread_list); + char transfer_type; + + length = MIN(length, thread_list_length - offset); + if (length < (thread_list_length - offset)) + transfer_type = 'm'; + else + transfer_type = 'l'; + + *chunk = malloc(length + 2); + if (*chunk == NULL) { + LOG_ERROR("Unable to allocate memory"); + return ERROR_FAIL; + } + + (*chunk)[0] = transfer_type; + strncpy((*chunk) + 1, (*thread_list) + offset, length); + (*chunk)[1 + length] = '\0'; + + /* After gdb-server sends out last chunk, invalidate thread list. */ + if (transfer_type == 'l') { + free(*thread_list); + *thread_list = NULL; + } + + return ERROR_OK; +} + static int gdb_query_packet(struct connection *connection, char const *packet, int packet_size) { @@ -2279,7 +2430,7 @@ static int gdb_query_packet(struct connection *connection, if (packet_size > 6) { char *cmd; cmd = malloc((packet_size - 6) / 2 + 1); - int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2); + size_t len = unhexify((uint8_t *)cmd, packet + 6, (packet_size - 6) / 2); cmd[len] = 0; /* We want to print all debug output to GDB connection */ @@ -2302,7 +2453,7 @@ static int gdb_query_packet(struct connection *connection, char gdb_reply[10]; char *separator; uint32_t checksum; - uint32_t addr = 0; + target_addr_t addr = 0; uint32_t len = 0; /* skip command character */ @@ -2357,7 +2508,7 @@ static int gdb_query_packet(struct connection *connection, &buffer, &pos, &size, - "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+", + "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+", (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-', (gdb_target_desc_supported == 1) ? '+' : '-'); @@ -2403,6 +2554,37 @@ static int gdb_query_packet(struct connection *connection, gdb_put_packet(connection, xml, strlen(xml)); + free(xml); + return ERROR_OK; + } else if (strncmp(packet, "qXfer:threads:read:", 19) == 0) { + char *xml = NULL; + int retval = ERROR_OK; + + int offset; + unsigned int length; + + /* skip command character */ + packet += 19; + + if (decode_xfer_read(packet, NULL, &offset, &length) < 0) { + gdb_send_error(connection, 01); + return ERROR_OK; + } + + /* Target should prepare correct thread list for annex. + * The first character of returned xml is 'm' or 'l'. 'm' for + * there are *more* chunks to transfer. 'l' for it is the *last* + * chunk of target description. + */ + retval = gdb_get_thread_list_chunk(target, &gdb_connection->thread_list, + &xml, offset, length); + if (retval != ERROR_OK) { + gdb_error(connection, retval); + return retval; + } + + gdb_put_packet(connection, xml, strlen(xml)); + free(xml); return ERROR_OK; } else if (strncmp(packet, "QStartNoAckMode", 15) == 0) { @@ -2422,6 +2604,15 @@ static int gdb_v_packet(struct connection *connection, struct gdb_service *gdb_service = connection->service->priv; int result; +#if BUILD_RISCV == 1 + struct target *target = get_target_from_connection(connection); + if (target->rtos != NULL && target->rtos->gdb_v_packet != NULL) { + int out = target->rtos->gdb_v_packet(connection, packet, packet_size); + if (out != GDB_THREAD_PACKET_NOT_CONSUMED) + return out; + } +#endif + /* if flash programming disabled - send a empty reply */ if (gdb_flash_program == 0) { @@ -2620,7 +2811,11 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line, gdb_output_con(connection, string); } +#if BUILD_RISCV == 1 +void gdb_sig_halted(struct connection *connection) +#else static void gdb_sig_halted(struct connection *connection) +#endif { char sig_reply[4]; snprintf(sig_reply, 4, "T%2.2x", 2); @@ -2923,6 +3118,11 @@ static int gdb_target_start(struct target *target, const char *port) static int gdb_target_add_one(struct target *target) { + if (strcmp(gdb_port, "disabled") == 0) { + LOG_INFO("gdb port disabled"); + return ERROR_OK; + } + /* one gdb instance per smp list */ if ((target->smp) && (target->gdb_service)) return ERROR_OK; @@ -2937,7 +3137,13 @@ static int gdb_target_add_one(struct target *target) if (!*end) { if (parse_long(gdb_port_next, &portnumber) == ERROR_OK) { free(gdb_port_next); - gdb_port_next = alloc_printf("%d", portnumber+1); + if (portnumber) { + gdb_port_next = alloc_printf("%d", portnumber+1); + } else { + /* Don't increment if gdb_port is 0, since we're just + * trying to allocate an unused port. */ + gdb_port_next = alloc_printf("0"); + } } } } @@ -2946,6 +3152,11 @@ static int gdb_target_add_one(struct target *target) int gdb_target_add_all(struct target *target) { + if (strcmp(gdb_port, "disabled") == 0) { + LOG_INFO("gdb server disabled"); + return ERROR_OK; + } + if (NULL == target) { LOG_WARNING("gdb services need one or more targets defined"); return ERROR_OK; @@ -3063,7 +3274,7 @@ COMMAND_HANDLER(handle_gdb_save_tdesc_command) tdesc_length = strlen(tdesc); - struct fileio fileio; + struct fileio *fileio; size_t size_written; char *tdesc_filename = alloc_printf("%s.xml", target_type_name(target)); @@ -3079,9 +3290,9 @@ COMMAND_HANDLER(handle_gdb_save_tdesc_command) goto out; } - retval = fileio_write(&fileio, tdesc_length, tdesc, &size_written); + retval = fileio_write(fileio, tdesc_length, tdesc, &size_written); - fileio_close(&fileio); + fileio_close(fileio); if (retval != ERROR_OK) LOG_ERROR("Error while writing the tdesc file"); @@ -3111,7 +3322,7 @@ static const struct command_registration gdb_command_handlers[] = { "server listens for the next port number after the " "base port number specified. " "No arguments reports GDB port. \"pipe\" means listen to stdin " - "output to stdout, an integer is base port number, \"disable\" disables " + "output to stdout, an integer is base port number, \"disabled\" disables " "port. Any other string is are interpreted as named pipe to listen to. " "Output pipe is the same name as input pipe, but with 'o' appended.", .usage = "[port_num]", @@ -3167,3 +3378,11 @@ int gdb_register_commands(struct command_context *cmd_ctx) gdb_port_next = strdup("3333"); return register_commands(cmd_ctx, NULL, gdb_command_handlers); } + +#if BUILD_RISCV == 1 +void gdb_set_frontend_state_running(struct connection *connection) +{ + struct gdb_connection *gdb_con = connection->priv; + gdb_con->frontend_state = TARGET_RUNNING; +} +#endif diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h index 8092d7b6d..460b12491 100644 --- a/src/server/gdb_server.h +++ b/src/server/gdb_server.h @@ -22,13 +22,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef GDB_SERVER_H -#define GDB_SERVER_H +#ifndef OPENOCD_SERVER_GDB_SERVER_H +#define OPENOCD_SERVER_GDB_SERVER_H struct image; struct reg; @@ -47,7 +45,12 @@ static inline struct target *get_target_from_connection(struct connection *conne return gdb_service->target; } +#if BUILD_RISCV == 1 +void gdb_set_frontend_state_running(struct connection *connection); +void gdb_sig_halted(struct connection *connection); +#endif + #define ERROR_GDB_BUFFER_TOO_SMALL (-800) #define ERROR_GDB_TIMEOUT (-801) -#endif /* GDB_SERVER_H */ +#endif /* OPENOCD_SERVER_GDB_SERVER_H */ diff --git a/src/server/server.c b/src/server/server.c index 24747f938..dae7df3c5 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -38,6 +36,10 @@ #include +#ifdef HAVE_NETDB_H +#include +#endif + #ifndef _WIN32 #include #endif @@ -54,6 +56,9 @@ static int last_signal; /* set the polling period to 100ms */ static int polling_period = 100; +/* address by name on which to listen for incoming TCP/IP connections */ +static char *bindto_name; + static int add_connection(struct service *service, struct command_context *cmd_ctx) { socklen_t address_size; @@ -127,7 +132,9 @@ static int add_connection(struct service *service, struct command_context *cmd_c free(out_file); if (c->fd_out == -1) { LOG_ERROR("could not open %s", service->port); - exit(1); + command_done(c->cmd_ctx); + free(c); + return ERROR_FAIL; } LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port); @@ -186,7 +193,13 @@ static int remove_connection(struct service *service, struct connection *connect return ERROR_OK; } -/* FIX! make service return error instead of invoking exit() */ +static void free_service(struct service *c) +{ + free(c->name); + free(c->port); + free(c); +} + int add_service(char *name, const char *port, int max_connections, @@ -196,6 +209,7 @@ int add_service(char *name, void *priv) { struct service *c, **p; + struct hostent *hp; int so_reuseaddr_option = 1; c = malloc(sizeof(struct service)); @@ -229,7 +243,8 @@ int add_service(char *name, c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd == -1) { LOG_ERROR("error creating socket: %s", strerror(errno)); - exit(-1); + free_service(c); + return ERROR_FAIL; } setsockopt(c->fd, @@ -242,12 +257,31 @@ int add_service(char *name, memset(&c->sin, 0, sizeof(c->sin)); c->sin.sin_family = AF_INET; - c->sin.sin_addr.s_addr = INADDR_ANY; + + if (bindto_name == NULL) + c->sin.sin_addr.s_addr = INADDR_ANY; + else { + hp = gethostbyname(bindto_name); + if (hp == NULL) { + LOG_ERROR("couldn't resolve bindto address: %s", bindto_name); + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; + } + memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length); + } c->sin.sin_port = htons(c->portnumber); if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { - LOG_ERROR("couldn't bind to socket: %s", strerror(errno)); - exit(-1); +#if BUILD_RISCV == 1 + LOG_ERROR("couldn't bind %s to socket on port %d: %s", name, + c->portnumber, strerror(errno)); +#else + LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno)); +#endif + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; } #ifndef _WIN32 @@ -265,8 +299,18 @@ int add_service(char *name, if (listen(c->fd, 1) == -1) { LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); - exit(-1); + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; } + +#if BUILD_RISCV == 1 + struct sockaddr_in addr_in; + socklen_t addr_in_size = sizeof(addr_in); + getsockname(c->fd, (struct sockaddr*)&addr_in, &addr_in_size); + LOG_INFO("Listening on port %d for %s connections", + ntohs(addr_in.sin_port), name); +#endif } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); @@ -286,13 +330,15 @@ int add_service(char *name, /* we currenty do not support named pipes under win32 * so exit openocd for now */ LOG_ERROR("Named pipes currently not supported under this os"); - exit(1); + free_service(c); + return ERROR_FAIL; #else /* Pipe we're reading from */ c->fd = open(c->port, O_RDONLY | O_NONBLOCK); if (c->fd == -1) { LOG_ERROR("could not open %s", c->port); - exit(1); + free_service(c); + return ERROR_FAIL; } #endif } @@ -409,7 +455,7 @@ int server_loop(struct command_context *command_context) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); - exit(-1); + return ERROR_FAIL; } #else @@ -417,7 +463,7 @@ int server_loop(struct command_context *command_context) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); - exit(-1); + return ERROR_FAIL; } #endif } @@ -536,7 +582,7 @@ int server_preinit(void) if (WSAStartup(wVersionRequested, &wsaData) != 0) { LOG_ERROR("Failed to Open Winsock"); - exit(-1); + return ERROR_FAIL; } /* register ctrl-c handler */ @@ -554,10 +600,18 @@ int server_preinit(void) int server_init(struct command_context *cmd_ctx) { int ret = tcl_init(); - if (ERROR_OK != ret) + + if (ret != ERROR_OK) + return ret; + + ret = telnet_init("Open On-Chip Debugger"); + + if (ret != ERROR_OK) { + remove_services(); return ret; + } - return telnet_init("Open On-Chip Debugger"); + return ERROR_OK; } int server_quit(void) @@ -634,6 +688,22 @@ COMMAND_HANDLER(handle_poll_period_command) return ERROR_OK; } +COMMAND_HANDLER(handle_bindto_command) +{ + switch (CMD_ARGC) { + case 0: + command_print(CMD_CTX, "bindto name: %s", bindto_name); + break; + case 1: + free(bindto_name); + bindto_name = strdup(CMD_ARGV[0]); + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + return ERROR_OK; +} + static const struct command_registration server_command_handlers[] = { { .name = "shutdown", @@ -649,6 +719,14 @@ static const struct command_registration server_command_handlers[] = { .usage = "", .help = "set the servers polling period", }, + { + .name = "bindto", + .handler = &handle_bindto_command, + .mode = COMMAND_ANY, + .usage = "[name]", + .help = "Specify address by name on which to listen for " + "incoming TCP/IP connections", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/server/server.h b/src/server/server.h index 061523346..68ad16d55 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef SERVER_H -#define SERVER_H +#ifndef OPENOCD_SERVER_SERVER_H +#define OPENOCD_SERVER_SERVER_H #include @@ -111,4 +109,4 @@ COMMAND_HELPER(server_port_command, unsigned short *out); #define ERROR_SERVER_REMOTE_CLOSED (-400) #define ERROR_CONNECTION_REJECTED (-401) -#endif /* SERVER_H */ +#endif /* OPENOCD_SERVER_SERVER_H */ diff --git a/src/server/server_stubs.c b/src/server/server_stubs.c index 4584f3199..a4c017289 100644 --- a/src/server/server_stubs.c +++ b/src/server/server_stubs.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 789eee8b6..0077339f2 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -107,7 +105,7 @@ static int tcl_target_callback_trace_handler(struct target *target, if (tclc->tc_trace) { hex = malloc(hex_len); buf = malloc(max_len); - hexify(hex, (const char *)data, len, hex_len); + hexify(hex, data, len, hex_len); snprintf(buf, max_len, "%s%s%s", header, hex, trailer); tcl_output(connection, buf, strlen(buf)); free(hex); diff --git a/src/server/tcl_server.h b/src/server/tcl_server.h index 971ab996a..422c794ee 100644 --- a/src/server/tcl_server.h +++ b/src/server/tcl_server.h @@ -12,17 +12,15 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _TCL_SERVER_H_ -#define _TCL_SERVER_H_ +#ifndef OPENOCD_SERVER_TCL_SERVER_H +#define OPENOCD_SERVER_TCL_SERVER_H #include int tcl_init(void); int tcl_register_commands(struct command_context *cmd_ctx); -#endif /* _TCL_SERVER_H_ */ +#endif /* OPENOCD_SERVER_TCL_SERVER_H */ diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 2187dbe28..e33188b5e 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -207,10 +205,17 @@ static void telnet_save_history(struct telnet_connection *t_con) static int telnet_new_connection(struct connection *connection) { - struct telnet_connection *telnet_connection = malloc(sizeof(struct telnet_connection)); + struct telnet_connection *telnet_connection; struct telnet_service *telnet_service = connection->service->priv; int i; + telnet_connection = malloc(sizeof(struct telnet_connection)); + + if (!telnet_connection) { + LOG_ERROR("Failed to allocate telnet connection."); + return ERROR_FAIL; + } + connection->priv = telnet_connection; /* initialize telnet connection information */ @@ -568,7 +573,7 @@ static int telnet_input(struct connection *connection) break; default: LOG_ERROR("unknown telnet state"); - exit(-1); + return ERROR_FAIL; } bytes_read--; @@ -619,17 +624,26 @@ int telnet_init(char *banner) return ERROR_OK; } - struct telnet_service *telnet_service = malloc(sizeof(struct telnet_service)); + struct telnet_service *telnet_service = + malloc(sizeof(struct telnet_service)); + + if (!telnet_service) { + LOG_ERROR("Failed to allocate telnet service."); + return ERROR_FAIL; + } telnet_service->banner = banner; - return add_service("telnet", - telnet_port, - CONNECTION_LIMIT_UNLIMITED, - telnet_new_connection, - telnet_input, - telnet_connection_closed, + int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED, + telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service); + + if (ret != ERROR_OK) { + free(telnet_service); + return ret; + } + + return ERROR_OK; } /* daemon configuration command telnet_port */ diff --git a/src/server/telnet_server.h b/src/server/telnet_server.h index 94da3d1bc..04ba96570 100644 --- a/src/server/telnet_server.h +++ b/src/server/telnet_server.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TELNET_SERVER_H -#define TELNET_SERVER_H +#ifndef OPENOCD_SERVER_TELNET_SERVER_H +#define OPENOCD_SERVER_TELNET_SERVER_H #include @@ -69,4 +67,4 @@ struct telnet_service { int telnet_init(char *banner); int telnet_register_commands(struct command_context *command_context); -#endif /* TELNET_SERVER_H */ +#endif /* OPENOCD_SERVER_TELNET_SERVER_H */ diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am index 3a14d2087..5603d53b5 100644 --- a/src/svf/Makefile.am +++ b/src/svf/Makefile.am @@ -1,8 +1,2 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libsvf.la -noinst_HEADERS = svf.h -libsvf_la_SOURCES = svf.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libsvf.la +%C%_libsvf_la_SOURCES = %D%/svf.c %D%/svf.h diff --git a/src/svf/svf.c b/src/svf/svf.c index 7b7b8d09d..e7e815c10 100644 --- a/src/svf/svf.c +++ b/src/svf/svf.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* The specification for SVF is available here: @@ -363,7 +361,7 @@ COMMAND_HANDLER(handle_svf_command) #define SVF_MAX_NUM_OF_OPTIONS 5 int command_num = 0; int ret = ERROR_OK; - long long time_measure_ms; + int64_t time_measure_ms; int time_measure_s, time_measure_m; /* use NULL to indicate a "plain" svf file which accounts for @@ -537,7 +535,7 @@ COMMAND_HANDLER(handle_svf_command) time_measure_s %= 60; if (time_measure_ms < 1000) command_print(CMD_CTX, - "\r\nTime used: %dm%ds%lldms ", + "\r\nTime used: %dm%ds%" PRId64 "ms ", time_measure_m, time_measure_s, time_measure_ms); diff --git a/src/svf/svf.h b/src/svf/svf.h index 4f2ac0a9b..4101a3f85 100644 --- a/src/svf/svf.h +++ b/src/svf/svf.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef SVF_H -#define SVF_H +#ifndef OPENOCD_SVF_SVF_H +#define OPENOCD_SVF_SVF_H #include @@ -46,4 +44,4 @@ int svf_add_statemove(tap_state_t goal_state); */ bool svf_tap_state_is_stable(tap_state_t state); -#endif /* SVF_H */ +#endif /* OPENOCD_SVF_SVF_H */ diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 9f47b1fd8..1e81f4a13 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -1,31 +1,15 @@ -include $(top_srcdir)/common.mk - if OOCD_TRACE -OOCD_TRACE_FILES = oocd_trace.c +OOCD_TRACE_FILES = %D%/oocd_trace.c else OOCD_TRACE_FILES = endif -SUBDIRS = openrisc -libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la - -BIN2C = $(top_srcdir)/src/helper/bin2char.sh - -DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin -EXTRA_DIST = \ - startup.tcl \ - $(wildcard $(srcdir)/xscale/*) +%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la -DEBUG_HEADER = xscale_debug.inc -BUILT_SOURCES = $(DEBUG_HEADER) -CLEANFILES = $(DEBUG_HEADER) +STARTUP_TCL_SRCS += %D%/startup.tcl -$(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C) - $(BIN2C) < $< > $@ || { rm -f $@; false; } - -METASOURCES = AUTO -noinst_LTLIBRARIES = libtarget.la -libtarget_la_SOURCES = \ +noinst_LTLIBRARIES += %D%/libtarget.la +%C%_libtarget_la_SOURCES = \ $(TARGET_CORE_SRC) \ $(ARM_DEBUG_SRC) \ $(ARMV4_5_SRC) \ @@ -36,176 +20,201 @@ libtarget_la_SOURCES = \ $(MIPS32_SRC) \ $(NDS32_SRC) \ $(INTEL_IA32_SRC) \ - avrt.c \ - dsp563xx.c \ - dsp563xx_once.c \ - dsp5680xx.c \ - hla_target.c + $(RISCV_SRC) \ + %D%/avrt.c \ + %D%/dsp563xx.c \ + %D%/dsp563xx_once.c \ + %D%/dsp5680xx.c \ + %D%/hla_target.c + +if TARGET64 +%C%_libtarget_la_SOURCES +=$(ARMV8_SRC) +endif TARGET_CORE_SRC = \ - algorithm.c \ - register.c \ - image.c \ - breakpoints.c \ - target.c \ - target_request.c \ - testee.c \ - smp.c + %D%/algorithm.c \ + %D%/register.c \ + %D%/image.c \ + %D%/breakpoints.c \ + %D%/target.c \ + %D%/target_request.c \ + %D%/testee.c \ + %D%/smp.c ARMV4_5_SRC = \ - armv4_5.c \ - armv4_5_mmu.c \ - armv4_5_cache.c \ + %D%/armv4_5.c \ + %D%/armv4_5_mmu.c \ + %D%/armv4_5_cache.c \ $(ARM7_9_SRC) ARM7_9_SRC = \ - arm7_9_common.c \ - arm7tdmi.c \ - arm720t.c \ - arm9tdmi.c \ - arm920t.c \ - arm966e.c \ - arm946e.c \ - arm926ejs.c \ - feroceon.c + %D%/arm7_9_common.c \ + %D%/arm7tdmi.c \ + %D%/arm720t.c \ + %D%/arm9tdmi.c \ + %D%/arm920t.c \ + %D%/arm966e.c \ + %D%/arm946e.c \ + %D%/arm926ejs.c \ + %D%/feroceon.c ARM_MISC_SRC = \ - fa526.c \ - xscale.c + %D%/fa526.c \ + %D%/xscale.c ARMV6_SRC = \ - arm11.c \ - arm11_dbgtap.c + %D%/arm11.c \ + %D%/arm11_dbgtap.c ARMV7_SRC = \ - armv7m.c \ - armv7m_trace.c \ - cortex_m.c \ - armv7a.c \ - cortex_a.c + %D%/armv7m.c \ + %D%/armv7m_trace.c \ + %D%/cortex_m.c \ + %D%/armv7a.c \ + %D%/cortex_a.c \ + %D%/ls1_sap.c + +ARMV8_SRC = \ + %D%/armv8_dpm.c \ + %D%/armv8_opcodes.c \ + %D%/aarch64.c \ + %D%/armv8.c \ + %D%/armv8_cache.c ARM_DEBUG_SRC = \ - arm_dpm.c \ - arm_jtag.c \ - arm_disassembler.c \ - arm_simulator.c \ - arm_semihosting.c \ - arm_adi_v5.c \ - armv7a_cache.c \ - armv7a_cache_l2x.c \ - adi_v5_jtag.c \ - adi_v5_swd.c \ - embeddedice.c \ - trace.c \ - etb.c \ - etm.c \ + %D%/arm_dpm.c \ + %D%/arm_jtag.c \ + %D%/arm_disassembler.c \ + %D%/arm_simulator.c \ + %D%/arm_semihosting.c \ + %D%/arm_adi_v5.c \ + %D%/armv7a_cache.c \ + %D%/armv7a_cache_l2x.c \ + %D%/adi_v5_jtag.c \ + %D%/adi_v5_swd.c \ + %D%/embeddedice.c \ + %D%/trace.c \ + %D%/etb.c \ + %D%/etm.c \ $(OOCD_TRACE_FILES) \ - etm_dummy.c + %D%/etm_dummy.c \ + %D%/arm_cti.c AVR32_SRC = \ - avr32_ap7k.c \ - avr32_jtag.c \ - avr32_mem.c \ - avr32_regs.c + %D%/avr32_ap7k.c \ + %D%/avr32_jtag.c \ + %D%/avr32_mem.c \ + %D%/avr32_regs.c MIPS32_SRC = \ - mips32.c \ - mips_m4k.c \ - mips32_pracc.c \ - mips32_dmaacc.c \ - mips_ejtag.c + %D%/mips32.c \ + %D%/mips_m4k.c \ + %D%/mips32_pracc.c \ + %D%/mips32_dmaacc.c \ + %D%/mips_ejtag.c NDS32_SRC = \ - nds32.c \ - nds32_reg.c \ - nds32_cmd.c \ - nds32_disassembler.c \ - nds32_tlb.c \ - nds32_v2.c \ - nds32_v3_common.c \ - nds32_v3.c \ - nds32_v3m.c \ - nds32_aice.c + %D%/nds32.c \ + %D%/nds32_reg.c \ + %D%/nds32_cmd.c \ + %D%/nds32_disassembler.c \ + %D%/nds32_tlb.c \ + %D%/nds32_v2.c \ + %D%/nds32_v3_common.c \ + %D%/nds32_v3.c \ + %D%/nds32_v3m.c \ + %D%/nds32_aice.c INTEL_IA32_SRC = \ - quark_x10xx.c \ - lakemont.c \ - x86_32_common.c - -noinst_HEADERS = \ - algorithm.h \ - arm.h \ - arm_dpm.h \ - arm_jtag.h \ - arm_adi_v5.h \ - armv7a_cache.h \ - armv7a_cache_l2x.h \ - arm_disassembler.h \ - arm_opcodes.h \ - arm_simulator.h \ - arm_semihosting.h \ - arm7_9_common.h \ - arm7tdmi.h \ - arm720t.h \ - arm9tdmi.h \ - arm920t.h \ - arm926ejs.h \ - arm966e.h \ - arm946e.h \ - arm11.h \ - arm11_dbgtap.h \ - armv4_5.h \ - armv4_5_mmu.h \ - armv4_5_cache.h \ - armv7a.h \ - armv7m.h \ - armv7m_trace.h \ - avrt.h \ - dsp563xx.h \ - dsp563xx_once.h \ - dsp5680xx.h \ - breakpoints.h \ - cortex_m.h \ - cortex_a.h \ - embeddedice.h \ - etb.h \ - etm.h \ - etm_dummy.h \ - image.h \ - mips32.h \ - mips_m4k.h \ - mips_ejtag.h \ - mips32_pracc.h \ - mips32_dmaacc.h \ - oocd_trace.h \ - register.h \ - target.h \ - target_type.h \ - trace.h \ - target_request.h \ - trace.h \ - xscale.h \ - smp.h \ - avr32_ap7k.h \ - avr32_jtag.h \ - avr32_mem.h \ - avr32_regs.h \ - nds32.h \ - nds32_cmd.h \ - nds32_disassembler.h \ - nds32_edm.h \ - nds32_insn.h \ - nds32_reg.h \ - nds32_tlb.h \ - nds32_v2.h \ - nds32_v3_common.h \ - nds32_v3.h \ - nds32_v3m.h \ - nds32_aice.h \ - lakemont.h \ - x86_32_common.h - -ocddatadir = $(pkglibdir) -nobase_dist_ocddata_DATA = - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + %D%/quark_x10xx.c \ + %D%/quark_d20xx.c \ + %D%/lakemont.c \ + %D%/x86_32_common.c + +RISCV_SRC = \ + %D%/riscv/riscv-011.c \ + %D%/riscv/riscv-013.c \ + %D%/riscv/riscv.c \ + %D%/riscv/program.c \ + %D%/riscv/batch.c + +%C%_libtarget_la_SOURCES += \ + %D%/algorithm.h \ + %D%/arm.h \ + %D%/arm_dpm.h \ + %D%/arm_jtag.h \ + %D%/arm_adi_v5.h \ + %D%/armv7a_cache.h \ + %D%/armv7a_cache_l2x.h \ + %D%/arm_disassembler.h \ + %D%/arm_opcodes.h \ + %D%/arm_simulator.h \ + %D%/arm_semihosting.h \ + %D%/arm7_9_common.h \ + %D%/arm7tdmi.h \ + %D%/arm720t.h \ + %D%/arm9tdmi.h \ + %D%/arm920t.h \ + %D%/arm926ejs.h \ + %D%/arm966e.h \ + %D%/arm946e.h \ + %D%/arm11.h \ + %D%/arm11_dbgtap.h \ + %D%/armv4_5.h \ + %D%/armv4_5_mmu.h \ + %D%/armv4_5_cache.h \ + %D%/armv7a.h \ + %D%/armv7m.h \ + %D%/armv7m_trace.h \ + %D%/armv8.h \ + %D%/armv8_dpm.h \ + %D%/armv8_opcodes.h \ + %D%/armv8_cache.h \ + %D%/avrt.h \ + %D%/dsp563xx.h \ + %D%/dsp563xx_once.h \ + %D%/dsp5680xx.h \ + %D%/breakpoints.h \ + %D%/cortex_m.h \ + %D%/cortex_a.h \ + %D%/aarch64.h \ + %D%/embeddedice.h \ + %D%/etb.h \ + %D%/etm.h \ + %D%/etm_dummy.h \ + %D%/image.h \ + %D%/mips32.h \ + %D%/mips_m4k.h \ + %D%/mips_ejtag.h \ + %D%/mips32_pracc.h \ + %D%/mips32_dmaacc.h \ + %D%/oocd_trace.h \ + %D%/register.h \ + %D%/target.h \ + %D%/target_type.h \ + %D%/trace.h \ + %D%/target_request.h \ + %D%/trace.h \ + %D%/xscale.h \ + %D%/smp.h \ + %D%/avr32_ap7k.h \ + %D%/avr32_jtag.h \ + %D%/avr32_mem.h \ + %D%/avr32_regs.h \ + %D%/nds32.h \ + %D%/nds32_cmd.h \ + %D%/nds32_disassembler.h \ + %D%/nds32_edm.h \ + %D%/nds32_insn.h \ + %D%/nds32_reg.h \ + %D%/nds32_tlb.h \ + %D%/nds32_v2.h \ + %D%/nds32_v3_common.h \ + %D%/nds32_v3.h \ + %D%/nds32_v3m.h \ + %D%/nds32_aice.h \ + %D%/lakemont.h \ + %D%/x86_32_common.h \ + %D%/arm_cti.h + +include %D%/openrisc/Makefile.am diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 77d714115..c7dc4f7c9 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -21,9 +21,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . ***************************************************************************/ /** @@ -39,6 +37,9 @@ #include "arm.h" #include "arm_adi_v5.h" #include +#include + +/*#define DEBUG_WAIT*/ /* JTAG instructions/registers for JTAG-DP and SWJ-DP */ #define JTAG_DP_ABORT 0x8 @@ -52,12 +53,198 @@ static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack); +#ifdef DEBUG_WAIT +static const char *dap_reg_name(int instr, int reg_addr) +{ + char *reg_name = "UNK"; + + if (instr == JTAG_DP_DPACC) { + switch (reg_addr) { + case DP_ABORT: + reg_name = "ABORT"; + break; + case DP_CTRL_STAT: + reg_name = "CTRL/STAT"; + break; + case DP_SELECT: + reg_name = "SELECT"; + break; + case DP_RDBUFF: + reg_name = "RDBUFF"; + break; + case DP_WCR: + reg_name = "WCR"; + break; + default: + reg_name = "UNK"; + break; + } + } + + if (instr == JTAG_DP_APACC) { + switch (reg_addr) { + case MEM_AP_REG_CSW: + reg_name = "CSW"; + break; + case MEM_AP_REG_TAR: + reg_name = "TAR"; + break; + case MEM_AP_REG_DRW: + reg_name = "DRW"; + break; + case MEM_AP_REG_BD0: + reg_name = "BD0"; + break; + case MEM_AP_REG_BD1: + reg_name = "BD1"; + break; + case MEM_AP_REG_BD2: + reg_name = "BD2"; + break; + case MEM_AP_REG_BD3: + reg_name = "BD3"; + break; + case MEM_AP_REG_CFG: + reg_name = "CFG"; + break; + case MEM_AP_REG_BASE: + reg_name = "BASE"; + break; + case AP_REG_IDR: + reg_name = "IDR"; + break; + default: + reg_name = "UNK"; + break; + } + } + + return reg_name; +} +#endif + +struct dap_cmd { + struct list_head lh; + uint8_t instr; + uint8_t reg_addr; + uint8_t RnW; + uint8_t *invalue; + uint8_t ack; + uint32_t memaccess_tck; + uint32_t dp_select; + + struct scan_field fields[2]; + uint8_t out_addr_buf; + uint8_t invalue_buf[4]; + uint8_t outvalue_buf[4]; +}; + +static void log_dap_cmd(const char *header, struct dap_cmd *el) +{ +#ifdef DEBUG_WAIT + LOG_DEBUG("%s: %2s %6s %5s 0x%08x 0x%08x %2s", header, + el->instr == JTAG_DP_APACC ? "AP" : "DP", + dap_reg_name(el->instr, el->reg_addr), + el->RnW == DPAP_READ ? "READ" : "WRITE", + buf_get_u32(el->outvalue_buf, 0, 32), + buf_get_u32(el->invalue, 0, 32), + el->ack == JTAG_ACK_OK_FAULT ? "OK" : + (el->ack == JTAG_ACK_WAIT ? "WAIT" : "INVAL")); +#endif +} + +static struct dap_cmd *dap_cmd_new(uint8_t instr, + uint8_t reg_addr, uint8_t RnW, + uint8_t *outvalue, uint8_t *invalue, + uint32_t memaccess_tck) +{ + struct dap_cmd *cmd; + + cmd = (struct dap_cmd *)calloc(1, sizeof(struct dap_cmd)); + if (cmd != NULL) { + INIT_LIST_HEAD(&cmd->lh); + cmd->instr = instr; + cmd->reg_addr = reg_addr; + cmd->RnW = RnW; + if (outvalue != NULL) + memcpy(cmd->outvalue_buf, outvalue, 4); + cmd->invalue = (invalue != NULL) ? invalue : cmd->invalue_buf; + cmd->memaccess_tck = memaccess_tck; + } + + return cmd; +} + +static void flush_journal(struct list_head *lh) +{ + struct dap_cmd *el, *tmp; + + list_for_each_entry_safe(el, tmp, lh, lh) { + list_del(&el->lh); + free(el); + } +} + /*************************************************************************** * * DPACC and APACC scanchain access through JTAG-DP (or SWJ-DP) * ***************************************************************************/ +static int adi_jtag_dp_scan_cmd(struct adiv5_dap *dap, struct dap_cmd *cmd, uint8_t *ack) +{ + struct jtag_tap *tap = dap->tap; + int retval; + + retval = arm_jtag_set_instr(tap, cmd->instr, NULL, TAP_IDLE); + if (retval != ERROR_OK) + return retval; + + /* Scan out a read or write operation using some DP or AP register. + * For APACC access with any sticky error flag set, this is discarded. + */ + cmd->fields[0].num_bits = 3; + buf_set_u32(&cmd->out_addr_buf, 0, 3, ((cmd->reg_addr >> 1) & 0x6) | (cmd->RnW & 0x1)); + cmd->fields[0].out_value = &cmd->out_addr_buf; + cmd->fields[0].in_value = (ack != NULL) ? ack : &cmd->ack; + + /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not + * complete; data we write is discarded, data we read is unpredictable. + * When overrun detect is active, STICKYORUN is set. + */ + + cmd->fields[1].num_bits = 32; + cmd->fields[1].out_value = cmd->outvalue_buf; + cmd->fields[1].in_value = cmd->invalue; + + jtag_add_dr_scan(tap, 2, cmd->fields, TAP_IDLE); + + /* Add specified number of tck clocks after starting memory bus + * access, giving the hardware time to complete the access. + * They provide more time for the (MEM) AP to complete the read ... + * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. + */ + if (cmd->instr == JTAG_DP_APACC) { + if (((cmd->reg_addr == MEM_AP_REG_DRW) + || ((cmd->reg_addr & 0xF0) == MEM_AP_REG_BD0)) + && (cmd->memaccess_tck != 0)) + jtag_add_runtest(cmd->memaccess_tck, TAP_IDLE); + } + + return ERROR_OK; +} + +static int adi_jtag_dp_scan_cmd_sync(struct adiv5_dap *dap, struct dap_cmd *cmd, uint8_t *ack) +{ + int retval; + + retval = adi_jtag_dp_scan_cmd(dap, cmd, ack); + if (retval != ERROR_OK) + return retval; + + return jtag_execute_queue(); +} + /** * Scan DPACC or APACC using target ordered uint8_t buffers. No endianness * conversions are performed. See section 4.4.3 of the ADIv5 spec, which @@ -80,49 +267,23 @@ static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack); static int adi_jtag_dp_scan(struct adiv5_dap *dap, uint8_t instr, uint8_t reg_addr, uint8_t RnW, - uint8_t *outvalue, uint8_t *invalue, uint8_t *ack, - uint32_t memaccess_tck) + uint8_t *outvalue, uint8_t *invalue, + uint32_t memaccess_tck, uint8_t *ack) { - struct jtag_tap *tap = dap->tap; - struct scan_field fields[2]; - uint8_t out_addr_buf; + struct dap_cmd *cmd; int retval; - retval = arm_jtag_set_instr(tap, instr, NULL, TAP_IDLE); - if (retval != ERROR_OK) - return retval; - - /* Scan out a read or write operation using some DP or AP register. - * For APACC access with any sticky error flag set, this is discarded. - */ - fields[0].num_bits = 3; - buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); - fields[0].out_value = &out_addr_buf; - fields[0].in_value = ack; - - /* NOTE: if we receive JTAG_ACK_WAIT, the previous operation did not - * complete; data we write is discarded, data we read is unpredictable. - * When overrun detect is active, STICKYORUN is set. - */ - - fields[1].num_bits = 32; - fields[1].out_value = outvalue; - fields[1].in_value = invalue; - - jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); + cmd = dap_cmd_new(instr, reg_addr, RnW, outvalue, invalue, memaccess_tck); + if (cmd != NULL) + cmd->dp_select = dap->select; + else + return ERROR_JTAG_DEVICE_ERROR; - /* Add specified number of tck clocks after starting memory bus - * access, giving the hardware time to complete the access. - * They provide more time for the (MEM) AP to complete the read ... - * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. - */ - if ((instr == JTAG_DP_APACC) - && ((reg_addr == MEM_AP_REG_DRW) - || ((reg_addr & 0xF0) == MEM_AP_REG_BD0)) - && memaccess_tck != 0) - jtag_add_runtest(memaccess_tck, TAP_IDLE); + retval = adi_jtag_dp_scan_cmd(dap, cmd, ack); + if (retval == ERROR_OK) + list_add_tail(&cmd->lh, &dap->cmd_journal); - return ERROR_OK; + return retval; } /** @@ -133,8 +294,8 @@ static int adi_jtag_dp_scan(struct adiv5_dap *dap, */ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, uint8_t instr, uint8_t reg_addr, uint8_t RnW, - uint32_t outvalue, uint32_t *invalue, uint8_t *ack, - uint32_t memaccess_tck) + uint32_t outvalue, uint32_t *invalue, + uint32_t memaccess_tck, uint8_t *ack) { uint8_t out_value_buf[4]; int retval; @@ -142,7 +303,7 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, buf_set_u32(out_value_buf, 0, 32, outvalue); retval = adi_jtag_dp_scan(dap, instr, reg_addr, RnW, - out_value_buf, (uint8_t *)invalue, ack, memaccess_tck); + out_value_buf, (uint8_t *)invalue, memaccess_tck, ack); if (retval != ERROR_OK) return retval; @@ -153,13 +314,17 @@ static int adi_jtag_dp_scan_u32(struct adiv5_dap *dap, return retval; } -static void adi_jtag_finish_read(struct adiv5_dap *dap) +static int adi_jtag_finish_read(struct adiv5_dap *dap) { + int retval = ERROR_OK; + if (dap->last_read != NULL) { - adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, - DP_RDBUFF, DPAP_READ, 0, dap->last_read, &dap->ack, 0); + retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, + DP_RDBUFF, DPAP_READ, 0, dap->last_read, 0, NULL); dap->last_read = NULL; } + + return retval; } static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap, @@ -170,143 +335,265 @@ static int adi_jtag_scan_inout_check_u32(struct adiv5_dap *dap, /* Issue the read or write */ retval = adi_jtag_dp_scan_u32(dap, instr, reg_addr, - RnW, outvalue, NULL, NULL, memaccess_tck); + RnW, outvalue, NULL, memaccess_tck, NULL); if (retval != ERROR_OK) return retval; /* For reads, collect posted value; RDBUFF has no other effect. * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK". */ - if ((RnW == DPAP_READ) && (invalue != NULL)) + if ((RnW == DPAP_READ) && (invalue != NULL)) { retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, - DP_RDBUFF, DPAP_READ, 0, invalue, &dap->ack, 0); - return retval; + DP_RDBUFF, DPAP_READ, 0, invalue, 0, NULL); + if (retval != ERROR_OK) + return retval; + } + + return jtag_execute_queue(); } -static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) +static int jtagdp_overrun_check(struct adiv5_dap *dap) { int retval; - uint32_t ctrlstat; + struct dap_cmd *el, *tmp, *prev = NULL; + int found_wait = 0; + int64_t time_now; + LIST_HEAD(replay_list); - /* too expensive to call keep_alive() here */ + /* make sure all queued transactions are complete */ + retval = jtag_execute_queue(); + if (retval != ERROR_OK) + goto done; + + /* skip all completed transactions up to the first WAIT */ + list_for_each_entry(el, &dap->cmd_journal, lh) { + if (el->ack == JTAG_ACK_OK_FAULT) { + log_dap_cmd("LOG", el); + } else if (el->ack == JTAG_ACK_WAIT) { + found_wait = 1; + break; + } else { + LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack); + log_dap_cmd("ERR", el); + retval = ERROR_JTAG_DEVICE_ERROR; + goto done; + } + } - /* Here be dragons! - * - * It is easy to be in a JTAG clock range where the target - * is not operating in a stable fashion. This happens - * for a few reasons: - * - * - the user may construct a simple test case to try to see - * if a higher JTAG clock works to eke out more performance. - * This simple case may pass, but more complex situations can - * fail. - * - * - The mostly works JTAG clock rate and the complete failure - * JTAG clock rate may be as much as 2-4x apart. This seems - * to be especially true on RC oscillator driven parts. - * - * So: even if calling adi_jtag_scan_inout_check_u32() multiple - * times here seems to "make things better here", it is just - * hiding problems with too high a JTAG clock. - * - * Note that even if some parts have RCLK/RTCK, that doesn't - * mean that RCLK/RTCK is the *correct* rate to run the JTAG - * interface at, i.e. RCLK/RTCK rates can be "too high", especially - * before the RC oscillator phase is not yet complete. + /* + * If we found a stalled transaction and a previous transaction + * exists, check if it's a READ access. */ + if (found_wait && el != list_first_entry(&dap->cmd_journal, struct dap_cmd, lh)) { + prev = list_entry(el->lh.prev, struct dap_cmd, lh); + if (prev->RnW == DPAP_READ) { + log_dap_cmd("PND", prev); + /* search for the next OK transaction, it contains + * the result of the previous READ */ + tmp = el; + list_for_each_entry_from(tmp, &dap->cmd_journal, lh) { + if (tmp->ack == JTAG_ACK_OK_FAULT) { + /* recover the read value */ + log_dap_cmd("FND", tmp); + if (el->invalue != el->invalue_buf) { + uint32_t invalue = le_to_h_u32(tmp->invalue); + memcpy(el->invalue, &invalue, sizeof(uint32_t)); + } + prev = NULL; + break; + } + } - /* Post CTRL/STAT read; discard any previous posted read value - * but collect its ACK status. - */ - retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, - DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0); - if (retval != ERROR_OK) - return retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) - return retval; + if (prev != NULL) { + log_dap_cmd("LST", el); + + /* + * At this point we're sure that no previous + * transaction completed and the DAP/AP is still + * in busy state. We know that the next "OK" scan + * will return the READ result we need to recover. + * To complete the READ, we just keep polling RDBUFF + * until the WAIT condition clears + */ + tmp = dap_cmd_new(JTAG_DP_DPACC, + DP_RDBUFF, DPAP_READ, NULL, NULL, 0); + if (tmp == NULL) { + retval = ERROR_JTAG_DEVICE_ERROR; + goto done; + } + /* synchronously retry the command until it succeeds */ + time_now = timeval_ms(); + do { + retval = adi_jtag_dp_scan_cmd_sync(dap, tmp, NULL); + if (retval != ERROR_OK) + break; + if (tmp->ack == JTAG_ACK_OK_FAULT) { + log_dap_cmd("FND", tmp); + if (el->invalue != el->invalue_buf) { + uint32_t invalue = le_to_h_u32(tmp->invalue); + memcpy(el->invalue, &invalue, sizeof(uint32_t)); + } + break; + } + if (tmp->ack != JTAG_ACK_WAIT) { + LOG_ERROR("Invalid ACK (%1x) in DAP response", tmp->ack); + log_dap_cmd("ERR", tmp); + retval = ERROR_JTAG_DEVICE_ERROR; + break; + } + + } while (timeval_ms() - time_now < 1000); + + if (retval == ERROR_OK) { + /* timeout happened */ + if (tmp->ack != JTAG_ACK_OK_FAULT) { + LOG_ERROR("Timeout during WAIT recovery"); + dap->select = DP_SELECT_INVALID; + jtag_ap_q_abort(dap, NULL); + /* clear the sticky overrun condition */ + adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_WRITE, + dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0); + retval = ERROR_JTAG_DEVICE_ERROR; + } + } - dap->ack = dap->ack & 0x7; + /* we're done with this command, release it */ + free(tmp); - /* common code path avoids calling timeval_ms() */ - if (dap->ack != JTAG_ACK_OK_FAULT) { - long long then = timeval_ms(); + if (retval != ERROR_OK) + goto done; - while (dap->ack != JTAG_ACK_OK_FAULT) { - if (dap->ack == JTAG_ACK_WAIT) { - if ((timeval_ms()-then) > 1000) { - LOG_WARNING("Timeout (1000ms) waiting " - "for ACK=OK/FAULT " - "in JTAG-DP transaction - aborting"); + } + /* make el->invalue point to the default invalue + * so that we can safely retry it without clobbering + * the result we just recovered */ + el->invalue = el->invalue_buf; + } + } - uint8_t ack; - int abort_ret = jtag_ap_q_abort(dap, &ack); + /* move all remaining transactions over to the replay list */ + list_for_each_entry_safe_from(el, tmp, &dap->cmd_journal, lh) { + log_dap_cmd("REP", el); + list_move_tail(&el->lh, &replay_list); + } - if (abort_ret != 0) - LOG_WARNING("Abort failed : return=%d ack=%d", abort_ret, ack); + /* we're done with the journal, flush it */ + flush_journal(&dap->cmd_journal); - return ERROR_JTAG_DEVICE_ERROR; - } - } else { - LOG_WARNING("Invalid ACK %#x " - "in JTAG-DP transaction", - dap->ack); - return ERROR_JTAG_DEVICE_ERROR; + /* check for overrun condition in the last batch of transactions */ + if (found_wait) { + LOG_INFO("DAP transaction stalled (WAIT) - slowing down"); + /* clear the sticky overrun condition */ + retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_WRITE, + dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0); + if (retval != ERROR_OK) + goto done; + + /* restore SELECT register first */ + if (!list_empty(&replay_list)) { + el = list_first_entry(&replay_list, struct dap_cmd, lh); + tmp = dap_cmd_new(JTAG_DP_DPACC, + DP_SELECT, DPAP_WRITE, (uint8_t *)&el->dp_select, NULL, 0); + if (tmp == NULL) { + retval = ERROR_JTAG_DEVICE_ERROR; + goto done; } + list_add(&tmp->lh, &replay_list); - retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, - DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0); - if (retval != ERROR_OK) - return retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) - return retval; - dap->ack = dap->ack & 0x7; + dap->select = DP_SELECT_INVALID; + } + + list_for_each_entry_safe(el, tmp, &replay_list, lh) { + time_now = timeval_ms(); + do { + retval = adi_jtag_dp_scan_cmd_sync(dap, el, NULL); + if (retval != ERROR_OK) + break; + log_dap_cmd("REC", el); + if (el->ack == JTAG_ACK_OK_FAULT) { + if (el->invalue != el->invalue_buf) { + uint32_t invalue = le_to_h_u32(el->invalue); + memcpy(el->invalue, &invalue, sizeof(uint32_t)); + } + break; + } + if (el->ack != JTAG_ACK_WAIT) { + LOG_ERROR("Invalid ACK (%1x) in DAP response", el->ack); + log_dap_cmd("ERR", el); + retval = ERROR_JTAG_DEVICE_ERROR; + break; + } + } while (timeval_ms() - time_now < 1000); + + if (retval == ERROR_OK) { + if (el->ack != JTAG_ACK_OK_FAULT) { + LOG_ERROR("Timeout during WAIT recovery"); + dap->select = DP_SELECT_INVALID; + jtag_ap_q_abort(dap, NULL); + /* clear the sticky overrun condition */ + adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_WRITE, + dap->dp_ctrl_stat | SSTICKYORUN, NULL, 0); + retval = ERROR_JTAG_DEVICE_ERROR; + break; + } + } else + break; } } + done: + flush_journal(&replay_list); + flush_journal(&dap->cmd_journal); + return retval; +} + +static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) +{ + int retval; + uint32_t ctrlstat; + + /* too expensive to call keep_alive() here */ + + /* Post CTRL/STAT read; discard any previous posted read value + * but collect its ACK status. + */ + retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0); + if (retval != ERROR_OK) + goto done; + /* REVISIT also STICKYCMP, for pushed comparisons (nyet used) */ - /* Check for STICKYERR and STICKYORUN */ - if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) { - LOG_DEBUG("jtag-dp: CTRL/STAT error, 0x%" PRIx32, ctrlstat); + /* Check for STICKYERR */ + if (ctrlstat & SSTICKYERR) { + LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat); /* Check power to debug regions */ if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) != (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) { LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened"); - return ERROR_JTAG_DEVICE_ERROR; - } else { - if (ctrlstat & SSTICKYORUN) - LOG_ERROR("JTAG-DP OVERRUN - check clock, " - "memaccess, or reduce jtag speed"); - - if (ctrlstat & SSTICKYERR) - LOG_ERROR("JTAG-DP STICKY ERROR"); - - /* Clear Sticky Error Bits */ - retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, - DP_CTRL_STAT, DPAP_WRITE, - dap->dp_ctrl_stat | SSTICKYORUN - | SSTICKYERR, NULL, 0); - if (retval != ERROR_OK) - return retval; - retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, - DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat, 0); - if (retval != ERROR_OK) - return retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("jtag-dp: CTRL/STAT 0x%" PRIx32, ctrlstat); } - retval = jtag_execute_queue(); + + if (ctrlstat & SSTICKYERR) + LOG_ERROR("JTAG-DP STICKY ERROR"); + if (ctrlstat & SSTICKYORUN) + LOG_DEBUG("JTAG-DP STICKY OVERRUN"); + + /* Clear Sticky Error Bits */ + retval = adi_jtag_scan_inout_check_u32(dap, JTAG_DP_DPACC, + DP_CTRL_STAT, DPAP_WRITE, + dap->dp_ctrl_stat | SSTICKYERR, NULL, 0); if (retval != ERROR_OK) - return retval; - return ERROR_JTAG_DEVICE_ERROR; + goto done; + + retval = ERROR_JTAG_DEVICE_ERROR; } - return ERROR_OK; + done: + flush_journal(&dap->cmd_journal); + return retval; } /*--------------------------------------------------------------------------*/ @@ -315,7 +602,7 @@ static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg, uint32_t *data) { int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, reg, - DPAP_READ, 0, dap->last_read, &dap->ack, 0); + DPAP_READ, 0, dap->last_read, 0, NULL); dap->last_read = data; return retval; } @@ -324,7 +611,7 @@ static int jtag_dp_q_write(struct adiv5_dap *dap, unsigned reg, uint32_t data) { int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_DPACC, - reg, DPAP_WRITE, data, dap->last_read, &dap->ack, 0); + reg, DPAP_WRITE, data, dap->last_read, 0, NULL); dap->last_read = NULL; return retval; } @@ -351,8 +638,7 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg, return retval; retval = adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg, - DPAP_READ, 0, ap->dap->last_read, &ap->dap->ack, - ap->memaccess_tck); + DPAP_READ, 0, ap->dap->last_read, ap->memaccess_tck, NULL); ap->dap->last_read = data; return retval; @@ -366,8 +652,7 @@ static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg, return retval; retval = adi_jtag_dp_scan_u32(ap->dap, JTAG_DP_APACC, reg, - DPAP_WRITE, data, ap->dap->last_read, &ap->dap->ack, - ap->memaccess_tck); + DPAP_WRITE, data, ap->dap->last_read, ap->memaccess_tck, NULL); ap->dap->last_read = NULL; return retval; } @@ -375,14 +660,32 @@ static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg, static int jtag_ap_q_abort(struct adiv5_dap *dap, uint8_t *ack) { /* for JTAG, this is the only valid ABORT register operation */ - return adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT, - 0, DPAP_WRITE, 1, NULL, ack, 0); + int retval = adi_jtag_dp_scan_u32(dap, JTAG_DP_ABORT, + 0, DPAP_WRITE, 1, NULL, 0, NULL); + if (retval != ERROR_OK) + return retval; + + return jtag_execute_queue(); } static int jtag_dp_run(struct adiv5_dap *dap) { - adi_jtag_finish_read(dap); - return jtagdp_transaction_endcheck(dap); + int retval; + int retval2 = ERROR_OK; + + retval = adi_jtag_finish_read(dap); + if (retval != ERROR_OK) + goto done; + retval2 = jtagdp_overrun_check(dap); + retval = jtagdp_transaction_endcheck(dap); + + done: + return (retval2 != ERROR_OK) ? retval2 : retval; +} + +static int jtag_dp_sync(struct adiv5_dap *dap) +{ + return jtagdp_overrun_check(dap); } /* FIXME don't export ... just initialize as @@ -395,6 +698,7 @@ const struct dap_ops jtag_dp_ops = { .queue_ap_write = jtag_ap_q_write, .queue_ap_abort = jtag_ap_q_abort, .run = jtag_dp_run, + .sync = jtag_dp_sync, }; diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 6990a8b9c..41ddbd789 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . ***************************************************************************/ /** @@ -99,24 +97,36 @@ static int swd_run_inner(struct adiv5_dap *dap) static int swd_connect(struct adiv5_dap *dap) { - uint32_t idcode; + uint32_t dpidr; int status; /* FIXME validate transport config ... is the * configured DAP present (check IDCODE)? * Is *only* one DAP configured? * - * MUST READ IDCODE + * MUST READ DPIDR */ + /* Check if we should reset srst already when connecting, but not if reconnecting. */ + if (!dap->do_reconnect) { + enum reset_types jtag_reset_config = jtag_get_reset_config(); + + if (jtag_reset_config & RESET_CNCT_UNDER_SRST) { + if (jtag_reset_config & RESET_SRST_NO_GATING) + swd_add_reset(1); + else + LOG_WARNING("\'srst_nogate\' reset_config option is required"); + } + } + /* Note, debugport_init() does setup too */ jtag_interface->swd->switch_seq(JTAG_TO_SWD); - /* Make sure we don't try to perform any other accesses before the DPIDR read. */ + /* Clear link state, including the SELECT cache. */ dap->do_reconnect = false; - dap->select = 0; + dap->select = DP_SELECT_INVALID; - swd_queue_dp_read(dap, DP_IDCODE, &idcode); + swd_queue_dp_read(dap, DP_DPIDR, &dpidr); /* force clear all sticky faults */ swd_clear_sticky_errors(dap); @@ -124,7 +134,7 @@ static int swd_connect(struct adiv5_dap *dap) status = swd_run_inner(dap); if (status == ERROR_OK) { - LOG_INFO("SWD IDCODE %#8.8" PRIx32, idcode); + LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr); dap->do_reconnect = false; } else dap->do_reconnect = true; @@ -158,7 +168,8 @@ static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack) /** Select the DP register bank matching bits 7:4 of reg. */ static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg) { - if (reg == DP_SELECT) + /* Only register address 4 is banked. */ + if ((reg & 0xf) != 4) return; uint32_t select_dp_bank = (reg & 0x000000F0) >> 4; @@ -341,61 +352,6 @@ int dap_to_swd(struct target *target) return retval; } -COMMAND_HANDLER(handle_swd_wcr) -{ - int retval; - struct target *target = get_current_target(CMD_CTX); - struct arm *arm = target_to_arm(target); - struct adiv5_dap *dap = arm->dap; - uint32_t wcr; - unsigned trn, scale = 0; - - switch (CMD_ARGC) { - /* no-args: just dump state */ - case 0: - /*retval = swd_queue_dp_read(dap, DP_WCR, &wcr); */ - retval = dap_queue_dp_read(dap, DP_WCR, &wcr); - if (retval == ERROR_OK) - dap->ops->run(dap); - if (retval != ERROR_OK) { - LOG_ERROR("can't read WCR?"); - return retval; - } - - command_print(CMD_CTX, - "turnaround=%" PRIu32 ", prescale=%" PRIu32, - WCR_TO_TRN(wcr), - WCR_TO_PRESCALE(wcr)); - return ERROR_OK; - - case 2: /* TRN and prescale */ - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], scale); - if (scale > 7) { - LOG_ERROR("prescale %d is too big", scale); - return ERROR_FAIL; - } - /* FALL THROUGH */ - - case 1: /* TRN only */ - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], trn); - if (trn < 1 || trn > 4) { - LOG_ERROR("turnaround %d is invalid", trn); - return ERROR_FAIL; - } - - wcr = ((trn - 1) << 8) | scale; - /* FIXME - * write WCR ... - * then, re-init adapter with new TRN - */ - LOG_ERROR("can't yet modify WCR"); - return ERROR_FAIL; - - default: /* too many arguments */ - return ERROR_COMMAND_SYNTAX_ERROR; - } -} - static const struct command_registration swd_commands[] = { { /* @@ -410,15 +366,6 @@ static const struct command_registration swd_commands[] = { .mode = COMMAND_CONFIG, .help = "declare a new SWD DAP" }, - { - .name = "wcr", - .handler = handle_swd_wcr, - .mode = COMMAND_ANY, - .help = "display or update DAP's WCR register", - .usage = "turnaround (1..4), prescale (0..7)", - }, - - /* REVISIT -- add a command for SWV trace on/off */ COMMAND_REGISTRATION_DONE }; @@ -477,6 +424,8 @@ static int swd_init(struct command_context *ctx) /* Force the DAP's ops vector for SWD mode. * messy - is there a better way? */ arm->dap->ops = &swd_dap_ops; + /* First connect after init is not reconnecting. */ + dap->do_reconnect = false; return swd_connect(dap); } diff --git a/src/target/algorithm.c b/src/target/algorithm.c index aa8262a6e..9fc938604 100644 --- a/src/target/algorithm.c +++ b/src/target/algorithm.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/algorithm.h b/src/target/algorithm.h index 2d510db7a..8894241c0 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ALGORITHM_H -#define ALGORITHM_H +#ifndef OPENOCD_TARGET_ALGORITHM_H +#define OPENOCD_TARGET_ALGORITHM_H enum param_direction { PARAM_IN, @@ -28,7 +26,7 @@ enum param_direction { }; struct mem_param { - uint32_t address; + target_addr_t address; uint32_t size; uint8_t *value; enum param_direction direction; @@ -49,4 +47,4 @@ void init_reg_param(struct reg_param *param, char *reg_name, uint32_t size, enum param_direction dir); void destroy_reg_param(struct reg_param *param); -#endif /* ALGORITHM_H */ +#endif /* OPENOCD_TARGET_ALGORITHM_H */ diff --git a/src/target/arm.h b/src/target/arm.h index 27636cc3d..d63ead215 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ -#ifndef ARM_H -#define ARM_H +#ifndef OPENOCD_TARGET_ARM_H +#define OPENOCD_TARGET_ARM_H #include #include "target.h" @@ -61,12 +59,22 @@ enum arm_mode { ARM_MODE_MON = 22, ARM_MODE_ABT = 23, ARM_MODE_UND = 27, + ARM_MODE_1176_MON = 28, ARM_MODE_SYS = 31, ARM_MODE_THREAD = 0, ARM_MODE_USER_THREAD = 1, ARM_MODE_HANDLER = 2, + /* shift left 4 bits for armv8 64 */ + ARMV8_64_EL0T = 0x0F, + ARMV8_64_EL1T = 0x4F, + ARMV8_64_EL1H = 0x5F, + ARMV8_64_EL2T = 0x8F, + ARMV8_64_EL2H = 0x9F, + ARMV8_64_EL3T = 0xCF, + ARMV8_64_EL3H = 0xDF, + ARM_MODE_ANY = -1 }; @@ -79,6 +87,7 @@ enum arm_state { ARM_STATE_THUMB, ARM_STATE_JAZELLE, ARM_STATE_THUMB_EE, + ARM_STATE_AARCH64, }; #define ARM_COMMON_MAGIC 0x0A450A45 @@ -131,6 +140,18 @@ struct arm { /** Flag reporting whether semihosting is active. */ bool is_semihosting; + /** Flag reporting whether semihosting fileio is active. */ + bool is_semihosting_fileio; + + /** Flag reporting whether semihosting fileio operation is active. */ + bool semihosting_hit_fileio; + + /** Current semihosting operation. */ + int semihosting_op; + + /** Current semihosting result. */ + int semihosting_result; + /** Value to be returned by semihosting SYS_ERRNO request. */ int semihosting_errno; @@ -202,10 +223,11 @@ struct arm_reg { enum arm_mode mode; struct target *target; struct arm *arm; - uint8_t value[4]; + uint8_t value[8]; }; struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm); +struct reg_cache *armv8_build_reg_cache(struct target *target); extern const struct command_registration arm_command_handlers[]; @@ -213,6 +235,9 @@ int arm_arch_state(struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); +int armv8_get_gdb_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); int arm_init_arch_info(struct target *target, struct arm *arm); @@ -220,7 +245,7 @@ int arm_init_arch_info(struct target *target, struct arm *arm); int armv4_5_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info); int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, @@ -231,14 +256,15 @@ int armv4_5_run_algorithm_inner(struct target *target, int timeout_ms, void *arch_info)); int arm_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum); + target_addr_t address, uint32_t count, uint32_t *checksum); int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); struct reg *arm_reg_current(struct arm *arm, unsigned regnum); +struct reg *armv8_reg_current(struct arm *arm, unsigned regnum); extern struct reg arm_gdb_dummy_fp_reg; extern struct reg arm_gdb_dummy_fps_reg; -#endif /* ARM_H */ +#endif /* OPENOCD_TARGET_ARM_H */ diff --git a/src/target/arm11.c b/src/target/arm11.c index 0cb1d8c83..13fbd207a 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -44,7 +42,7 @@ static int arm11_step(struct target *target, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); /** Check and if necessary take control of the system @@ -392,7 +390,7 @@ static int arm11_halt(struct target *target) break; - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { @@ -420,16 +418,38 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a { void *value = arm11->arm.pc->value; - if (!current) - buf_set_u32(value, 0, 32, address); - else + /* use the current program counter */ + if (current) address = buf_get_u32(value, 0, 32); + /* Make sure that the gdb thumb fixup does not + * kill the return address + */ + switch (arm11->arm.core_state) { + case ARM_STATE_ARM: + address &= 0xFFFFFFFC; + break; + case ARM_STATE_THUMB: + /* When the return address is loaded into PC + * bit 0 must be 1 to stay in Thumb state + */ + address |= 0x1; + break; + + /* catch-all for JAZELLE and THUMB_EE */ + default: + break; + } + + buf_set_u32(value, 0, 32, address); + arm11->arm.pc->dirty = 1; + arm11->arm.pc->valid = 1; + return address; } static int arm11_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */ /* current, address, handle_breakpoints, debug_execution); */ @@ -447,7 +467,7 @@ static int arm11_resume(struct target *target, int current, address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /* clear breakpoints/watchpoints and VCR*/ CHECK_RETVAL(arm11_sc7_clear_vbw(arm11)); @@ -461,7 +481,7 @@ static int arm11_resume(struct target *target, int current, for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { - LOG_DEBUG("must step over %08" PRIx32 "", bp->address); + LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address); arm11_step(target, 1, 0, 0); break; } @@ -487,7 +507,7 @@ static int arm11_resume(struct target *target, int current, CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp))); - LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num, + LOG_DEBUG("Add BP %d at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num++; @@ -514,7 +534,7 @@ static int arm11_resume(struct target *target, int current, break; - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); if (i >= 1000) { @@ -537,7 +557,7 @@ static int arm11_resume(struct target *target, int current, } static int arm11_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -551,7 +571,7 @@ static int arm11_step(struct target *target, int current, address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /** \todo TODO: Thumb not supported here */ @@ -563,13 +583,13 @@ static int arm11_step(struct target *target, int current, /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { address = arm11_nextpc(arm11, 0, address + 4); - LOG_DEBUG("Skipping BKPT %08" PRIx32, address); + LOG_DEBUG("Skipping BKPT %08" TARGET_PRIxADDR, address); } /* skip over Wait for interrupt / Standby * mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { address = arm11_nextpc(arm11, 0, address + 4); - LOG_DEBUG("Skipping WFI %08" PRIx32, address); + LOG_DEBUG("Skipping WFI %08" TARGET_PRIxADDR, address); } /* ignore B to self */ else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe) @@ -694,21 +714,32 @@ static int arm11_assert_reset(struct target *target) { struct arm11_common *arm11 = target_to_arm11(target); - /* optionally catch reset vector */ - if (target->reset_halt && !(arm11->vcr & 1)) - CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); - - /* Issue some kind of warm reset. */ - if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) - target_handle_event(target, TARGET_EVENT_RESET_ASSERT); - else if (jtag_get_reset_config() & RESET_HAS_SRST) { - /* REVISIT handle "pulls" cases, if there's - * hardware that needs them to work. - */ - jtag_add_reset(0, 1); + if (!(target_was_examined(target))) { + if (jtag_get_reset_config() & RESET_HAS_SRST) + jtag_add_reset(0, 1); + else { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } } else { - LOG_ERROR("%s: how to reset?", target_name(target)); - return ERROR_FAIL; + + /* optionally catch reset vector */ + if (target->reset_halt && !(arm11->vcr & 1)) + CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1)); + + /* Issue some kind of warm reset. */ + if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); + else if (jtag_get_reset_config() & RESET_HAS_SRST) { + /* REVISIT handle "pulls" cases, if there's + * hardware that needs them to work. + */ + jtag_add_reset(0, 1); + } else { + LOG_ERROR("%s: how to reset?", target_name(target)); + return ERROR_FAIL; + } } /* registers are now invalid */ @@ -856,7 +887,7 @@ static int arm11_read_memory_inner(struct target *target, } static int arm11_read_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1012,7 +1043,7 @@ static int arm11_write_memory_inner(struct target *target, } static int arm11_write_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { /* pointer increment matters only for multi-unit writes ... diff --git a/src/target/arm11.h b/src/target/arm11.h index d9e45357e..77cc2236d 100644 --- a/src/target/arm11.h +++ b/src/target/arm11.h @@ -15,13 +15,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM11_H -#define ARM11_H +#ifndef OPENOCD_TARGET_ARM11_H +#define OPENOCD_TARGET_ARM11_H #include "arm.h" #include "arm_dpm.h" @@ -113,4 +111,4 @@ enum arm11_sc7 { ARM11_SC7_WCR0 = 112, }; -#endif /* ARM11_H */ +#endif /* OPENOCD_TARGET_ARM11_H */ diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c index 9271a2b96..2232b3ef6 100644 --- a/src/target/arm11_dbgtap.c +++ b/src/target/arm11_dbgtap.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -410,7 +408,7 @@ int arm11_run_instr_no_data(struct arm11_common *arm11, if (flag) break; - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); @@ -493,7 +491,7 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, JTAG_DEBUG("DTR Ready %d nRetry %d", Ready, nRetry); - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); @@ -525,7 +523,7 @@ int arm11_run_instr_data_to_core(struct arm11_common *arm11, JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", (unsigned) Data, Ready, nRetry); - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); @@ -789,7 +787,7 @@ int arm11_run_instr_data_from_core(struct arm11_common *arm11, JTAG_DEBUG("DTR Data %08x Ready %d nRetry %d", (unsigned) Data, Ready, nRetry); - long long then = 0; + int64_t then = 0; if (i == 1000) then = timeval_ms(); @@ -924,7 +922,7 @@ int arm11_sc7_run(struct arm11_common *arm11, struct arm11_sc7_action *actions, if (Ready) break; - long long then = 0; + int64_t then = 0; if (i_n == 1000) then = timeval_ms(); diff --git a/src/target/arm11_dbgtap.h b/src/target/arm11_dbgtap.h index 7f48ec4fe..541434edc 100644 --- a/src/target/arm11_dbgtap.h +++ b/src/target/arm11_dbgtap.h @@ -15,13 +15,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM11_DBGTAP_H -#define ARM11_DBGTAP_H +#ifndef OPENOCD_TARGET_ARM11_DBGTAP_H +#define OPENOCD_TARGET_ARM11_DBGTAP_H #include "arm11.h" @@ -82,4 +80,4 @@ int arm11_read_memory_word(struct arm11_common *arm11, int arm11_dpm_init(struct arm11_common *arm11, uint32_t didr); int arm11_bpwp_flush(struct arm11_common *arm11); -#endif /* ARM11_DBGTAP_H */ +#endif /* OPENOCD_TARGET_ARM11_DBGTAP_H */ diff --git a/src/target/arm720t.c b/src/target/arm720t.c index a97ad118e..bcbfa9dff 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -273,7 +271,7 @@ static int arm720_mmu(struct target *target, int *enabled) } static int arm720_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { uint32_t cb; struct arm720t_common *arm720t = target_to_arm720(target); @@ -288,7 +286,7 @@ static int arm720_virt2phys(struct target *target, } static int arm720t_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; struct arm720t_common *arm720t = target_to_arm720(target); @@ -311,7 +309,7 @@ static int arm720t_read_memory(struct target *target, } static int arm720t_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); @@ -319,7 +317,7 @@ static int arm720t_read_phys_memory(struct target *target, } static int arm720t_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); @@ -338,7 +336,7 @@ static int arm720t_soft_reset_halt(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { diff --git a/src/target/arm720t.h b/src/target/arm720t.h index 35d45ffd4..31dad9c76 100644 --- a/src/target/arm720t.h +++ b/src/target/arm720t.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM720T_H -#define ARM720T_H +#ifndef OPENOCD_TARGET_ARM720T_H +#define OPENOCD_TARGET_ARM720T_H #include "arm7tdmi.h" #include "armv4_5_mmu.h" @@ -40,4 +38,4 @@ static inline struct arm720t_common *target_to_arm720(struct target *target) return container_of(target->arch_info, struct arm720t_common, arm7_9_common.arm); } -#endif /* ARM720T_H */ +#endif /* OPENOCD_TARGET_ARM720T_H */ diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 7b40f5057..7fd1ed9f8 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -24,9 +24,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -103,7 +101,8 @@ static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *br arm7_9->wp_available--; } else LOG_ERROR("BUG: no hardware comparator available"); - LOG_DEBUG("BPID: %" PRId32 " (0x%08" PRIx32 ") using hw wp: %d", + + LOG_DEBUG("BPID: %" PRId32 " (0x%08" TARGET_PRIxADDR ") using hw wp: %d", breakpoint->unique_id, breakpoint->address, breakpoint->set); @@ -189,7 +188,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval = ERROR_OK; - LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32 ", Type: %d", + LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" TARGET_PRIxADDR ", Type: %d", breakpoint->unique_id, breakpoint->address, breakpoint->type); @@ -246,7 +245,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break if (retval != ERROR_OK) return retval; if (verify != arm7_9->arm_bkpt) { - LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -266,7 +265,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break if (retval != ERROR_OK) return retval; if (verify != arm7_9->thumb_bkpt) { - LOG_ERROR("Unable to set thumb software breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set thumb software breakpoint at address %08" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -301,7 +300,7 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32, + LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" TARGET_PRIxADDR, breakpoint->unique_id, breakpoint->address); @@ -350,12 +349,12 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); - if (current_instr == arm7_9->thumb_bkpt) + if (current_instr == arm7_9->thumb_bkpt) { retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - + } } if (--arm7_9->sw_breakpoint_count == 0) { @@ -636,8 +635,8 @@ int arm7_9_execute_sys_speed(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); - int timeout; + int64_t then = timeval_ms(); + bool timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { /* read debug status register */ embeddedice_read_reg(dbg_stat); @@ -875,6 +874,13 @@ int arm7_9_assert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); bool use_event = false; + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } + LOG_DEBUG("target->state: %s", target_state_name(target)); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) @@ -1687,7 +1693,7 @@ static void arm7_9_enable_breakpoints(struct target *target) int arm7_9_resume(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints, int debug_execution) { @@ -1719,7 +1725,7 @@ int arm7_9_resume(struct target *target, breakpoint = breakpoint_find(target, buf_get_u32(arm->pc->value, 0, 32)); if (breakpoint != NULL) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %" PRId32, + LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR " (id: %" PRId32, breakpoint->address, breakpoint->unique_id); retval = arm7_9_unset_breakpoint(target, breakpoint); @@ -1778,7 +1784,7 @@ int arm7_9_resume(struct target *target, LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); - LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("set breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address); retval = arm7_9_set_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; @@ -1889,7 +1895,7 @@ void arm7_9_disable_eice_step(struct target *target) embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]); } -int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints) +int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -2089,7 +2095,7 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, } int arm7_9_read_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -2104,7 +2110,7 @@ int arm7_9_read_memory(struct target *target, int retval; int last_reg = 0; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -2242,7 +2248,8 @@ int arm7_9_read_memory(struct target *target, if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( - "memory read caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", + "memory read caused data abort " + "(address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2258,7 +2265,7 @@ int arm7_9_read_memory(struct target *target, } int arm7_9_write_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -2455,7 +2462,8 @@ int arm7_9_write_memory(struct target *target, if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( - "memory write caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", + "memory write caused data abort " + "(address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2471,7 +2479,7 @@ int arm7_9_write_memory(struct target *target, } int arm7_9_write_memory_opt(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -2571,7 +2579,7 @@ static const uint32_t dcc_code[] = { }; int arm7_9_bulk_write_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t count, const uint8_t *buffer) { @@ -2627,7 +2635,7 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t endaddress = buf_get_u32(reg_params[0].value, 0, 32); if (endaddress != (address + count*4)) { LOG_ERROR( - "DCC write failed, expected end address 0x%08" PRIx32 " got 0x%0" PRIx32 "", + "DCC write failed, expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32 "", (address + count*4), endaddress); retval = ERROR_FAIL; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 5821e132b..811f9c593 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -22,13 +22,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM7_9_COMMON_H -#define ARM7_9_COMMON_H +#ifndef OPENOCD_TARGET_ARM7_9_COMMON_H +#define OPENOCD_TARGET_ARM7_9_COMMON_H #include "arm.h" #include "arm_jtag.h" @@ -124,13 +122,13 @@ struct arm7_9_common { * Used as a fallback when bulk writes are unavailable, or for writing data needed to * do the bulk writes. */ - int (*write_memory)(struct target *target, uint32_t address, + int (*write_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /** * Write target memory in multiples of 4 bytes, optimized for * writing large quantities of data. */ - int (*bulk_write_memory)(struct target *target, uint32_t address, + int (*bulk_write_memory)(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); }; @@ -157,19 +155,19 @@ int arm7_9_early_halt(struct target *target); int arm7_9_soft_reset_halt(struct target *target); int arm7_9_halt(struct target *target); -int arm7_9_resume(struct target *target, int current, uint32_t address, +int arm7_9_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); -int arm7_9_step(struct target *target, int current, uint32_t address, +int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); -int arm7_9_read_memory(struct target *target, uint32_t address, +int arm7_9_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int arm7_9_write_memory(struct target *target, uint32_t address, +int arm7_9_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm7_9_write_memory_opt(struct target *target, uint32_t address, +int arm7_9_write_memory_opt(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_write_memory_no_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm7_9_bulk_write_memory(struct target *target, uint32_t address, +int arm7_9_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); int arm7_9_run_algorithm(struct target *target, int num_mem_params, @@ -194,4 +192,4 @@ int arm7_9_endianness_callback(jtag_callback_data_t pu8_in, jtag_callback_data_t i_size, jtag_callback_data_t i_be, jtag_callback_data_t i_flip); -#endif /* ARM7_9_COMMON_H */ +#endif /* OPENOCD_TARGET_ARM7_9_COMMON_H */ diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 490ecfc0b..9dcb302d9 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -32,6 +30,7 @@ #include "target_type.h" #include "register.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" /* * For information about ARM7TDMI, see ARM DDI 0210C (r4p1) @@ -617,7 +616,7 @@ static void arm7tdmi_build_reg_cache(struct target *target) int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm7tdmi_build_reg_cache(target); - + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/arm7tdmi.h b/src/target/arm7tdmi.h index a44ceee53..053f64df8 100644 --- a/src/target/arm7tdmi.h +++ b/src/target/arm7tdmi.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM7TDMI_H -#define ARM7TDMI_H +#ifndef OPENOCD_TARGET_ARM7TDMI_H +#define OPENOCD_TARGET_ARM7TDMI_H #include "embeddedice.h" @@ -31,4 +29,4 @@ int arm7tdmi_init_arch_info(struct target *target, int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target); -#endif /* ARM7TDMI_H */ +#endif /* OPENOCD_TARGET_ARM7TDMI_H */ diff --git a/src/target/arm920t.c b/src/target/arm920t.c index b1579bca5..7927a2bea 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -555,7 +553,7 @@ static int arm920_mmu(struct target *target, int *enabled) } static int arm920_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys) + target_addr_t virt, target_addr_t *phys) { uint32_t cb; struct arm920t_common *arm920t = target_to_arm920(target); @@ -570,7 +568,7 @@ static int arm920_virt2phys(struct target *target, } /** Reads a buffer, in the specified word size, with current MMU settings. */ -int arm920t_read_memory(struct target *target, uint32_t address, +int arm920t_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; @@ -582,7 +580,7 @@ int arm920t_read_memory(struct target *target, uint32_t address, static int arm920t_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); @@ -592,7 +590,7 @@ static int arm920t_read_phys_memory(struct target *target, } static int arm920t_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); @@ -602,7 +600,7 @@ static int arm920t_write_phys_memory(struct target *target, } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm920t_write_memory(struct target *target, uint32_t address, +int arm920t_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; @@ -753,8 +751,8 @@ int arm920t_soft_reset_halt(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); - int timeout; + int64_t then = timeval_ms(); + bool timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { embeddedice_read_reg(dbg_stat); diff --git a/src/target/arm920t.h b/src/target/arm920t.h index 71876a69b..2e3b08ca3 100644 --- a/src/target/arm920t.h +++ b/src/target/arm920t.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM920T_H -#define ARM920T_H +#ifndef OPENOCD_TARGET_ARM920T_H +#define OPENOCD_TARGET_ARM920T_H #include "arm9tdmi.h" #include "armv4_5_mmu.h" @@ -57,9 +55,9 @@ struct arm920t_tlb_entry { int arm920t_arch_state(struct target *target); int arm920t_soft_reset_halt(struct target *target); int arm920t_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm920t_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm920t_post_debug_entry(struct target *target); void arm920t_pre_restore_context(struct target *target); int arm920t_get_ttb(struct target *target, uint32_t *result); @@ -70,4 +68,4 @@ int arm920t_enable_mmu_caches(struct target *target, extern const struct command_registration arm920t_command_handlers[]; -#endif /* ARM920T_H */ +#endif /* OPENOCD_TARGET_ARM920T_H */ diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index d8bf2d046..58de77850 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -89,7 +87,7 @@ static int arm926ejs_cp15_read(struct target *target, uint32_t op1, uint32_t op2 jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;;) { /* rescan with NOP, to wait for the access to complete */ @@ -175,7 +173,7 @@ static int arm926ejs_cp15_write(struct target *target, uint32_t op1, uint32_t op jtag_add_dr_scan(jtag_info->tap, 4, fields, TAP_IDLE); - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;;) { /* rescan with NOP, to wait for the access to complete */ @@ -548,7 +546,7 @@ int arm926ejs_soft_reset_halt(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); int timeout; while (!(timeout = ((timeval_ms()-then) > 1000))) { if (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0) { @@ -596,7 +594,7 @@ int arm926ejs_soft_reset_halt(struct target *target) } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm926ejs_write_memory(struct target *target, uint32_t address, +int arm926ejs_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; @@ -625,7 +623,7 @@ int arm926ejs_write_memory(struct target *target, uint32_t address, return retval; } - uint32_t pa; + target_addr_t pa; retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) return retval; @@ -657,7 +655,7 @@ int arm926ejs_write_memory(struct target *target, uint32_t address, } static int arm926ejs_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); @@ -667,7 +665,7 @@ static int arm926ejs_write_phys_memory(struct target *target, } static int arm926ejs_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); @@ -738,7 +736,7 @@ COMMAND_HANDLER(arm926ejs_handle_cache_info_command) return armv4_5_handle_cache_info_command(CMD_CTX, &arm926ejs->armv4_5_mmu.armv4_5_cache); } -static int arm926ejs_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) +static int arm926ejs_virt2phys(struct target *target, target_addr_t virtual, target_addr_t *physical) { uint32_t cb; struct arm926ejs_common *arm926ejs = target_to_arm926(target); diff --git a/src/target/arm926ejs.h b/src/target/arm926ejs.h index cc19c9fc5..d4fd0cb6e 100644 --- a/src/target/arm926ejs.h +++ b/src/target/arm926ejs.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM926EJS_H -#define ARM926EJS_H +#ifndef OPENOCD_TARGET_ARM926EJS_H +#define OPENOCD_TARGET_ARM926EJS_H #include "arm9tdmi.h" #include "armv4_5_mmu.h" @@ -49,9 +47,9 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs, struct jtag_tap *tap); int arm926ejs_arch_state(struct target *target); int arm926ejs_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm926ejs_soft_reset_halt(struct target *target); extern const struct command_registration arm926ejs_command_handlers[]; -#endif /* ARM926EJS_H */ +#endif /* OPENOCD_TARGET_ARM926EJS_H */ diff --git a/src/target/arm946e.c b/src/target/arm946e.c index c21ff95f7..06c9fc30d 100644 --- a/src/target/arm946e.c +++ b/src/target/arm946e.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -489,7 +487,7 @@ uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address, } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm946e_write_memory(struct target *target, uint32_t address, +int arm946e_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; @@ -537,7 +535,7 @@ int arm946e_write_memory(struct target *target, uint32_t address, } -int arm946e_read_memory(struct target *target, uint32_t address, +int arm946e_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; diff --git a/src/target/arm946e.h b/src/target/arm946e.h index fd45f05af..ee1ef3235 100644 --- a/src/target/arm946e.h +++ b/src/target/arm946e.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM946E_H -#define ARM946E_H +#ifndef OPENOCD_TARGET_ARM946E_H +#define OPENOCD_TARGET_ARM946E_H #include "arm9tdmi.h" @@ -50,4 +48,4 @@ int arm946e_write_cp15(struct target *target, int reg_addr, uint32_t value); extern const struct command_registration arm946e_command_handlers[]; -#endif /* ARM946E_H */ +#endif /* OPENOCD_TARGET_ARM946E_H */ diff --git a/src/target/arm966e.c b/src/target/arm966e.c index a174eab40..0429c54b5 100644 --- a/src/target/arm966e.c +++ b/src/target/arm966e.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/arm966e.h b/src/target/arm966e.h index e7ace9299..aa2e9bb27 100644 --- a/src/target/arm966e.h +++ b/src/target/arm966e.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM966E_H -#define ARM966E_H +#ifndef OPENOCD_TARGET_ARM966E_H +#define OPENOCD_TARGET_ARM966E_H #include "arm9tdmi.h" @@ -47,4 +45,4 @@ int arm966e_write_cp15(struct target *target, int reg_addr, uint32_t value); extern const struct command_registration arm966e_command_handlers[]; -#endif /* ARM966E_H */ +#endif /* OPENOCD_TARGET_ARM966E_H */ diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index ca000a7fe..82b430f88 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -32,6 +30,7 @@ #include "target_type.h" #include "register.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" /* * NOTE: this holds code that's used with multiple ARM9 processors: @@ -716,6 +715,7 @@ int arm9tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm9tdmi_build_reg_cache(target); + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/arm9tdmi.h b/src/target/arm9tdmi.h index 366cd1294..c6f0ccf0f 100644 --- a/src/target/arm9tdmi.h +++ b/src/target/arm9tdmi.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM9TDMI_H -#define ARM9TDMI_H +#ifndef OPENOCD_TARGET_ARM9TDMI_H +#define OPENOCD_TARGET_ARM9TDMI_H #include "embeddedice.h" @@ -55,4 +53,4 @@ void arm9tdmi_branch_resume(struct target *target); void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc); void arm9tdmi_disable_single_step(struct target *target); -#endif /* ARM9TDMI_H */ +#endif /* OPENOCD_TARGET_ARM9TDMI_H */ diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 6efc0af13..eafc2ddc0 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -24,9 +24,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** @@ -75,7 +73,9 @@ #include "jtag/interface.h" #include "arm.h" #include "arm_adi_v5.h" +#include #include +#include /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ @@ -586,6 +586,7 @@ struct adiv5_dap *dap_init(void) /* Number of bits for tar autoincrement, impl. dep. at least 10 */ dap->ap[i].tar_autoincr_block = (1<<10); } + INIT_LIST_HEAD(&dap->cmd_journal); return dap; } @@ -611,60 +612,58 @@ int dap_dp_init(struct adiv5_dap *dap) dap->select = DP_SELECT_INVALID; dap->last_read = NULL; - for (size_t i = 0; i < 10; i++) { + for (size_t i = 0; i < 30; i++) { /* DP initialization */ - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; - - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); - if (retval != ERROR_OK) - continue; + retval = dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL); + if (retval == ERROR_OK) + break; + } - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); + if (retval != ERROR_OK) + return retval; - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - /* Check that we have debug power domains activated */ - LOG_DEBUG("DAP: wait CDBGPWRUPACK"); - retval = dap_dp_poll_register(dap, DP_CTRL_STAT, - CDBGPWRUPACK, CDBGPWRUPACK, - DAP_POWER_DOMAIN_TIMEOUT); - if (retval != ERROR_OK) - continue; + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; - LOG_DEBUG("DAP: wait CSYSPWRUPACK"); - retval = dap_dp_poll_register(dap, DP_CTRL_STAT, - CSYSPWRUPACK, CSYSPWRUPACK, - DAP_POWER_DOMAIN_TIMEOUT); - if (retval != ERROR_OK) - continue; + /* Check that we have debug power domains activated */ + LOG_DEBUG("DAP: wait CDBGPWRUPACK"); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CDBGPWRUPACK, CDBGPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); + if (retval != ERROR_OK) + return retval; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + LOG_DEBUG("DAP: wait CSYSPWRUPACK"); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CSYSPWRUPACK, CSYSPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); + if (retval != ERROR_OK) + return retval; - /* With debug power on we can activate OVERRUN checking */ - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); - if (retval != ERROR_OK) - continue; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - continue; + /* With debug power on we can activate OVERRUN checking */ + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - break; - } + retval = dap_run(dap); + if (retval != ERROR_OK) + return retval; return retval; } @@ -737,10 +736,9 @@ static const char *class_description[16] = { "Generic IP component", "PrimeCell or System component" }; -static bool is_dap_cid_ok(uint32_t cid3, uint32_t cid2, uint32_t cid1, uint32_t cid0) +static bool is_dap_cid_ok(uint32_t cid) { - return cid3 == 0xb1 && cid2 == 0x05 - && ((cid1 & 0x0f) == 0) && cid0 == 0x0d; + return (cid & 0xffff0fff) == 0xb105000d; } /* @@ -874,6 +872,61 @@ int dap_lookup_cs_component(struct adiv5_ap *ap, return ERROR_OK; } +static int dap_read_part_id(struct adiv5_ap *ap, uint32_t component_base, uint32_t *cid, uint64_t *pid) +{ + assert((component_base & 0xFFF) == 0); + assert(ap != NULL && cid != NULL && pid != NULL); + + uint32_t cid0, cid1, cid2, cid3; + uint32_t pid0, pid1, pid2, pid3, pid4; + int retval; + + /* IDs are in last 4K section */ + retval = mem_ap_read_u32(ap, component_base + 0xFE0, &pid0); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFE4, &pid1); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFE8, &pid2); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFEC, &pid3); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFD0, &pid4); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF0, &cid0); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF4, &cid1); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFF8, &cid2); + if (retval != ERROR_OK) + return retval; + retval = mem_ap_read_u32(ap, component_base + 0xFFC, &cid3); + if (retval != ERROR_OK) + return retval; + + retval = dap_run(ap->dap); + if (retval != ERROR_OK) + return retval; + + *cid = (cid3 & 0xff) << 24 + | (cid2 & 0xff) << 16 + | (cid1 & 0xff) << 8 + | (cid0 & 0xff); + *pid = (uint64_t)(pid4 & 0xff) << 32 + | (pid3 & 0xff) << 24 + | (pid2 & 0xff) << 16 + | (pid1 & 0xff) << 8 + | (pid0 & 0xff); + + return ERROR_OK; +} + /* The designer identity code is encoded as: * bits 11:8 : JEP106 Bank (number of continuation codes), only valid when bit 7 is 1. * bit 7 : Set when bits 6:0 represent a JEP106 ID and cleared when bits 6:0 represent @@ -905,62 +958,101 @@ static const struct { const char *type; const char *full; } dap_partnums[] = { - { ARM_ID, 0x000, "Cortex-M3 SCS", "(System Control Space)", }, - { ARM_ID, 0x001, "Cortex-M3 ITM", "(Instrumentation Trace Module)", }, - { ARM_ID, 0x002, "Cortex-M3 DWT", "(Data Watchpoint and Trace)", }, - { ARM_ID, 0x003, "Cortex-M3 FBP", "(Flash Patch and Breakpoint)", }, - { ARM_ID, 0x008, "Cortex-M0 SCS", "(System Control Space)", }, - { ARM_ID, 0x00a, "Cortex-M0 DWT", "(Data Watchpoint and Trace)", }, - { ARM_ID, 0x00b, "Cortex-M0 BPU", "(Breakpoint Unit)", }, - { ARM_ID, 0x00c, "Cortex-M4 SCS", "(System Control Space)", }, - { ARM_ID, 0x00d, "CoreSight ETM11", "(Embedded Trace)", }, - { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", }, - { ARM_ID, 0x4c7, "Cortex-M7 PPB", "(Private Peripheral Bus ROM Table)", }, - { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", }, - { ARM_ID, 0x907, "CoreSight ETB", "(Trace Buffer)", }, - { ARM_ID, 0x908, "CoreSight CSTF", "(Trace Funnel)", }, - { ARM_ID, 0x910, "CoreSight ETM9", "(Embedded Trace)", }, - { ARM_ID, 0x912, "CoreSight TPIU", "(Trace Port Interface Unit)", }, - { ARM_ID, 0x913, "CoreSight ITM", "(Instrumentation Trace Macrocell)", }, - { ARM_ID, 0x914, "CoreSight SWO", "(Single Wire Output)", }, - { ARM_ID, 0x917, "CoreSight HTM", "(AHB Trace Macrocell)", }, - { ARM_ID, 0x920, "CoreSight ETM11", "(Embedded Trace)", }, - { ARM_ID, 0x921, "Cortex-A8 ETM", "(Embedded Trace)", }, - { ARM_ID, 0x922, "Cortex-A8 CTI", "(Cross Trigger)", }, - { ARM_ID, 0x923, "Cortex-M3 TPIU", "(Trace Port Interface Unit)", }, - { ARM_ID, 0x924, "Cortex-M3 ETM", "(Embedded Trace)", }, - { ARM_ID, 0x925, "Cortex-M4 ETM", "(Embedded Trace)", }, - { ARM_ID, 0x930, "Cortex-R4 ETM", "(Embedded Trace)", }, - { ARM_ID, 0x941, "CoreSight TPIU-Lite", "(Trace Port Interface Unit)", }, - { ARM_ID, 0x950, "CoreSight Component", "(unidentified Cortex-A9 component)", }, - { ARM_ID, 0x955, "CoreSight Component", "(unidentified Cortex-A5 component)", }, - { ARM_ID, 0x95f, "Cortex-A15 PTM", "(Program Trace Macrocell)", }, - { ARM_ID, 0x961, "CoreSight TMC", "(Trace Memory Controller)", }, - { ARM_ID, 0x962, "CoreSight STM", "(System Trace Macrocell)", }, - { ARM_ID, 0x9a0, "CoreSight PMU", "(Performance Monitoring Unit)", }, - { ARM_ID, 0x9a1, "Cortex-M4 TPIU", "(Trace Port Interface Unit)", }, - { ARM_ID, 0x9a5, "Cortex-A5 ETM", "(Embedded Trace)", }, - { ARM_ID, 0x9a7, "Cortex-A7 PMU", "(Performance Monitor Unit)", }, - { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, - { ARM_ID, 0xc05, "Cortex-A5 Debug", "(Debug Unit)", }, - { ARM_ID, 0xc07, "Cortex-A7 Debug", "(Debug Unit)", }, - { ARM_ID, 0xc08, "Cortex-A8 Debug", "(Debug Unit)", }, - { ARM_ID, 0xc09, "Cortex-A9 Debug", "(Debug Unit)", }, - { ARM_ID, 0xc0f, "Cortex-A15 Debug", "(Debug Unit)", }, - { ARM_ID, 0xc14, "Cortex-R4 Debug", "(Debug Unit)", }, - { 0x0E5, 0x000, "SHARC+/Blackfin+", "", }, + { ARM_ID, 0x000, "Cortex-M3 SCS", "(System Control Space)", }, + { ARM_ID, 0x001, "Cortex-M3 ITM", "(Instrumentation Trace Module)", }, + { ARM_ID, 0x002, "Cortex-M3 DWT", "(Data Watchpoint and Trace)", }, + { ARM_ID, 0x003, "Cortex-M3 FPB", "(Flash Patch and Breakpoint)", }, + { ARM_ID, 0x008, "Cortex-M0 SCS", "(System Control Space)", }, + { ARM_ID, 0x00a, "Cortex-M0 DWT", "(Data Watchpoint and Trace)", }, + { ARM_ID, 0x00b, "Cortex-M0 BPU", "(Breakpoint Unit)", }, + { ARM_ID, 0x00c, "Cortex-M4 SCS", "(System Control Space)", }, + { ARM_ID, 0x00d, "CoreSight ETM11", "(Embedded Trace)", }, + { ARM_ID, 0x00e, "Cortex-M7 FPB", "(Flash Patch and Breakpoint)", }, + { ARM_ID, 0x490, "Cortex-A15 GIC", "(Generic Interrupt Controller)", }, + { ARM_ID, 0x4a1, "Cortex-A53 ROM", "(v8 Memory Map ROM Table)", }, + { ARM_ID, 0x4a2, "Cortex-A57 ROM", "(ROM Table)", }, + { ARM_ID, 0x4a3, "Cortex-A53 ROM", "(v7 Memory Map ROM Table)", }, + { ARM_ID, 0x4a4, "Cortex-A72 ROM", "(ROM Table)", }, + { ARM_ID, 0x4af, "Cortex-A15 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c0, "Cortex-M0+ ROM", "(ROM Table)", }, + { ARM_ID, 0x4c3, "Cortex-M3 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c4, "Cortex-M4 ROM", "(ROM Table)", }, + { ARM_ID, 0x4c7, "Cortex-M7 PPB ROM", "(Private Peripheral Bus ROM Table)", }, + { ARM_ID, 0x4c8, "Cortex-M7 ROM", "(ROM Table)", }, + { ARM_ID, 0x470, "Cortex-M1 ROM", "(ROM Table)", }, + { ARM_ID, 0x471, "Cortex-M0 ROM", "(ROM Table)", }, + { ARM_ID, 0x906, "CoreSight CTI", "(Cross Trigger)", }, + { ARM_ID, 0x907, "CoreSight ETB", "(Trace Buffer)", }, + { ARM_ID, 0x908, "CoreSight CSTF", "(Trace Funnel)", }, + { ARM_ID, 0x909, "CoreSight ATBR", "(Advanced Trace Bus Replicator)", }, + { ARM_ID, 0x910, "CoreSight ETM9", "(Embedded Trace)", }, + { ARM_ID, 0x912, "CoreSight TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x913, "CoreSight ITM", "(Instrumentation Trace Macrocell)", }, + { ARM_ID, 0x914, "CoreSight SWO", "(Single Wire Output)", }, + { ARM_ID, 0x917, "CoreSight HTM", "(AHB Trace Macrocell)", }, + { ARM_ID, 0x920, "CoreSight ETM11", "(Embedded Trace)", }, + { ARM_ID, 0x921, "Cortex-A8 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x922, "Cortex-A8 CTI", "(Cross Trigger)", }, + { ARM_ID, 0x923, "Cortex-M3 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x924, "Cortex-M3 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x925, "Cortex-M4 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x930, "Cortex-R4 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x931, "Cortex-R5 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x932, "CoreSight MTB-M0+", "(Micro Trace Buffer)", }, + { ARM_ID, 0x941, "CoreSight TPIU-Lite", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x950, "Cortex-A9 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x955, "Cortex-A5 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95a, "Cortex-A72 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95b, "Cortex-A17 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x95d, "Cortex-A53 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95e, "Cortex-A57 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x95f, "Cortex-A15 PTM", "(Program Trace Macrocell)", }, + { ARM_ID, 0x961, "CoreSight TMC", "(Trace Memory Controller)", }, + { ARM_ID, 0x962, "CoreSight STM", "(System Trace Macrocell)", }, + { ARM_ID, 0x975, "Cortex-M7 ETM", "(Embedded Trace)", }, + { ARM_ID, 0x9a0, "CoreSight PMU", "(Performance Monitoring Unit)", }, + { ARM_ID, 0x9a1, "Cortex-M4 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x9a4, "CoreSight GPR", "(Granular Power Requester)", }, + { ARM_ID, 0x9a5, "Cortex-A5 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9a7, "Cortex-A7 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9a8, "Cortex-A53 CTI", "(Cross Trigger)", }, + { ARM_ID, 0x9a9, "Cortex-M7 TPIU", "(Trace Port Interface Unit)", }, + { ARM_ID, 0x9ae, "Cortex-A17 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9af, "Cortex-A15 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9b7, "Cortex-R7 PMU", "(Performance Monitoring Unit)", }, + { ARM_ID, 0x9d3, "Cortex-A53 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9d7, "Cortex-A57 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0x9d8, "Cortex-A72 PMU", "(Performance Monitor Unit)", }, + { ARM_ID, 0xc05, "Cortex-A5 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc07, "Cortex-A7 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc08, "Cortex-A8 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc09, "Cortex-A9 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc0e, "Cortex-A17 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc0f, "Cortex-A15 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc14, "Cortex-R4 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc15, "Cortex-R5 Debug", "(Debug Unit)", }, + { ARM_ID, 0xc17, "Cortex-R7 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd03, "Cortex-A53 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd07, "Cortex-A57 Debug", "(Debug Unit)", }, + { ARM_ID, 0xd08, "Cortex-A72 Debug", "(Debug Unit)", }, + { 0x097, 0x9af, "MSP432 ROM", "(ROM Table)" }, + { 0x09f, 0xcd0, "Atmel CPU with DSU", "(CPU)" }, + { 0x0c1, 0x1db, "XMC4500 ROM", "(ROM Table)" }, + { 0x0c1, 0x1df, "XMC4700/4800 ROM", "(ROM Table)" }, + { 0x0c1, 0x1ed, "XMC1000 ROM", "(ROM Table)" }, + { 0x0E5, 0x000, "SHARC+/Blackfin+", "", }, + { 0x0F0, 0x440, "Qualcomm QDSS Component v1", "(Qualcomm Designed CoreSight Component v1)", }, /* legacy comment: 0x113: what? */ - { ANY_ID, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ - { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ + { ANY_ID, 0x120, "TI SDTI", "(System Debug Trace Interface)", }, /* from OMAP3 memmap */ + { ANY_ID, 0x343, "TI DAPCTL", "", }, /* from OMAP3 memmap */ }; static int dap_rom_display(struct command_context *cmd_ctx, struct adiv5_ap *ap, uint32_t dbgbase, int depth) { - struct adiv5_dap *dap = ap->dap; int retval; - uint32_t cid0, cid1, cid2, cid3, memtype, romentry; - uint16_t entry_offset; + uint64_t pid; + uint32_t cid; char tabs[7] = ""; if (depth > 16) { @@ -971,330 +1063,241 @@ static int dap_rom_display(struct command_context *cmd_ctx, if (depth) snprintf(tabs, sizeof(tabs), "[L%02d] ", depth); - /* bit 16 of apid indicates a memory access port */ - if (dbgbase & 0x02) - command_print(cmd_ctx, "\t%sValid ROM table present", tabs); - else - command_print(cmd_ctx, "\t%sROM table in legacy format", tabs); + uint32_t base_addr = dbgbase & 0xFFFFF000; + command_print(cmd_ctx, "\t\tComponent base address 0x%08" PRIx32, base_addr); - /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF0, &cid0); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF4, &cid1); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFF8, &cid2); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFFC, &cid3); - if (retval != ERROR_OK) - return retval; - retval = mem_ap_read_u32(ap, (dbgbase&0xFFFFF000) | 0xFCC, &memtype); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - return retval; + retval = dap_read_part_id(ap, base_addr, &cid, &pid); + if (retval != ERROR_OK) { + command_print(cmd_ctx, "\t\tCan't read component, the corresponding core might be turned off"); + return ERROR_OK; /* Don't abort recursion */ + } - if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) - command_print(cmd_ctx, "\t%sCID3 0x%02x" - ", CID2 0x%02x" - ", CID1 0x%02x" - ", CID0 0x%02x", - tabs, - (unsigned)cid3, (unsigned)cid2, - (unsigned)cid1, (unsigned)cid0); - if (memtype & 0x01) - command_print(cmd_ctx, "\t%sMEMTYPE system memory present on bus", tabs); - else - command_print(cmd_ctx, "\t%sMEMTYPE system memory not present: dedicated debug bus", tabs); + if (!is_dap_cid_ok(cid)) { + command_print(cmd_ctx, "\t\tInvalid CID 0x%08" PRIx32, cid); + return ERROR_OK; /* Don't abort recursion */ + } + + /* component may take multiple 4K pages */ + uint32_t size = (pid >> 36) & 0xf; + if (size > 0) + command_print(cmd_ctx, "\t\tStart address 0x%08" PRIx32, (uint32_t)(base_addr - 0x1000 * size)); - /* Now we read ROM table entries from dbgbase&0xFFFFF000) | 0x000 until we get 0x00000000 */ - for (entry_offset = 0; ; entry_offset += 4) { - retval = mem_ap_read_atomic_u32(ap, (dbgbase&0xFFFFF000) | entry_offset, &romentry); + command_print(cmd_ctx, "\t\tPeripheral ID 0x%010" PRIx64, pid); + + uint8_t class = (cid >> 12) & 0xf; + uint16_t part_num = pid & 0xfff; + uint16_t designer_id = ((pid >> 32) & 0xf) << 8 | ((pid >> 12) & 0xff); + + if (designer_id & 0x80) { + /* JEP106 code */ + command_print(cmd_ctx, "\t\tDesigner is 0x%03" PRIx16 ", %s", + designer_id, jep106_manufacturer(designer_id >> 8, designer_id & 0x7f)); + } else { + /* Legacy ASCII ID, clear invalid bits */ + designer_id &= 0x7f; + command_print(cmd_ctx, "\t\tDesigner ASCII code 0x%02" PRIx16 ", %s", + designer_id, designer_id == 0x41 ? "ARM" : ""); + } + + /* default values to be overwritten upon finding a match */ + const char *type = "Unrecognized"; + const char *full = ""; + + /* search dap_partnums[] array for a match */ + for (unsigned entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) { + + if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID)) + continue; + + if (dap_partnums[entry].part_num != part_num) + continue; + + type = dap_partnums[entry].type; + full = dap_partnums[entry].full; + break; + } + + command_print(cmd_ctx, "\t\tPart is 0x%" PRIx16", %s %s", part_num, type, full); + command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", class, class_description[class]); + + if (class == 1) { /* ROM Table */ + uint32_t memtype; + retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &memtype); if (retval != ERROR_OK) return retval; - command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", - tabs, entry_offset, romentry); - if (romentry & 0x01) { - uint32_t c_cid0, c_cid1, c_cid2, c_cid3; - uint32_t c_pid0, c_pid1, c_pid2, c_pid3, c_pid4; - uint32_t component_base; - uint16_t part_num, designer_id; - const char *type, *full; - - component_base = (dbgbase & 0xFFFFF000) + (romentry & 0xFFFFF000); - - /* IDs are in last 4K section */ - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE0, &c_pid0); - if (retval != ERROR_OK) { - command_print(cmd_ctx, "\t%s\tCan't read component with base address 0x%" PRIx32 - ", the corresponding core might be turned off", tabs, component_base); - continue; - } - c_pid0 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE4, &c_pid1); - if (retval != ERROR_OK) - return retval; - c_pid1 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFE8, &c_pid2); - if (retval != ERROR_OK) - return retval; - c_pid2 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFEC, &c_pid3); - if (retval != ERROR_OK) - return retval; - c_pid3 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFD0, &c_pid4); - if (retval != ERROR_OK) - return retval; - c_pid4 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF0, &c_cid0); - if (retval != ERROR_OK) - return retval; - c_cid0 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF4, &c_cid1); - if (retval != ERROR_OK) - return retval; - c_cid1 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFF8, &c_cid2); - if (retval != ERROR_OK) - return retval; - c_cid2 &= 0xff; - retval = mem_ap_read_atomic_u32(ap, component_base + 0xFFC, &c_cid3); + if (memtype & 0x01) + command_print(cmd_ctx, "\t\tMEMTYPE system memory present on bus"); + else + command_print(cmd_ctx, "\t\tMEMTYPE system memory not present: dedicated debug bus"); + + /* Read ROM table entries from base address until we get 0x00000000 or reach the reserved area */ + for (uint16_t entry_offset = 0; entry_offset < 0xF00; entry_offset += 4) { + uint32_t romentry; + retval = mem_ap_read_atomic_u32(ap, base_addr | entry_offset, &romentry); if (retval != ERROR_OK) return retval; - c_cid3 &= 0xff; - - command_print(cmd_ctx, "\t\tComponent base address 0x%" PRIx32 ", " - "start address 0x%" PRIx32, component_base, - /* component may take multiple 4K pages */ - (uint32_t)(component_base - 0x1000*(c_pid4 >> 4))); - command_print(cmd_ctx, "\t\tComponent class is 0x%" PRIx8 ", %s", - (uint8_t)((c_cid1 >> 4) & 0xf), - /* See ARM IHI 0029B Table 3-3 */ - class_description[(c_cid1 >> 4) & 0xf]); - - /* CoreSight component? */ - if (((c_cid1 >> 4) & 0x0f) == 9) { - uint32_t devtype; - unsigned minor; - const char *major = "Reserved", *subtype = "Reserved"; - - retval = mem_ap_read_atomic_u32(ap, - (component_base & 0xfffff000) | 0xfcc, - &devtype); + command_print(cmd_ctx, "\t%sROMTABLE[0x%x] = 0x%" PRIx32 "", + tabs, entry_offset, romentry); + if (romentry & 0x01) { + /* Recurse */ + retval = dap_rom_display(cmd_ctx, ap, base_addr + (romentry & 0xFFFFF000), depth + 1); if (retval != ERROR_OK) return retval; - minor = (devtype >> 4) & 0x0f; - switch (devtype & 0x0f) { - case 0: - major = "Miscellaneous"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 4: - subtype = "Validation component"; - break; - } - break; - case 1: - major = "Trace Sink"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Port"; - break; - case 2: - subtype = "Buffer"; - break; - case 3: - subtype = "Router"; - break; - } - break; - case 2: - major = "Trace Link"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Funnel, router"; - break; - case 2: - subtype = "Filter"; - break; - case 3: - subtype = "FIFO, buffer"; - break; - } - break; - case 3: - major = "Trace Source"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 6: - subtype = "Software"; - break; - } - break; - case 4: - major = "Debug Control"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Trigger Matrix"; - break; - case 2: - subtype = "Debug Auth"; - break; - case 3: - subtype = "Power Requestor"; - break; - } - break; - case 5: - major = "Debug Logic"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 5: - subtype = "Memory"; - break; - } - break; - case 6: - major = "Perfomance Monitor"; - switch (minor) { - case 0: - subtype = "other"; - break; - case 1: - subtype = "Processor"; - break; - case 2: - subtype = "DSP"; - break; - case 3: - subtype = "Engine/Coprocessor"; - break; - case 4: - subtype = "Bus"; - break; - case 5: - subtype = "Memory"; - break; - } - break; - } - command_print(cmd_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s", - (uint8_t)(devtype & 0xff), - major, subtype); - /* REVISIT also show 0xfc8 DevId */ + } else if (romentry != 0) { + command_print(cmd_ctx, "\t\tComponent not present"); + } else { + command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs); + break; } + } + } else if (class == 9) { /* CoreSight component */ + const char *major = "Reserved", *subtype = "Reserved"; - if (!is_dap_cid_ok(cid3, cid2, cid1, cid0)) - command_print(cmd_ctx, - "\t\tCID3 0%02x" - ", CID2 0%02x" - ", CID1 0%02x" - ", CID0 0%02x", - (int)c_cid3, - (int)c_cid2, - (int)c_cid1, - (int)c_cid0); - command_print(cmd_ctx, - "\t\tPeripheral ID[4..0] = hex " - "%02x %02x %02x %02x %02x", - (int)c_pid4, (int)c_pid3, (int)c_pid2, - (int)c_pid1, (int)c_pid0); - - part_num = (c_pid0 & 0xff); - part_num |= (c_pid1 & 0x0f) << 8; - designer_id = (c_pid1 & 0xf0) >> 4; - designer_id |= (c_pid2 & 0x0f) << 4; - designer_id |= (c_pid4 & 0x0f) << 8; - if ((designer_id & 0x80) == 0) { - /* Legacy ASCII ID, clear invalid bits */ - designer_id &= 0x7f; + uint32_t devtype; + retval = mem_ap_read_atomic_u32(ap, base_addr | 0xFCC, &devtype); + if (retval != ERROR_OK) + return retval; + unsigned minor = (devtype >> 4) & 0x0f; + switch (devtype & 0x0f) { + case 0: + major = "Miscellaneous"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 4: + subtype = "Validation component"; + break; } - - /* default values to be overwritten upon finding a match */ - type = NULL; - full = ""; - - /* search dap_partnums[] array for a match */ - unsigned entry; - for (entry = 0; entry < ARRAY_SIZE(dap_partnums); entry++) { - - if ((dap_partnums[entry].designer_id != designer_id) && (dap_partnums[entry].designer_id != ANY_ID)) - continue; - - if (dap_partnums[entry].part_num != part_num) - continue; - - type = dap_partnums[entry].type; - full = dap_partnums[entry].full; + break; + case 1: + major = "Trace Sink"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Port"; + break; + case 2: + subtype = "Buffer"; + break; + case 3: + subtype = "Router"; break; } - - if (type) { - command_print(cmd_ctx, "\t\tPart is %s %s", - type, full); - } else { - command_print(cmd_ctx, "\t\tUnrecognized (Part 0x%" PRIx16 ", designer 0x%" PRIx16 ")", - part_num, designer_id); + break; + case 2: + major = "Trace Link"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Funnel, router"; + break; + case 2: + subtype = "Filter"; + break; + case 3: + subtype = "FIFO, buffer"; + break; } - - /* ROM Table? */ - if (((c_cid1 >> 4) & 0x0f) == 1) { - retval = dap_rom_display(cmd_ctx, ap, component_base, depth + 1); - if (retval != ERROR_OK) - return retval; + break; + case 3: + major = "Trace Source"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 6: + subtype = "Software"; + break; } - } else { - if (romentry) - command_print(cmd_ctx, "\t\tComponent not present"); - else + break; + case 4: + major = "Debug Control"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Trigger Matrix"; + break; + case 2: + subtype = "Debug Auth"; + break; + case 3: + subtype = "Power Requestor"; break; + } + break; + case 5: + major = "Debug Logic"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 5: + subtype = "Memory"; + break; + } + break; + case 6: + major = "Perfomance Monitor"; + switch (minor) { + case 0: + subtype = "other"; + break; + case 1: + subtype = "Processor"; + break; + case 2: + subtype = "DSP"; + break; + case 3: + subtype = "Engine/Coprocessor"; + break; + case 4: + subtype = "Bus"; + break; + case 5: + subtype = "Memory"; + break; + } + break; } + command_print(cmd_ctx, "\t\tType is 0x%02" PRIx8 ", %s, %s", + (uint8_t)(devtype & 0xff), + major, subtype); + /* REVISIT also show 0xfc8 DevId */ } - command_print(cmd_ctx, "\t%s\tEnd of ROM table", tabs); + return ERROR_OK; } @@ -1303,7 +1306,6 @@ static int dap_info_command(struct command_context *cmd_ctx, { int retval; uint32_t dbgbase, apid; - int romtable_present = 0; uint8_t mem_ap; /* Now we read ROM table ID registers, ref. ARM IHI 0029B sec */ @@ -1342,16 +1344,56 @@ static int dap_info_command(struct command_context *cmd_ctx, if (mem_ap) { command_print(cmd_ctx, "MEM-AP BASE 0x%8.8" PRIx32, dbgbase); - romtable_present = dbgbase != 0xFFFFFFFF; - if (romtable_present) - dap_rom_display(cmd_ctx, ap, dbgbase, 0); - else + if (dbgbase == 0xFFFFFFFF || (dbgbase & 0x3) == 0x2) { command_print(cmd_ctx, "\tNo ROM table present"); + } else { + if (dbgbase & 0x01) + command_print(cmd_ctx, "\tValid ROM table present"); + else + command_print(cmd_ctx, "\tROM table in legacy format"); + + dap_rom_display(cmd_ctx, ap, dbgbase & 0xFFFFF000, 0); + } } return ERROR_OK; } +int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi) +{ + struct adiv5_private_config *pc; + const char *arg; + jim_wide ap_num; + int e; + + /* check if argv[0] is for us */ + arg = Jim_GetString(goi->argv[0], NULL); + if (strcmp(arg, "-ap-num")) + return JIM_CONTINUE; + + e = Jim_GetOpt_String(goi, &arg, NULL); + if (e != JIM_OK) + return e; + + if (goi->argc == 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-ap-num ?ap-number? ..."); + return JIM_ERR; + } + + e = Jim_GetOpt_Wide(goi, &ap_num); + if (e != JIM_OK) + return e; + + if (target->private_config == NULL) { + pc = calloc(1, sizeof(struct adiv5_private_config)); + target->private_config = pc; + pc->ap_num = ap_num; + } + + + return JIM_OK; +} + COMMAND_HANDLER(handle_dap_info_command) { struct target *target = get_current_target(CMD_CTX); @@ -1547,6 +1589,45 @@ COMMAND_HANDLER(dap_apid_command) return retval; } +COMMAND_HANDLER(dap_apreg_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct arm *arm = target_to_arm(target); + struct adiv5_dap *dap = arm->dap; + + uint32_t apsel, reg, value; + int retval; + + if (CMD_ARGC < 2 || CMD_ARGC > 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); + /* AP address is in bits 31:24 of DP_SELECT */ + if (apsel >= 256) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg); + if (reg >= 256 || (reg & 3)) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 3) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); + retval = dap_queue_ap_write(dap_ap(dap, apsel), reg, value); + } else { + retval = dap_queue_ap_read(dap_ap(dap, apsel), reg, &value); + } + if (retval == ERROR_OK) + retval = dap_run(dap); + + if (retval != ERROR_OK) + return retval; + + if (CMD_ARGC == 2) + command_print(CMD_CTX, "0x%08" PRIx32, value); + + return retval; +} + COMMAND_HANDLER(dap_ti_be_32_quirks_command) { struct target *target = get_current_target(CMD_CTX); @@ -1606,6 +1687,14 @@ static const struct command_registration dap_commands[] = { "(default currently selected AP)", .usage = "[ap_num]", }, + { + .name = "apreg", + .handler = dap_apreg_command, + .mode = COMMAND_EXEC, + .help = "read/write a register from AP " + "(reg is byte address of a word register, like 0 4 8...)", + .usage = "ap_num reg [value]", + }, { .name = "baseaddr", .handler = dap_baseaddr_command, diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index fed25ec2e..bf9cb5cce 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM_ADI_V5_H -#define ARM_ADI_V5_H +#ifndef OPENOCD_TARGET_ARM_ADI_V5_H +#define OPENOCD_TARGET_ARM_ADI_V5_H /** * @file @@ -31,14 +29,9 @@ * resources accessed through a MEM-AP. */ +#include #include "arm_jtag.h" -/* FIXME remove these JTAG-specific decls when mem_ap_read_buf_u32() - * is no longer JTAG-specific - */ -#define JTAG_DP_DPACC 0xA -#define JTAG_DP_APACC 0xB - /* three-bit ACK values for SWD access (sent LSB first) */ #define SWD_ACK_OK 0x1 #define SWD_ACK_WAIT 0x2 @@ -52,18 +45,21 @@ /* A[3:0] for DP registers; A[1:0] are always zero. * - JTAG accesses all of these via JTAG_DP_DPACC, except for * IDCODE (JTAG_DP_IDCODE) and ABORT (JTAG_DP_ABORT). - * - SWD accesses these directly, sometimes needing SELECT.CTRLSEL + * - SWD accesses these directly, sometimes needing SELECT.DPBANKSEL */ -#define DP_IDCODE BANK_REG(0x0, 0x0) /* SWD: read */ -#define DP_ABORT BANK_REG(0x0, 0x0) /* SWD: write */ -#define DP_CTRL_STAT BANK_REG(0x0, 0x4) /* r/w */ -#define DP_RESEND BANK_REG(0x0, 0x8) /* SWD: read */ -#define DP_SELECT BANK_REG(0x0, 0x8) /* JTAG: r/w; SWD: write */ -#define DP_RDBUFF BANK_REG(0x0, 0xC) /* read-only */ -#define DP_WCR BANK_REG(0x1, 0x4) /* SWD: r/w */ - -#define WCR_TO_TRN(wcr) ((uint32_t)(1 + (3 & ((wcr)) >> 8))) /* 1..4 clocks */ -#define WCR_TO_PRESCALE(wcr) ((uint32_t)(7 & ((wcr)))) /* impl defined */ +#define DP_DPIDR BANK_REG(0x0, 0x0) /* DPv1+: ro */ +#define DP_ABORT BANK_REG(0x0, 0x0) /* DPv1+: SWD: wo */ +#define DP_CTRL_STAT BANK_REG(0x0, 0x4) /* DPv0+: rw */ +#define DP_DLCR BANK_REG(0x1, 0x4) /* DPv1+: SWD: rw */ +#define DP_TARGETID BANK_REG(0x2, 0x4) /* DPv2: ro */ +#define DP_DLPIDR BANK_REG(0x3, 0x4) /* DPv2: ro */ +#define DP_EVENTSTAT BANK_REG(0x4, 0x4) /* DPv2: ro */ +#define DP_RESEND BANK_REG(0x0, 0x8) /* DPv1+: SWD: ro */ +#define DP_SELECT BANK_REG(0x0, 0x8) /* DPv0+: JTAG: rw; SWD: wo */ +#define DP_RDBUFF BANK_REG(0x0, 0xC) /* DPv0+: ro */ +#define DP_TARGETSEL BANK_REG(0x0, 0xC) /* DPv2: SWD: wo */ + +#define DLCR_TO_TRN(dlcr) ((uint32_t)(1 + ((3 & (dlcr)) >> 8))) /* 1..4 clocks */ /* Fields of the DP's AP ABORT register */ #define DAPABORT (1UL << 0) @@ -206,6 +202,9 @@ struct adiv5_ap { struct adiv5_dap { const struct dap_ops *ops; + /* dap transaction list for WAIT support */ + struct list_head cmd_journal; + struct jtag_tap *tap; /* Control config */ uint32_t dp_ctrl_stat; @@ -270,6 +269,10 @@ struct dap_ops { /** Executes all queued DAP operations. */ int (*run)(struct adiv5_dap *dap); + + /** Executes all queued DAP operations but doesn't check + * sticky error conditions */ + int (*sync)(struct adiv5_dap *dap); }; /* @@ -393,6 +396,14 @@ static inline int dap_run(struct adiv5_dap *dap) return dap->ops->run(dap); } +static inline int dap_sync(struct adiv5_dap *dap) +{ + assert(dap->ops != NULL); + if (dap->ops->sync) + return dap->ops->sync(dap); + return ERROR_OK; +} + static inline int dap_dp_read_atomic(struct adiv5_dap *dap, unsigned reg, uint32_t *value) { @@ -493,4 +504,10 @@ int dap_to_jtag(struct target *target); extern const struct command_registration dap_command_handlers[]; -#endif +struct adiv5_private_config { + int ap_num; +}; + +extern int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi); + +#endif /* OPENOCD_TARGET_ARM_ADI_V5_H */ diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 65086c2fd..5277b94d8 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -278,7 +276,7 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint8_t cp_num = (opcode & 0xf00) >> 8; /* MCRR or MRRC */ - if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000)) { + if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) { uint8_t cp_opcode, Rd, Rn, CRm; char *mnemonic; diff --git a/src/target/arm_disassembler.h b/src/target/arm_disassembler.h index 4aee3519d..6f8f65d44 100644 --- a/src/target/arm_disassembler.h +++ b/src/target/arm_disassembler.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM_DISASSEMBLER_H -#define ARM_DISASSEMBLER_H +#ifndef OPENOCD_TARGET_ARM_DISASSEMBLER_H +#define OPENOCD_TARGET_ARM_DISASSEMBLER_H enum arm_instruction_type { ARM_UNKNOWN_INSTUCTION, @@ -203,4 +201,4 @@ int arm_access_size(struct arm_instruction *instruction); #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000) >> 28]) -#endif /* ARM_DISASSEMBLER_H */ +#endif /* OPENOCD_TARGET_ARM_DISASSEMBLER_H */ diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 5df625f03..3e8180c36 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H @@ -23,6 +21,7 @@ #include "arm.h" #include "arm_dpm.h" +#include "armv8_dpm.h" #include #include "register.h" #include "breakpoints.h" @@ -167,6 +166,9 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) /* core-specific ... ? */ LOG_WARNING("Jazelle PC adjustment unknown"); break; + default: + LOG_WARNING("unknow core state"); + break; } break; default: @@ -230,6 +232,18 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) return retval; } +/** + * Write to program counter and switch the core state (arm/thumb) according to + * the address. + */ +static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r) +{ + uint32_t value = buf_get_u32(r->value, 0, 32); + + /* read r0 from DCC; then "BX r0" */ + return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value); +} + /** * Read basic registers of the the current context: R0 to R15, and CPSR; * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). @@ -423,20 +437,20 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) /* cope with special cases */ switch (regnum) { - case 8 ... 12: - /* r8..r12 "anything but FIQ" case; - * we "know" core mode is accurate - * since we haven't changed it yet - */ - if (arm->core_mode == ARM_MODE_FIQ - && ARM_MODE_ANY - != mode) - tmode = ARM_MODE_USR; - break; - case 16: - /* SPSR */ - regnum++; - break; + case 8 ... 12: + /* r8..r12 "anything but FIQ" case; + * we "know" core mode is accurate + * since we haven't changed it yet + */ + if (arm->core_mode == ARM_MODE_FIQ + && ARM_MODE_ANY + != mode) + tmode = ARM_MODE_USR; + break; + case 16: + /* SPSR */ + regnum++; + break; } /* REVISIT error checks */ @@ -450,8 +464,8 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) continue; retval = dpm_write_reg(dpm, - &cache->reg_list[i], - regnum); + &cache->reg_list[i], + regnum); if (retval != ERROR_OK) goto done; } @@ -467,6 +481,19 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) goto done; arm->cpsr->dirty = false; + /* restore the PC, make sure to also switch the core state + * to whatever it was set to with "arm core_state" command. + * target code will have set PC to an appropriate resume address. + */ + retval = dpm_write_pc_core_state(dpm, arm->pc); + if (retval != ERROR_OK) + goto done; + /* on Cortex-A5 (as found on NXP VF610 SoC), BX instruction + * executed in debug state doesn't appear to set the PC, + * explicitly set it with a "MOV pc, r0". This doesn't influence + * CPSR on Cortex-A9 so it should be OK. Maybe due to different + * debug version? + */ retval = dpm_write_reg(dpm, arm->pc, 15); if (retval != ERROR_OK) goto done; @@ -882,6 +909,7 @@ void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr) addr -= 4; break; case ARM_STATE_JAZELLE: + case ARM_STATE_AARCH64: /* ?? */ break; } @@ -902,20 +930,16 @@ void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) /* Examine debug reason */ switch (DSCR_ENTRY(dscr)) { - case 6: /* Data abort (v6 only) */ - case 7: /* Prefetch abort (v6 only) */ - /* FALL THROUGH -- assume a v6 core in abort mode */ - case 0: /* HALT request from debugger */ - case 4: /* EDBGRQ */ + case DSCR_ENTRY_HALT_REQ: /* HALT request from debugger */ + case DSCR_ENTRY_EXT_DBG_REQ: /* EDBGRQ */ target->debug_reason = DBG_REASON_DBGRQ; break; - case 1: /* HW breakpoint */ - case 3: /* SW BKPT */ - case 5: /* vector catch */ + case DSCR_ENTRY_BREAKPOINT: /* HW breakpoint */ + case DSCR_ENTRY_BKPT_INSTR: /* vector catch */ target->debug_reason = DBG_REASON_BREAKPOINT; break; - case 2: /* asynch watchpoint */ - case 10:/* precise watchpoint */ + case DSCR_ENTRY_IMPRECISE_WATCHPT: /* asynch watchpoint */ + case DSCR_ENTRY_PRECISE_WATCHPT:/* precise watchpoint */ target->debug_reason = DBG_REASON_WATCHPOINT; break; default: @@ -940,7 +964,7 @@ int arm_dpm_setup(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct target *target = arm->target; - struct reg_cache *cache; + struct reg_cache *cache = 0; arm->dpm = dpm; @@ -949,11 +973,13 @@ int arm_dpm_setup(struct arm_dpm *dpm) arm->read_core_reg = arm_dpm_read_core_reg; arm->write_core_reg = arm_dpm_write_core_reg; - cache = arm_build_reg_cache(target, arm); - if (!cache) - return ERROR_FAIL; + if (arm->core_cache == NULL) { + cache = arm_build_reg_cache(target, arm); + if (!cache) + return ERROR_FAIL; - *register_get_last_cache_p(&target->reg_cache) = cache; + *register_get_last_cache_p(&target->reg_cache) = cache; + } /* coprocessor access setup */ arm->mrc = dpm_mrc; @@ -972,9 +998,8 @@ int arm_dpm_setup(struct arm_dpm *dpm) /* FIXME add vector catch support */ dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); - dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); - dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); + dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); if (!dpm->dbp || !dpm->dwp) { diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 73ed1bcf0..f8d124813 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ -#ifndef __ARM_DPM_H -#define __ARM_DPM_H +#ifndef OPENOCD_TARGET_ARM_DPM_H +#define OPENOCD_TARGET_ARM_DPM_H /** * @file @@ -61,7 +59,7 @@ struct arm_dpm { struct arm *arm; /** Cache of DIDR */ - uint32_t didr; + uint64_t didr; /** Invoke before a series of instruction operations */ int (*prepare)(struct arm_dpm *); @@ -69,16 +67,26 @@ struct arm_dpm { /** Invoke after a series of instruction operations */ int (*finish)(struct arm_dpm *); + /** Runs one instruction. */ + int (*instr_execute)(struct arm_dpm *, uint32_t opcode); + /* WRITE TO CPU */ /** Runs one instruction, writing data to DCC before execution. */ int (*instr_write_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t data); + int (*instr_write_data_dcc_64)(struct arm_dpm *, + uint32_t opcode, uint64_t data); + /** Runs one instruction, writing data to R0 before execution. */ int (*instr_write_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t data); + /** Runs one instruction, writing data to R0 before execution. */ + int (*instr_write_data_r0_64)(struct arm_dpm *, + uint32_t opcode, uint64_t data); + /** Optional core-specific operation invoked after CPSR writes. */ int (*instr_cpsr_sync)(struct arm_dpm *dpm); @@ -88,10 +96,19 @@ struct arm_dpm { int (*instr_read_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t *data); + int (*instr_read_data_dcc_64)(struct arm_dpm *, + uint32_t opcode, uint64_t *data); + /** Runs one instruction, reading data from r0 after execution. */ int (*instr_read_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t *data); + int (*instr_read_data_r0_64)(struct arm_dpm *, + uint32_t opcode, uint64_t *data); + + struct reg *(*arm_reg_current)(struct arm *arm, + unsigned regnum); + /* BREAKPOINT/WATCHPOINT SUPPORT */ /** @@ -121,11 +138,14 @@ struct arm_dpm { struct dpm_wp *dwp; /** Address of the instruction which triggered a watchpoint. */ - uint32_t wp_pc; + target_addr_t wp_pc; /** Recent value of DSCR. */ uint32_t dscr; + /** Recent exception level on armv8 */ + unsigned int last_el; + /* FIXME -- read/write DCSR methods and symbols */ }; @@ -135,7 +155,6 @@ int arm_dpm_initialize(struct arm_dpm *dpm); int arm_dpm_read_current_registers(struct arm_dpm *); int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); - int arm_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp); void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); @@ -168,21 +187,21 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); #define DSCR_DTR_TX_FULL (0x1 << 29) #define DSCR_DTR_RX_FULL (0x1 << 30) /* bit 31 is reserved */ -#define DSCR_ENTRY(dscr) (((dscr) >> 2) & 0xf) -#define DSCR_RUN_MODE(dscr) ((dscr) & (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) +#define DSCR_ENTRY(dscr) ((dscr) & 0x3f) +#define DSCR_RUN_MODE(dscr) ((dscr) & 0x03) /* Methods of entry into debug mode */ -#define DSCR_ENTRY_HALT_REQ (0x0 << 2) -#define DSCR_ENTRY_BREAKPOINT (0x1 << 2) -#define DSCR_ENTRY_IMPRECISE_WATCHPT (0x2 << 2) -#define DSCR_ENTRY_BKPT_INSTR (0x3 << 2) -#define DSCR_ENTRY_EXT_DBG_REQ (0x4 << 2) -#define DSCR_ENTRY_VECT_CATCH (0x5 << 2) -#define DSCR_ENTRY_D_SIDE_ABORT (0x6 << 2) /* v6 only */ -#define DSCR_ENTRY_I_SIDE_ABORT (0x7 << 2) /* v6 only */ -#define DSCR_ENTRY_OS_UNLOCK (0x8 << 2) -#define DSCR_ENTRY_PRECISE_WATCHPT (0xA << 2) +#define DSCR_ENTRY_HALT_REQ (0x03) +#define DSCR_ENTRY_BREAKPOINT (0x07) +#define DSCR_ENTRY_IMPRECISE_WATCHPT (0x0B) +#define DSCR_ENTRY_BKPT_INSTR (0x0F) +#define DSCR_ENTRY_EXT_DBG_REQ (0x13) +#define DSCR_ENTRY_VECT_CATCH (0x17) +#define DSCR_ENTRY_D_SIDE_ABORT (0x1B) /* v6 only */ +#define DSCR_ENTRY_I_SIDE_ABORT (0x1F) /* v6 only */ +#define DSCR_ENTRY_OS_UNLOCK (0x23) +#define DSCR_ENTRY_PRECISE_WATCHPT (0x2B) /* DTR modes */ #define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20) @@ -200,4 +219,25 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); -#endif /* __ARM_DPM_H */ +/* PRCR (Device Power-down and Reset Control Register) bits */ +#define PRCR_DEBUG_NO_POWER_DOWN (1 << 0) +#define PRCR_WARM_RESET (1 << 1) +#define PRCR_HOLD_NON_DEBUG_RESET (1 << 2) + +/* PRSR (Device Power-down and Reset Status Register) bits */ +#define PRSR_POWERUP_STATUS (1 << 0) +#define PRSR_STICKY_POWERDOWN_STATUS (1 << 1) +#define PRSR_RESET_STATUS (1 << 2) +#define PRSR_STICKY_RESET_STATUS (1 << 3) +#define PRSR_HALTED (1 << 4) /* v7.1 Debug only */ +#define PRSR_OSLK (1 << 5) /* v7.1 Debug only */ +#define PRSR_DLK (1 << 6) /* v7.1 Debug only */ + +/* OSLSR (OS Lock Status Register) bits */ +#define OSLSR_OSLM0 (1 << 0) +#define OSLSR_OSLK (1 << 1) +#define OSLSR_nTT (1 << 2) +#define OSLSR_OSLM1 (1 << 3) +#define OSLSR_OSLM (OSLSR_OSLM0|OSLSR_OSLM1) + +#endif /* OPENOCD_TARGET_ARM_DPM_H */ diff --git a/src/target/arm_jtag.c b/src/target/arm_jtag.c index d2b9feeed..9b73d4ea8 100644 --- a/src/target/arm_jtag.c +++ b/src/target/arm_jtag.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/arm_jtag.h b/src/target/arm_jtag.h index dbfec857b..bb92abb84 100644 --- a/src/target/arm_jtag.h +++ b/src/target/arm_jtag.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM_JTAG -#define ARM_JTAG +#ifndef OPENOCD_TARGET_ARM_JTAG_H +#define OPENOCD_TARGET_ARM_JTAG_H #include @@ -77,4 +75,4 @@ static inline void arm_le_to_h_u32(jtag_callback_data_t arg) *((uint32_t *)arg) = le_to_h_u32(in); } -#endif /* ARM_JTAG */ +#endif /* OPENOCD_TARGET_ARM_JTAG_H */ diff --git a/src/target/arm_opcodes.h b/src/target/arm_opcodes.h index 81c4766ad..a53fee71e 100644 --- a/src/target/arm_opcodes.h +++ b/src/target/arm_opcodes.h @@ -22,12 +22,11 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ -#ifndef __ARM_OPCODES_H -#define __ARM_OPCODES_H + +#ifndef OPENOCD_TARGET_ARM_OPCODES_H +#define OPENOCD_TARGET_ARM_OPCODES_H /** * @file @@ -311,4 +310,4 @@ ((0xB660 | (0 << 8) | ((IF)&0x3)) \ | ((0xB660 | (0 << 8) | ((IF)&0x3)) << 16)) -#endif /* __ARM_OPCODES_H */ +#endif /* OPENOCD_TARGET_ARM_OPCODES_H */ diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 21b7809c2..252511962 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -5,6 +5,9 @@ * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -16,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /** @@ -41,8 +42,11 @@ #include "armv4_5.h" #include "arm7_9_common.h" #include "armv7m.h" +#include "armv7a.h" #include "cortex_m.h" #include "register.h" +#include "arm_opcodes.h" +#include "target_type.h" #include "arm_semihosting.h" #include #include @@ -63,13 +67,59 @@ static const int open_modeflags[12] = { O_RDWR | O_CREAT | O_APPEND | O_BINARY }; +static int post_result(struct target *target) +{ + struct arm *arm = target_to_arm(target); + + /* REVISIT this looks wrong ... ARM11 and Cortex-A8 + * should work this way at least sometimes. + */ + if (is_arm7_9(target_to_arm7_9(target)) || + is_armv7a(target_to_armv7a(target))) { + uint32_t spsr; + + /* return value in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + arm->core_cache->reg_list[0].dirty = 1; + + /* LR --> PC */ + buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, + buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); + arm->core_cache->reg_list[15].dirty = 1; + + /* saved PSR --> current PSR */ + spsr = buf_get_u32(arm->spsr->value, 0, 32); + + /* REVISIT should this be arm_set_cpsr(arm, spsr) + * instead of a partially unrolled version? + */ + + buf_set_u32(arm->cpsr->value, 0, 32, spsr); + arm->cpsr->dirty = 1; + arm->core_mode = spsr & 0x1f; + if (spsr & 0x20) + arm->core_state = ARM_STATE_THUMB; + + } else { + /* resume execution, this will be pc+2 to skip over the + * bkpt instruction */ + + /* return result in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + arm->core_cache->reg_list[0].dirty = 1; + } + + return ERROR_OK; +} + static int do_semihosting(struct target *target) { struct arm *arm = target_to_arm(target); + struct gdb_fileio_info *fileio_info = target->fileio_info; uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); uint8_t params[16]; - int retval, result; + int retval; /* * TODO: lots of security issues are not considered yet, such as: @@ -77,10 +127,10 @@ static int do_semihosting(struct target *target) * - no safety checks on opened/deleted/renamed file paths * Beware the target app you use this support with. * - * TODO: explore mapping requests to GDB's "File-I/O Remote - * Protocol Extension" ... when GDB is active. + * TODO: unsupported semihosting fileio operations could be + * implemented if we had a small working area at our disposal. */ - switch (r0) { + switch ((arm->semihosting_op = r0)) { case 0x01: /* SYS_OPEN */ retval = target_read_memory(target, r1, 4, 3, params); if (retval != ERROR_OK) @@ -89,27 +139,40 @@ static int do_semihosting(struct target *target) uint32_t a = target_buffer_get_u32(target, params+0); uint32_t m = target_buffer_get_u32(target, params+4); uint32_t l = target_buffer_get_u32(target, params+8); - if (l <= 255 && m <= 11) { - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - if (strcmp((char *)fn, ":tt") == 0) { - if (m < 4) - result = dup(STDIN_FILENO); - else - result = dup(STDOUT_FILENO); - } else { - /* cygwin requires the permission setting - * otherwise it will fail to reopen a previously - * written file */ - result = open((char *)fn, open_modeflags[m], 0644); + uint8_t fn[256]; + retval = target_read_memory(target, a, 1, l, fn); + if (retval != ERROR_OK) + return retval; + fn[l] = 0; + if (arm->is_semihosting_fileio) { + if (strcmp((char *)fn, ":tt") == 0) + arm->semihosting_result = 0; + else { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "open"; + fileio_info->param_1 = a; + fileio_info->param_2 = l; + fileio_info->param_3 = open_modeflags[m]; + fileio_info->param_4 = 0644; } - arm->semihosting_errno = errno; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l <= 255 && m <= 11) { + if (strcmp((char *)fn, ":tt") == 0) { + if (m < 4) + arm->semihosting_result = dup(STDIN_FILENO); + else + arm->semihosting_result = dup(STDOUT_FILENO); + } else { + /* cygwin requires the permission setting + * otherwise it will fail to reopen a previously + * written file */ + arm->semihosting_result = open((char *)fn, open_modeflags[m], 0644); + } + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; @@ -120,33 +183,63 @@ static int do_semihosting(struct target *target) return retval; else { int fd = target_buffer_get_u32(target, params+0); - result = close(fd); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "close"; + fileio_info->param_1 = fd; + } else { + arm->semihosting_result = close(fd); + arm->semihosting_errno = errno; + } } break; case 0x03: /* SYS_WRITEC */ - { + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = r1; + fileio_info->param_3 = 1; + } else { unsigned char c; retval = target_read_memory(target, r1, 1, 1, &c); if (retval != ERROR_OK) return retval; putchar(c); - result = 0; + arm->semihosting_result = 0; } break; case 0x04: /* SYS_WRITE0 */ - do { - unsigned char c; - retval = target_read_memory(target, r1++, 1, 1, &c); - if (retval != ERROR_OK) - return retval; - if (!c) - break; - putchar(c); - } while (1); - result = 0; + if (arm->is_semihosting_fileio) { + size_t count = 0; + for (uint32_t a = r1;; a++) { + unsigned char c; + retval = target_read_memory(target, a, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (c == '\0') + break; + count++; + } + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = r1; + fileio_info->param_3 = count; + } else { + do { + unsigned char c; + retval = target_read_memory(target, r1++, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (!c) + break; + putchar(c); + } while (1); + arm->semihosting_result = 0; + } break; case 0x05: /* SYS_WRITE */ @@ -157,21 +250,29 @@ static int do_semihosting(struct target *target) int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); size_t l = target_buffer_get_u32(target, params+8); - uint8_t *buf = malloc(l); - if (!buf) { - result = -1; - arm->semihosting_errno = ENOMEM; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = fd; + fileio_info->param_2 = a; + fileio_info->param_3 = l; } else { - retval = target_read_buffer(target, a, l, buf); - if (retval != ERROR_OK) { + uint8_t *buf = malloc(l); + if (!buf) { + arm->semihosting_result = -1; + arm->semihosting_errno = ENOMEM; + } else { + retval = target_read_buffer(target, a, l, buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + arm->semihosting_result = write(fd, buf, l); + arm->semihosting_errno = errno; + if (arm->semihosting_result >= 0) + arm->semihosting_result = l - arm->semihosting_result; free(buf); - return retval; } - result = write(fd, buf, l); - arm->semihosting_errno = errno; - if (result >= 0) - result = l - result; - free(buf); } } break; @@ -184,42 +285,60 @@ static int do_semihosting(struct target *target) int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); ssize_t l = target_buffer_get_u32(target, params+8); - uint8_t *buf = malloc(l); - if (!buf) { - result = -1; - arm->semihosting_errno = ENOMEM; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "read"; + fileio_info->param_1 = fd; + fileio_info->param_2 = a; + fileio_info->param_3 = l; } else { - result = read(fd, buf, l); - arm->semihosting_errno = errno; - if (result >= 0) { - retval = target_write_buffer(target, a, result, buf); - if (retval != ERROR_OK) { - free(buf); - return retval; + uint8_t *buf = malloc(l); + if (!buf) { + arm->semihosting_result = -1; + arm->semihosting_errno = ENOMEM; + } else { + arm->semihosting_result = read(fd, buf, l); + arm->semihosting_errno = errno; + if (arm->semihosting_result >= 0) { + retval = target_write_buffer(target, a, arm->semihosting_result, buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + arm->semihosting_result = l - arm->semihosting_result; } - result = l - result; + free(buf); } - free(buf); } } break; case 0x07: /* SYS_READC */ - result = getchar(); + if (arm->is_semihosting_fileio) { + LOG_ERROR("SYS_READC not supported by semihosting fileio"); + return ERROR_FAIL; + } + arm->semihosting_result = getchar(); break; case 0x08: /* SYS_ISERROR */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; - result = (target_buffer_get_u32(target, params+0) != 0); + arm->semihosting_result = (target_buffer_get_u32(target, params+0) != 0); break; case 0x09: /* SYS_ISTTY */ - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - result = isatty(target_buffer_get_u32(target, params+0)); + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "isatty"; + fileio_info->param_1 = r1; + } else { + retval = target_read_memory(target, r1, 4, 1, params); + if (retval != ERROR_OK) + return retval; + arm->semihosting_result = isatty(target_buffer_get_u32(target, params+0)); + } break; case 0x0a: /* SYS_SEEK */ @@ -229,27 +348,39 @@ static int do_semihosting(struct target *target) else { int fd = target_buffer_get_u32(target, params+0); off_t pos = target_buffer_get_u32(target, params+4); - result = lseek(fd, pos, SEEK_SET); - arm->semihosting_errno = errno; - if (result == pos) - result = 0; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "lseek"; + fileio_info->param_1 = fd; + fileio_info->param_2 = pos; + fileio_info->param_3 = SEEK_SET; + } else { + arm->semihosting_result = lseek(fd, pos, SEEK_SET); + arm->semihosting_errno = errno; + if (arm->semihosting_result == pos) + arm->semihosting_result = 0; + } } break; case 0x0c: /* SYS_FLEN */ + if (arm->is_semihosting_fileio) { + LOG_ERROR("SYS_FLEN not supported by semihosting fileio"); + return ERROR_FAIL; + } retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); struct stat buf; - result = fstat(fd, &buf); - if (result == -1) { + arm->semihosting_result = fstat(fd, &buf); + if (arm->semihosting_result == -1) { arm->semihosting_errno = errno; - result = -1; + arm->semihosting_result = -1; break; } - result = buf.st_size; + arm->semihosting_result = buf.st_size; } break; @@ -260,17 +391,24 @@ static int do_semihosting(struct target *target) else { uint32_t a = target_buffer_get_u32(target, params+0); uint32_t l = target_buffer_get_u32(target, params+4); - if (l <= 255) { - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - result = remove((char *)fn); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "unlink"; + fileio_info->param_1 = a; + fileio_info->param_2 = l; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l <= 255) { + uint8_t fn[256]; + retval = target_read_memory(target, a, 1, l, fn); + if (retval != ERROR_OK) + return retval; + fn[l] = 0; + arm->semihosting_result = remove((char *)fn); + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; @@ -284,31 +422,40 @@ static int do_semihosting(struct target *target) uint32_t l1 = target_buffer_get_u32(target, params+4); uint32_t a2 = target_buffer_get_u32(target, params+8); uint32_t l2 = target_buffer_get_u32(target, params+12); - if (l1 <= 255 && l2 <= 255) { - uint8_t fn1[256], fn2[256]; - retval = target_read_memory(target, a1, 1, l1, fn1); - if (retval != ERROR_OK) - return retval; - retval = target_read_memory(target, a2, 1, l2, fn2); - if (retval != ERROR_OK) - return retval; - fn1[l1] = 0; - fn2[l2] = 0; - result = rename((char *)fn1, (char *)fn2); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "rename"; + fileio_info->param_1 = a1; + fileio_info->param_2 = l1; + fileio_info->param_3 = a2; + fileio_info->param_4 = l2; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l1 <= 255 && l2 <= 255) { + uint8_t fn1[256], fn2[256]; + retval = target_read_memory(target, a1, 1, l1, fn1); + if (retval != ERROR_OK) + return retval; + retval = target_read_memory(target, a2, 1, l2, fn2); + if (retval != ERROR_OK) + return retval; + fn1[l1] = 0; + fn2[l2] = 0; + arm->semihosting_result = rename((char *)fn1, (char *)fn2); + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; case 0x11: /* SYS_TIME */ - result = time(NULL); + arm->semihosting_result = time(NULL); break; case 0x13: /* SYS_ERRNO */ - result = arm->semihosting_errno; + arm->semihosting_result = arm->semihosting_errno; break; case 0x15: /* SYS_GET_CMDLINE */ @@ -321,12 +468,12 @@ static int do_semihosting(struct target *target) char *arg = "foobar"; uint32_t s = strlen(arg) + 1; if (l < s) - result = -1; + arm->semihosting_result = -1; else { retval = target_write_buffer(target, a, s, (uint8_t *)arg); if (retval != ERROR_OK) return retval; - result = 0; + arm->semihosting_result = 0; } } break; @@ -342,7 +489,7 @@ static int do_semihosting(struct target *target) retval = target_write_memory(target, a, 4, 4, params); if (retval != ERROR_OK) return retval; - result = 0; + arm->semihosting_result = 0; } break; @@ -386,17 +533,24 @@ static int do_semihosting(struct target *target) else { uint32_t len = target_buffer_get_u32(target, params+4); uint32_t c_ptr = target_buffer_get_u32(target, params); - uint8_t cmd[256]; - if (len > 255) { - result = -1; - arm->semihosting_errno = EINVAL; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "system"; + fileio_info->param_1 = c_ptr; + fileio_info->param_2 = len; } else { - memset(cmd, 0x0, 256); - retval = target_read_memory(target, c_ptr, 1, len, cmd); - if (retval != ERROR_OK) - return retval; - else - result = system((const char *)cmd); + uint8_t cmd[256]; + if (len > 255) { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } else { + memset(cmd, 0x0, 256); + retval = target_read_memory(target, c_ptr, 1, len, cmd); + if (retval != ERROR_OK) + return retval; + else + arm->semihosting_result = system((const char *)cmd); + } } } break; @@ -408,50 +562,84 @@ static int do_semihosting(struct target *target) default: fprintf(stderr, "semihosting: unsupported call %#x\n", (unsigned) r0); - result = -1; + arm->semihosting_result = -1; arm->semihosting_errno = ENOTSUP; } - /* resume execution to the original mode */ + return ERROR_OK; +} - /* REVISIT this looks wrong ... ARM11 and Cortex-A8 - * should work this way at least sometimes. +static int get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) +{ + struct arm *arm = target_to_arm(target); + + /* To avoid uneccessary duplication, semihosting prepares the + * fileio_info structure out-of-band when the target halts. See + * do_semihosting for more detail. */ - if (is_arm7_9(target_to_arm7_9(target))) { - uint32_t spsr; + if (!arm->is_semihosting_fileio || !arm->semihosting_hit_fileio) + return ERROR_FAIL; - /* return value in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); - arm->core_cache->reg_list[0].dirty = 1; + return ERROR_OK; +} - /* LR --> PC */ - buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, - buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); - arm->core_cache->reg_list[15].dirty = 1; +static int gdb_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c) +{ + struct arm *arm = target_to_arm(target); + struct gdb_fileio_info *fileio_info = target->fileio_info; - /* saved PSR --> current PSR */ - spsr = buf_get_u32(arm->spsr->value, 0, 32); + /* clear pending status */ + arm->semihosting_hit_fileio = false; - /* REVISIT should this be arm_set_cpsr(arm, spsr) - * instead of a partially unrolled version? - */ + arm->semihosting_result = result; + arm->semihosting_errno = fileio_errno; - buf_set_u32(arm->cpsr->value, 0, 32, spsr); - arm->cpsr->dirty = 1; - arm->core_mode = spsr & 0x1f; - if (spsr & 0x20) - arm->core_state = ARM_STATE_THUMB; + /* Some fileio results do not match up with what the semihosting + * operation expects; for these operations, we munge the results + * below: + */ + switch (arm->semihosting_op) { + case 0x05: /* SYS_WRITE */ + if (result < 0) + arm->semihosting_result = fileio_info->param_3; + else + arm->semihosting_result = 0; + break; - } else { - /* resume execution, this will be pc+2 to skip over the - * bkpt instruction */ + case 0x06: /* SYS_READ */ + if (result == (int)fileio_info->param_3) + arm->semihosting_result = 0; + if (result <= 0) + arm->semihosting_result = fileio_info->param_3; + break; - /* return result in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); - arm->core_cache->reg_list[0].dirty = 1; + case 0x0a: /* SYS_SEEK */ + if (result > 0) + arm->semihosting_result = 0; + break; } - return target_resume(target, 1, 0, 0, 0); + return post_result(target); +} + +/** + * Initialize ARM semihosting support. + * + * @param target Pointer to the ARM target to initialize. + * @return An error status if there is a problem during initialization. + */ +int arm_semihosting_init(struct target *target) +{ + target->fileio_info = malloc(sizeof(*target->fileio_info)); + if (target->fileio_info == NULL) { + LOG_ERROR("out of memory"); + return ERROR_FAIL; + } + + target->type->get_gdb_fileio_info = get_gdb_fileio_info; + target->type->gdb_fileio_end = gdb_fileio_end; + + return ERROR_OK; } /** @@ -470,20 +658,42 @@ static int do_semihosting(struct target *target) int arm_semihosting(struct target *target, int *retval) { struct arm *arm = target_to_arm(target); + struct armv7a_common *armv7a = target_to_armv7a(target); uint32_t pc, lr, spsr; struct reg *r; if (!arm->is_semihosting) return 0; - if (is_arm7_9(target_to_arm7_9(target))) { + if (is_arm7_9(target_to_arm7_9(target)) || + is_armv7a(armv7a)) { + uint32_t vbar = 0x00000000; + if (arm->core_mode != ARM_MODE_SVC) return 0; + if (is_armv7a(armv7a)) { + struct arm_dpm *dpm = armv7a->arm.dpm; + + *retval = dpm->prepare(dpm); + if (*retval == ERROR_OK) { + *retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 12, 0, 0), + &vbar); + + dpm->finish(dpm); + + if (*retval != ERROR_OK) + return 1; + } else { + return 1; + } + } + /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */ r = arm->pc; pc = buf_get_u32(r->value, 0, 32); - if (pc != 0x00000008 && pc != 0xffff0008) + if (pc != (vbar + 0x00000008) && pc != 0xffff0008) return 0; r = arm_reg_current(arm, 14); @@ -553,6 +763,35 @@ int arm_semihosting(struct target *target, int *retval) return 0; } - *retval = do_semihosting(target); - return 1; + /* Perform semihosting if we are not waiting on a fileio + * operation to complete. + */ + if (!arm->semihosting_hit_fileio) { + *retval = do_semihosting(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed semihosting operation"); + return 0; + } + } + + /* Post result to target if we are not waiting on a fileio + * operation to complete: + */ + if (!arm->semihosting_hit_fileio) { + *retval = post_result(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to post semihosting result"); + return 0; + } + + *retval = target_resume(target, 1, 0, 0, 0); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to resume target"); + return 0; + } + + return 1; + } + + return 0; } diff --git a/src/target/arm_semihosting.h b/src/target/arm_semihosting.h index 58b343266..011f19f00 100644 --- a/src/target/arm_semihosting.h +++ b/src/target/arm_semihosting.h @@ -13,14 +13,13 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM_SEMIHOSTING_H -#define ARM_SEMIHOSTING_H +#ifndef OPENOCD_TARGET_ARM_SEMIHOSTING_H +#define OPENOCD_TARGET_ARM_SEMIHOSTING_H +int arm_semihosting_init(struct target *target); int arm_semihosting(struct target *target, int *retval); -#endif +#endif /* OPENOCD_TARGET_ARM_SEMIHOSTING_H */ diff --git a/src/target/arm_simulator.c b/src/target/arm_simulator.c index 26f5b8e16..245e108ac 100644 --- a/src/target/arm_simulator.c +++ b/src/target/arm_simulator.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/arm_simulator.h b/src/target/arm_simulator.h index 3aedaee2e..5bdbf562c 100644 --- a/src/target/arm_simulator.h +++ b/src/target/arm_simulator.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM_SIMULATOR_H -#define ARM_SIMULATOR_H +#ifndef OPENOCD_TARGET_ARM_SIMULATOR_H +#define OPENOCD_TARGET_ARM_SIMULATOR_H struct target; @@ -38,4 +36,4 @@ struct arm_sim_interface { /* armv4_5 version */ int arm_simulate_step(struct target *target, uint32_t *dry_run_pc); -#endif /* ARM_SIMULATOR_H */ +#endif /* OPENOCD_TARGET_ARM_SIMULATOR_H */ diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index e75fe99c4..2029ca92a 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -140,6 +138,12 @@ static const struct { .n_indices = ARRAY_SIZE(arm_mon_indices), .indices = arm_mon_indices, }, + { + .name = "Secure Monitor ARM1176JZF-S", + .psr = ARM_MODE_1176_MON, + .n_indices = ARRAY_SIZE(arm_mon_indices), + .indices = arm_mon_indices, + }, /* These special modes are currently only supported * by ARMv6M and ARMv7M profiles */ @@ -199,6 +203,7 @@ int arm_mode_to_number(enum arm_mode mode) case ARM_MODE_SYS: return 6; case ARM_MODE_MON: + case ARM_MODE_1176_MON: return 7; default: LOG_ERROR("invalid mode value encountered %d", mode); @@ -661,14 +666,19 @@ int arm_arch_state(struct target *target) return ERROR_FAIL; } + /* avoid filling log waiting for fileio reply */ + if (arm->semihosting_hit_fileio) + return ERROR_OK; + LOG_USER("target halted in %s state due to %s, current mode: %s\n" - "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s", + "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s%s", arm_state_strings[arm->core_state], debug_reason_name(target), arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), - arm->is_semihosting ? ", semihosting" : ""); + arm->is_semihosting ? ", semihosting" : "", + arm->is_semihosting_fileio ? " fileio" : ""); return ERROR_OK; } @@ -806,7 +816,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) } struct arm *arm = target_to_arm(target); - uint32_t address; + target_addr_t address; int count = 1; int thumb = 0; @@ -830,7 +840,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count); /* FALL THROUGH */ case 1: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); if (address & 0x01) { if (!thumb) { command_print(CMD_CTX, "Disassemble as Thumb"); @@ -1050,6 +1060,37 @@ COMMAND_HANDLER(handle_arm_semihosting_command) return ERROR_OK; } +COMMAND_HANDLER(handle_arm_semihosting_fileio_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct arm *arm = target_to_arm(target); + + if (!is_arm(arm)) { + command_print(CMD_CTX, "current target isn't an ARM"); + return ERROR_FAIL; + } + + if (!arm->is_semihosting) { + command_print(CMD_CTX, "semihosting is not enabled"); + return ERROR_FAIL; + } + + if (CMD_ARGC > 0) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm->is_semihosting_fileio); + + command_print(CMD_CTX, "semihosting fileio is %s", + arm->is_semihosting_fileio + ? "enabled" : "disabled"); + + return ERROR_OK; +} + static const struct command_registration arm_exec_command_handlers[] = { { .name = "reg", @@ -1092,6 +1133,13 @@ static const struct command_registration arm_exec_command_handlers[] = { .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, + { + "semihosting_fileio", + .handler = handle_arm_semihosting_fileio_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting fileio operations", + }, COMMAND_REGISTRATION_DONE }; @@ -1386,8 +1434,8 @@ int armv4_5_run_algorithm(struct target *target, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, - uint32_t exit_point, + target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info) { @@ -1396,8 +1444,8 @@ int armv4_5_run_algorithm(struct target *target, mem_params, num_reg_params, reg_params, - entry_point, - exit_point, + (uint32_t)entry_point, + (uint32_t)exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion); @@ -1408,7 +1456,7 @@ int armv4_5_run_algorithm(struct target *target, * */ int arm_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct arm_algorithm arm_algo; @@ -1418,49 +1466,24 @@ int arm_checksum_memory(struct target *target, uint32_t i; uint32_t exit_var = 0; - /* see contrib/loaders/checksum/armv4_5_crc.s for src */ - - static const uint32_t arm_crc_code[] = { - 0xE1A02000, /* mov r2, r0 */ - 0xE3E00000, /* mov r0, #0xffffffff */ - 0xE1A03001, /* mov r3, r1 */ - 0xE3A04000, /* mov r4, #0 */ - 0xEA00000B, /* b ncomp */ - /* nbyte: */ - 0xE7D21004, /* ldrb r1, [r2, r4] */ - 0xE59F7030, /* ldr r7, CRC32XOR */ - 0xE0200C01, /* eor r0, r0, r1, asl 24 */ - 0xE3A05000, /* mov r5, #0 */ - /* loop: */ - 0xE3500000, /* cmp r0, #0 */ - 0xE1A06080, /* mov r6, r0, asl #1 */ - 0xE2855001, /* add r5, r5, #1 */ - 0xE1A00006, /* mov r0, r6 */ - 0xB0260007, /* eorlt r0, r6, r7 */ - 0xE3550008, /* cmp r5, #8 */ - 0x1AFFFFF8, /* bne loop */ - 0xE2844001, /* add r4, r4, #1 */ - /* ncomp: */ - 0xE1540003, /* cmp r4, r3 */ - 0x1AFFFFF1, /* bne nbyte */ - /* end: */ - 0xe1200070, /* bkpt #0 */ - /* CRC32XOR: */ - 0x04C11DB7 /* .word 0x04C11DB7 */ + static const uint8_t arm_crc_code_le[] = { +#include "../../contrib/loaders/checksum/armv4_5_crc.inc" }; + assert(sizeof(arm_crc_code_le) % 4 == 0); + retval = target_alloc_working_area(target, - sizeof(arm_crc_code), &crc_algorithm); + sizeof(arm_crc_code_le), &crc_algorithm); if (retval != ERROR_OK) return retval; /* convert code into a buffer in target endianness */ - for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) { + for (i = 0; i < ARRAY_SIZE(arm_crc_code_le) / 4; i++) { retval = target_write_u32(target, crc_algorithm->address + i * sizeof(uint32_t), - arm_crc_code[i]); + le_to_h_u32(&arm_crc_code_le[i * 4])); if (retval != ERROR_OK) - return retval; + goto cleanup; } arm_algo.common_magic = ARM_COMMON_MAGIC; @@ -1478,28 +1501,25 @@ int arm_checksum_memory(struct target *target, /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) - exit_var = crc_algorithm->address + sizeof(arm_crc_code) - 8; + exit_var = crc_algorithm->address + sizeof(arm_crc_code_le) - 8; retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, exit_var, timeout, &arm_algo); - if (retval != ERROR_OK) { - LOG_ERROR("error executing ARM crc algorithm"); - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - target_free_working_area(target, crc_algorithm); - return retval; - } - *checksum = buf_get_u32(reg_params[0].value, 0, 32); + if (retval == ERROR_OK) + *checksum = buf_get_u32(reg_params[0].value, 0, 32); + else + LOG_ERROR("error executing ARM crc algorithm"); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); +cleanup: target_free_working_area(target, crc_algorithm); - return ERROR_OK; + return retval; } /** @@ -1509,7 +1529,7 @@ int arm_checksum_memory(struct target *target, * */ int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *check_algorithm; struct reg_param reg_params[3]; @@ -1519,32 +1539,32 @@ int arm_blank_check_memory(struct target *target, uint32_t i; uint32_t exit_var = 0; - /* see contrib/loaders/erase_check/armv4_5_erase_check.s for src */ - - static const uint32_t check_code[] = { - /* loop: */ - 0xe4d03001, /* ldrb r3, [r0], #1 */ - 0xe0022003, /* and r2, r2, r3 */ - 0xe2511001, /* subs r1, r1, #1 */ - 0x1afffffb, /* bne loop */ - /* end: */ - 0xe1200070, /* bkpt #0 */ + static const uint8_t check_code_le[] = { +#include "../../contrib/loaders/erase_check/armv4_5_erase_check.inc" }; + assert(sizeof(check_code_le) % 4 == 0); + + if (erased_value != 0xff) { + LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for ARMv4/v5 targets", + erased_value); + return ERROR_FAIL; + } + /* make sure we have a working area */ retval = target_alloc_working_area(target, - sizeof(check_code), &check_algorithm); + sizeof(check_code_le), &check_algorithm); if (retval != ERROR_OK) return retval; /* convert code into a buffer in target endianness */ - for (i = 0; i < ARRAY_SIZE(check_code); i++) { + for (i = 0; i < ARRAY_SIZE(check_code_le) / 4; i++) { retval = target_write_u32(target, check_algorithm->address + i * sizeof(uint32_t), - check_code[i]); + le_to_h_u32(&check_code_le[i * 4])); if (retval != ERROR_OK) - return retval; + goto cleanup; } arm_algo.common_magic = ARM_COMMON_MAGIC; @@ -1558,33 +1578,28 @@ int arm_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) - exit_var = check_algorithm->address + sizeof(check_code) - 4; + exit_var = check_algorithm->address + sizeof(check_code_le) - 4; retval = target_run_algorithm(target, 0, NULL, 3, reg_params, check_algorithm->address, exit_var, 10000, &arm_algo); - if (retval != ERROR_OK) { - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - target_free_working_area(target, check_algorithm); - return retval; - } - *blank = buf_get_u32(reg_params[2].value, 0, 32); + if (retval == ERROR_OK) + *blank = buf_get_u32(reg_params[2].value, 0, 32); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); +cleanup: target_free_working_area(target, check_algorithm); - return ERROR_OK; + return retval; } static int arm_full_context(struct target *target) diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h index 250d95bbd..3ce4ed0e5 100644 --- a/src/target/armv4_5.h +++ b/src/target/armv4_5.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV4_5_H -#define ARMV4_5_H +#ifndef OPENOCD_TARGET_ARMV4_5_H +#define OPENOCD_TARGET_ARMV4_5_H /* This stuff "knows" that its callers aren't talking * to microcontroller profile (current Cortex-M) parts. @@ -48,4 +46,4 @@ extern const int armv4_5_core_reg_map[8][17]; /* offset into armv4_5 core register cache -- OBSOLETE, DO NOT USE! */ enum { ARMV4_5_CPSR = 31, }; -#endif /* ARMV4_5_H */ +#endif /* OPENOCD_TARGET_ARMV4_5_H */ diff --git a/src/target/armv4_5_cache.c b/src/target/armv4_5_cache.c index 66dac3c20..bd0091d80 100644 --- a/src/target/armv4_5_cache.c +++ b/src/target/armv4_5_cache.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/armv4_5_cache.h b/src/target/armv4_5_cache.h index a1777e802..2fd1ca387 100644 --- a/src/target/armv4_5_cache.h +++ b/src/target/armv4_5_cache.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV4_5_CACHE_H -#define ARMV4_5_CACHE_H +#ifndef OPENOCD_TARGET_ARMV4_5_CACHE_H +#define OPENOCD_TARGET_ARMV4_5_CACHE_H struct command_context; @@ -54,4 +52,4 @@ enum { ARMV4_5_CACHE_RR_BIT = 0x5000, }; -#endif /* ARMV4_5_CACHE_H */ +#endif /* OPENOCD_TARGET_ARMV4_5_CACHE_H */ diff --git a/src/target/armv4_5_mmu.c b/src/target/armv4_5_mmu.c index ad9040fb4..115a48950 100644 --- a/src/target/armv4_5_mmu.c +++ b/src/target/armv4_5_mmu.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/armv4_5_mmu.h b/src/target/armv4_5_mmu.h index e2dde7fe7..7beaf4ee9 100644 --- a/src/target/armv4_5_mmu.h +++ b/src/target/armv4_5_mmu.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV4_5_MMU_H -#define ARMV4_5_MMU_H +#ifndef OPENOCD_TARGET_ARMV4_5_MMU_H +#define OPENOCD_TARGET_ARMV4_5_MMU_H #include "armv4_5_cache.h" @@ -27,8 +25,9 @@ struct target; struct armv4_5_mmu_common { int (*get_ttb)(struct target *target, uint32_t *result); - int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); - int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + int (*read_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); + int (*write_memory)(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, const uint8_t *buffer); int (*disable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); int (*enable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); struct armv4_5_cache_common armv4_5_cache; @@ -55,4 +54,4 @@ enum { ARMV4_5_MMU_R_BIT = 0x200 }; -#endif /* ARMV4_5_MMU_H */ +#endif /* OPENOCD_TARGET_ARMV4_5_MMU_H */ diff --git a/src/target/armv7a.c b/src/target/armv7a.c index b9320d143..6021def4e 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -14,9 +14,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -177,7 +175,7 @@ static int armv7a_read_ttbcr(struct target *target) return retval; } -/* method adapted to cortex A : reused arm v4 v5 method*/ +/* method adapted to Cortex-A : reused ARM v4 v5 method */ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) { uint32_t first_lvl_descriptor = 0x0; @@ -681,11 +679,40 @@ int armv7a_identify_cache(struct target *target) } +static int armv7a_setup_semihosting(struct target *target, int enable) +{ + struct armv7a_common *armv7a = target_to_armv7a(target); + uint32_t vcr; + int ret; + + ret = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + &vcr); + if (ret < 0) { + LOG_ERROR("Failed to read VCR register\n"); + return ret; + } + + if (enable) + vcr |= DBG_VCR_SVC_MASK; + else + vcr &= ~DBG_VCR_SVC_MASK; + + ret = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + vcr); + if (ret < 0) + LOG_ERROR("Failed to write VCR register\n"); + + return ret; +} + int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) { struct arm *arm = &armv7a->arm; arm->arch_info = armv7a; target->arch_info = &armv7a->arm; + arm->setup_semihosting = armv7a_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv7a->arm.target = target; armv7a->arm.common_magic = ARM_COMMON_MAGIC; diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 5ca4eb86e..14112e4ed 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV7A_H -#define ARMV7A_H +#ifndef OPENOCD_TARGET_ARMV7A_H +#define OPENOCD_TARGET_ARMV7A_H #include "arm_adi_v5.h" #include "armv7a_cache.h" @@ -50,7 +48,6 @@ struct armv7a_l2x_cache { }; struct armv7a_cachesize { - uint32_t level_num; /* cache dimensionning */ uint32_t linelen; uint32_t associativity; @@ -93,7 +90,7 @@ struct armv7a_mmu_common { uint32_t ttbr_mask[2]; uint32_t ttbr_range[2]; - int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size, + int (*read_physical_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); struct armv7a_cache_common armv7a_cache; uint32_t mmu_enabled; @@ -136,6 +133,12 @@ target_to_armv7a(struct target *target) return container_of(target->arch_info, struct armv7a_common, arm); } +static inline bool is_armv7a(struct armv7a_common *armv7a) +{ + return armv7a->common_magic == ARMV7_COMMON_MAGIC; +} + + /* register offsets from armv7a.debug_base */ /* See ARMv7a arch spec section C10.2 */ @@ -174,6 +177,13 @@ target_to_armv7a(struct target *target) /* See ARMv7a arch spec section C10.8 */ #define CPUDBG_AUTHSTATUS 0xFB8 +/* Masks for Vector Catch register */ +#define DBG_VCR_FIQ_MASK ((1 << 31) | (1 << 7)) +#define DBG_VCR_IRQ_MASK ((1 << 30) | (1 << 6)) +#define DBG_VCR_DATA_ABORT_MASK ((1 << 28) | (1 << 4)) +#define DBG_VCR_PREF_ABORT_MASK ((1 << 27) | (1 << 3)) +#define DBG_VCR_SVC_MASK ((1 << 26) | (1 << 2)) + int armv7a_arch_state(struct target *target); int armv7a_identify_cache(struct target *target); int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a); @@ -186,4 +196,4 @@ int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, extern const struct command_registration armv7a_command_handlers[]; -#endif /* ARMV4_5_H */ +#endif /* OPENOCD_TARGET_ARMV7A_H */ diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 9237e73fe..7af3e6d4e 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/armv7a_cache.h b/src/target/armv7a_cache.h index e0ebb618b..e0f7eb3a5 100644 --- a/src/target/armv7a_cache.h +++ b/src/target/armv7a_cache.h @@ -11,10 +11,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM7A_CACHE_H -#define ARM7A_CACHE_H +#ifndef OPENOCD_TARGET_ARM7A_CACHE_H +#define OPENOCD_TARGET_ARM7A_CACHE_H #include "arm_jtag.h" #include "armv7a_cache_l2x.h" @@ -40,4 +43,4 @@ extern const struct command_registration arm7a_cache_command_handlers[]; #define CACHE_LEVEL_HAS_D_CACHE 0x2 #define CACHE_LEVEL_HAS_I_CACHE 0x1 -#endif +#endif /* OPENOCD_TARGET_ARM7A_CACHE_H */ diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c index 8b35fd89b..e181f268d 100644 --- a/src/target/armv7a_cache_l2x.c +++ b/src/target/armv7a_cache_l2x.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -60,12 +63,12 @@ int arm7a_l2x_flush_all_data(struct target *target) l2_way_val = (1 << l2x_cache->way) - 1; - return target_write_phys_memory(target, + return target_write_phys_u32(target, l2x_cache->base + L2X0_CLEAN_INV_WAY, - 4, 1, (uint8_t *)&l2_way_val); + l2_way_val); } -int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, +int armv7a_l2x_cache_flush_virt(struct target *target, target_addr_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -80,16 +83,15 @@ int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_CLEAN_INV_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_CLEAN_INV_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -101,7 +103,7 @@ int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, return retval; } -static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt, +static int armv7a_l2x_cache_inval_virt(struct target *target, target_addr_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -116,16 +118,15 @@ static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_INV_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_INV_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -137,7 +138,7 @@ static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt, return retval; } -static int armv7a_l2x_cache_clean_virt(struct target *target, uint32_t virt, +static int armv7a_l2x_cache_clean_virt(struct target *target, target_addr_t virt, unsigned int size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -152,16 +153,15 @@ static int armv7a_l2x_cache_clean_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_CLEAN_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_CLEAN_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -249,7 +249,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_all_command) COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -259,7 +260,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_flush_virt(target, virt, size); } @@ -267,7 +268,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -277,7 +279,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_inval_virt(target, virt, size); } @@ -285,7 +287,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) COMMAND_HANDLER(arm7a_l2x_cache_clean_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -295,7 +298,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_clean_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_clean_virt(target, virt, size); } diff --git a/src/target/armv7a_cache_l2x.h b/src/target/armv7a_cache_l2x.h index 99fbe8aa6..f98b55446 100644 --- a/src/target/armv7a_cache_l2x.h +++ b/src/target/armv7a_cache_l2x.h @@ -11,10 +11,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARM7A_CACHE_L2X_H -#define ARM7A_CACHE_L2X_H +#ifndef OPENOCD_TARGET_ARM7A_CACHE_L2X_H +#define OPENOCD_TARGET_ARM7A_CACHE_L2X_H #define L2X0_CACHE_LINE_SIZE 32 @@ -148,8 +151,8 @@ struct l2c_init_data { extern const struct command_registration arm7a_l2x_cache_command_handler[]; -int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, +int armv7a_l2x_cache_flush_virt(struct target *target, target_addr_t virt, uint32_t size); int arm7a_l2x_flush_all_data(struct target *target); -#endif +#endif /* OPENOCD_TARGET_ARM7A_CACHE_L2X_H */ diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 15de8cd9c..e0911c30f 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * * * * ARMv7-M Architecture, Application Level Reference Manual * * ARM DDI 0405C (September 2008) * @@ -320,7 +318,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int armv7m_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info) { int retval; @@ -345,7 +343,7 @@ int armv7m_run_algorithm(struct target *target, int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -433,7 +431,7 @@ int armv7m_start_algorithm(struct target *target, int armv7m_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -463,7 +461,7 @@ int armv7m_wait_algorithm(struct target *target, armv7m->load_core_reg_u32(target, 15, &pc); if (exit_point && (pc != exit_point)) { - LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32, + LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, pc, exit_point); return ERROR_TARGET_TIMEOUT; @@ -538,11 +536,15 @@ int armv7m_arch_state(struct target *target) struct arm *arm = &armv7m->arm; uint32_t ctrl, sp; + /* avoid filling log waiting for fileio reply */ + if (arm->semihosting_hit_fileio) + return ERROR_OK; + ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32); LOG_USER("target halted due to %s, current mode: %s %s\n" - "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s", + "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s%s", debug_reason_name(target), arm_mode_name(arm->core_mode), armv7m_exception_string(armv7m->exception_number), @@ -550,7 +552,8 @@ int armv7m_arch_state(struct target *target) buf_get_u32(arm->pc->value, 0, 32), (ctrl & 0x02) ? 'p' : 'm', sp, - arm->is_semihosting ? ", semihosting" : ""); + arm->is_semihosting ? ", semihosting" : "", + arm->is_semihosting_fileio ? " fileio" : ""); return ERROR_OK; } @@ -679,47 +682,15 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) /** Generates a CRC32 checksum of a memory region. */ int armv7m_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct armv7m_algorithm armv7m_info; struct reg_param reg_params[2]; int retval; - /* see contrib/loaders/checksum/armv7m_crc.s for src */ - static const uint8_t cortex_m_crc_code[] = { - /* main: */ - 0x02, 0x46, /* mov r2, r0 */ - 0x00, 0x20, /* movs r0, #0 */ - 0xC0, 0x43, /* mvns r0, r0 */ - 0x0A, 0x4E, /* ldr r6, CRC32XOR */ - 0x0B, 0x46, /* mov r3, r1 */ - 0x00, 0x24, /* movs r4, #0 */ - 0x0D, 0xE0, /* b ncomp */ - /* nbyte: */ - 0x11, 0x5D, /* ldrb r1, [r2, r4] */ - 0x09, 0x06, /* lsls r1, r1, #24 */ - 0x48, 0x40, /* eors r0, r0, r1 */ - 0x00, 0x25, /* movs r5, #0 */ - /* loop: */ - 0x00, 0x28, /* cmp r0, #0 */ - 0x02, 0xDA, /* bge notset */ - 0x40, 0x00, /* lsls r0, r0, #1 */ - 0x70, 0x40, /* eors r0, r0, r6 */ - 0x00, 0xE0, /* b cont */ - /* notset: */ - 0x40, 0x00, /* lsls r0, r0, #1 */ - /* cont: */ - 0x01, 0x35, /* adds r5, r5, #1 */ - 0x08, 0x2D, /* cmp r5, #8 */ - 0xF6, 0xD1, /* bne loop */ - 0x01, 0x34, /* adds r4, r4, #1 */ - /* ncomp: */ - 0x9C, 0x42, /* cmp r4, r3 */ - 0xEF, 0xD1, /* bne nbyte */ - 0x00, 0xBE, /* bkpt #0 */ - 0xB7, 0x1D, 0xC1, 0x04 /* CRC32XOR: .word 0x04c11db7 */ +#include "../../contrib/loaders/checksum/armv7m_crc.inc" }; retval = target_alloc_working_area(target, sizeof(cortex_m_crc_code), &crc_algorithm); @@ -760,36 +731,44 @@ int armv7m_checksum_memory(struct target *target, return retval; } -/** Checks whether a memory region is zeroed. */ +/** Checks whether a memory region is erased. */ int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; + const uint8_t *code; + uint32_t code_size; int retval; - /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */ - static const uint8_t erase_check_code[] = { - /* loop: */ - 0x03, 0x78, /* ldrb r3, [r0] */ - 0x01, 0x30, /* adds r0, #1 */ - 0x1A, 0x40, /* ands r2, r2, r3 */ - 0x01, 0x39, /* subs r1, r1, #1 */ - 0xFA, 0xD1, /* bne loop */ - 0x00, 0xBE /* bkpt #0 */ +#include "../../contrib/loaders/erase_check/armv7m_erase_check.inc" + }; + static const uint8_t zero_erase_check_code[] = { +#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc" }; + switch (erased_value) { + case 0x00: + code = zero_erase_check_code; + code_size = sizeof(zero_erase_check_code); + break; + case 0xff: + default: + code = erase_check_code; + code_size = sizeof(erase_check_code); + } + /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), + if (target_alloc_working_area(target, code_size, &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; retval = target_write_buffer(target, erase_check_algorithm->address, - sizeof(erase_check_code), (uint8_t *)erase_check_code); + code_size, code); if (retval != ERROR_OK) - return retval; + goto cleanup; armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; @@ -801,7 +780,7 @@ int armv7m_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); retval = target_run_algorithm(target, 0, @@ -809,7 +788,7 @@ int armv7m_blank_check_memory(struct target *target, 3, reg_params, erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 2), + erase_check_algorithm->address + (code_size - 2), 10000, &armv7m_info); @@ -820,6 +799,7 @@ int armv7m_blank_check_memory(struct target *target, destroy_reg_param(®_params[1]); destroy_reg_param(®_params[2]); +cleanup: target_free_working_area(target, erase_check_algorithm); return retval; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 65a2ef059..284bb9caa 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV7M_COMMON_H -#define ARMV7M_COMMON_H +#ifndef OPENOCD_TARGET_ARMV7M_H +#define OPENOCD_TARGET_ARMV7M_H #include "arm_adi_v5.h" #include "arm.h" @@ -134,6 +132,8 @@ enum { enum { FP_NONE = 0, FPv4_SP, + FPv5_SP, + FPv5_DP, }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) @@ -203,19 +203,19 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m); int armv7m_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info); int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info); int armv7m_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info); int armv7m_invalidate_core_regs(struct target *target); @@ -223,12 +223,12 @@ int armv7m_invalidate_core_regs(struct target *target); int armv7m_restore_context(struct target *target); int armv7m_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum); + target_addr_t address, uint32_t count, uint32_t *checksum); int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found); extern const struct command_registration armv7m_command_handlers[]; -#endif /* ARMV7M_H */ +#endif /* OPENOCD_TARGET_ARMV7M_H */ diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c index 3592bad0f..c1e4f5baa 100644 --- a/src/target/armv7m_trace.c +++ b/src/target/armv7m_trace.c @@ -10,6 +10,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h index eae72f557..4f9939464 100644 --- a/src/target/armv7m_trace.h +++ b/src/target/armv7m_trace.h @@ -10,10 +10,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ARMV7M_TRACE_H -#define ARMV7M_TRACE_H +#ifndef OPENOCD_TARGET_ARMV7M_TRACE_H +#define OPENOCD_TARGET_ARMV7M_TRACE_H #include #include @@ -85,4 +88,4 @@ int armv7m_trace_tpiu_config(struct target *target); */ int armv7m_trace_itm_config(struct target *target); -#endif +#endif /* OPENOCD_TARGET_ARMV7M_TRACE_H */ diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index 55d1efb4c..f8da8d5ac 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -314,7 +312,7 @@ static int avr32_ap7k_deassert_reset(struct target *target) } static int avr32_ap7k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; @@ -350,7 +348,7 @@ static int avr32_ap7k_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address); #if 0 avr32_ap7k_unset_breakpoint(target, breakpoint); avr32_ap7k_single_step_core(target); @@ -396,7 +394,7 @@ static int avr32_ap7k_resume(struct target *target, int current, } static int avr32_ap7k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_ERROR("%s: implement me", __func__); @@ -433,12 +431,12 @@ static int avr32_ap7k_remove_watchpoint(struct target *target, return ERROR_OK; } -static int avr32_ap7k_read_memory(struct target *target, uint32_t address, +static int avr32_ap7k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); @@ -474,12 +472,12 @@ static int avr32_ap7k_read_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int avr32_ap7k_write_memory(struct target *target, uint32_t address, +static int avr32_ap7k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); diff --git a/src/target/avr32_ap7k.h b/src/target/avr32_ap7k.h index 1f952eb86..3f27534a3 100644 --- a/src/target/avr32_ap7k.h +++ b/src/target/avr32_ap7k.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef AVR32_AP7K -#define AVR32_AP7K +#ifndef OPENOCD_TARGET_AVR32_AP7K_H +#define OPENOCD_TARGET_AVR32_AP7K_H struct target; @@ -42,4 +40,4 @@ struct avr32_core_reg { struct avr32_ap7k_common *avr32_common; }; -#endif /*AVR32_AP7K*/ +#endif /* OPENOCD_TARGET_AVR32_AP7K_H */ diff --git a/src/target/avr32_jtag.c b/src/target/avr32_jtag.c index 647afd5e4..6526810e2 100644 --- a/src/target/avr32_jtag.c +++ b/src/target/avr32_jtag.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/avr32_jtag.h b/src/target/avr32_jtag.h index b5fdeafa7..b431ef4c8 100644 --- a/src/target/avr32_jtag.h +++ b/src/target/avr32_jtag.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef AVR32_JTAG -#define AVR32_JTAG +#ifndef OPENOCD_TARGET_AVR32_JTAG_H +#define OPENOCD_TARGET_AVR32_JTAG_H #define AVR32NUMCOREREGS 17 @@ -102,4 +100,4 @@ int avr32_ocd_clearbits(struct avr32_jtag *jtag, int reg, uint32_t bits); int avr32_jtag_exec(struct avr32_jtag *jtag_info, uint32_t inst); -#endif /* AVR32_JTAG */ +#endif /* OPENOCD_TARGET_AVR32_JTAG_H */ diff --git a/src/target/avr32_mem.c b/src/target/avr32_mem.c index a7797a292..71ec0b431 100644 --- a/src/target/avr32_mem.c +++ b/src/target/avr32_mem.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/avr32_mem.h b/src/target/avr32_mem.h index 4c36bdb31..f60a12179 100644 --- a/src/target/avr32_mem.h +++ b/src/target/avr32_mem.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef AVR32_MEM -#define AVR32_MEM +#ifndef OPENOCD_TARGET_AVR32_MEM_H +#define OPENOCD_TARGET_AVR32_MEM_H int avr32_jtag_read_memory32(struct avr32_jtag *jtag_info, uint32_t addr, int count, uint32_t *buffer); @@ -34,4 +32,4 @@ int avr32_jtag_write_memory16(struct avr32_jtag *jtag_info, int avr32_jtag_write_memory8(struct avr32_jtag *jtag_info, uint32_t addr, int count, const uint8_t *buffer); -#endif /* AVR32_MEM */ +#endif /* OPENOCD_TARGET_AVR32_MEM_H */ diff --git a/src/target/avr32_regs.c b/src/target/avr32_regs.c index 901f4fed7..7273822c2 100644 --- a/src/target/avr32_regs.c +++ b/src/target/avr32_regs.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/avr32_regs.h b/src/target/avr32_regs.h index 6590dec9c..cb492a9fe 100644 --- a/src/target/avr32_regs.h +++ b/src/target/avr32_regs.h @@ -12,13 +12,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef AVR32_REGS -#define AVR32_REGS +#ifndef OPENOCD_TARGET_AVR32_REGS_H +#define OPENOCD_TARGET_AVR32_REGS_H enum avr32_reg_nums { AVR32_REG_R0 = 0, @@ -43,4 +41,4 @@ enum avr32_reg_nums { int avr32_jtag_read_regs(struct avr32_jtag *jtag_info, uint32_t *regs); int avr32_jtag_write_regs(struct avr32_jtag *jtag_info, uint32_t *regs); -#endif /* AVR32_REGS */ +#endif /* OPENOCD_TARGET_AVR32_REGS_H */ diff --git a/src/target/avrt.c b/src/target/avrt.c index a4ce46b78..1e1898c7e 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -35,9 +33,9 @@ static int avr_init_target(struct command_context *cmd_ctx, struct target *targe static int avr_arch_state(struct target *target); static int avr_poll(struct target *target); static int avr_halt(struct target *target); -static int avr_resume(struct target *target, int current, uint32_t address, +static int avr_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); -static int avr_step(struct target *target, int current, uint32_t address, +static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); static int avr_assert_reset(struct target *target); @@ -118,14 +116,14 @@ static int avr_halt(struct target *target) return ERROR_OK; } -static int avr_resume(struct target *target, int current, uint32_t address, +static int avr_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints) +static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/avrt.h b/src/target/avrt.h index 707b48160..3610eb5e3 100644 --- a/src/target/avrt.h +++ b/src/target/avrt.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef AVRT_H -#define AVRT_H +#ifndef OPENOCD_TARGET_AVRT_H +#define OPENOCD_TARGET_AVRT_H #include @@ -36,4 +34,4 @@ int avr_jtag_sendinstr(struct jtag_tap *tap, uint8_t *ir_in, uint8_t ir_out); int avr_jtag_senddat(struct jtag_tap *tap, uint32_t *dr_in, uint32_t dr_out, int len); -#endif /* AVRT_H */ +#endif /* OPENOCD_TARGET_AVRT_H */ diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index b854f1f05..7cf4a6957 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -44,7 +42,7 @@ static const char * const watchpoint_rw_strings[] = { static int bpwp_unique_id; int breakpoint_add_internal(struct target *target, - uint32_t address, + target_addr_t address, uint32_t length, enum breakpoint_type type) { @@ -62,7 +60,7 @@ int breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_DEBUG("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return ERROR_OK; } @@ -100,7 +98,7 @@ int breakpoint_add_internal(struct target *target, return retval; } - LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", + LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -161,7 +159,7 @@ int context_breakpoint_add_internal(struct target *target, } int hybrid_breakpoint_add_internal(struct target *target, - uint32_t address, + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) @@ -182,7 +180,7 @@ int hybrid_breakpoint_add_internal(struct target *target, asid, breakpoint->unique_id); return -1; } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) { - LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_DEBUG("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return -1; @@ -210,7 +208,7 @@ int hybrid_breakpoint_add_internal(struct target *target, return retval; } LOG_DEBUG( - "added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", + "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, @@ -220,7 +218,7 @@ int hybrid_breakpoint_add_internal(struct target *target, } int breakpoint_add(struct target *target, - uint32_t address, + target_addr_t address, uint32_t length, enum breakpoint_type type) { @@ -265,7 +263,7 @@ int context_breakpoint_add(struct target *target, return context_breakpoint_add_internal(target, asid, length, type); } int hybrid_breakpoint_add(struct target *target, - uint32_t address, + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) @@ -312,7 +310,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint free(breakpoint); } -int breakpoint_remove_internal(struct target *target, uint32_t address) +int breakpoint_remove_internal(struct target *target, target_addr_t address) { struct breakpoint *breakpoint = target->breakpoints; @@ -331,11 +329,11 @@ int breakpoint_remove_internal(struct target *target, uint32_t address) return 1; } else { if (!target->smp) - LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); return 0; } } -void breakpoint_remove(struct target *target, uint32_t address) +void breakpoint_remove(struct target *target, target_addr_t address) { int found = 0; if (target->smp) { @@ -348,7 +346,7 @@ void breakpoint_remove(struct target *target, uint32_t address) head = head->next; } if (found == 0) - LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); } else breakpoint_remove_internal(target, address); } @@ -377,7 +375,7 @@ void breakpoint_clear_target(struct target *target) } -struct breakpoint *breakpoint_find(struct target *target, uint32_t address) +struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) { struct breakpoint *breakpoint = target->breakpoints; @@ -390,7 +388,7 @@ struct breakpoint *breakpoint_find(struct target *target, uint32_t address) return NULL; } -int watchpoint_add(struct target *target, uint32_t address, uint32_t length, +int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; @@ -404,8 +402,8 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, || watchpoint->value != value || watchpoint->mask != mask || watchpoint->rw != rw) { - LOG_ERROR("address 0x%8.8" PRIx32 - "already has watchpoint %d", + LOG_ERROR("address " TARGET_ADDR_FMT + " already has watchpoint %d", address, watchpoint->unique_id); return ERROR_FAIL; } @@ -438,7 +436,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, default: reason = "unrecognized error"; bye: - LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s", + LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT ", %s", watchpoint_rw_strings[(*watchpoint_p)->rw], address, reason); free(*watchpoint_p); @@ -446,7 +444,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, return retval; } - LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 + LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT " of length 0x%8.8" PRIx32 " (WPID: %d)", watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, @@ -477,7 +475,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint free(watchpoint); } -void watchpoint_remove(struct target *target, uint32_t address) +void watchpoint_remove(struct target *target, target_addr_t address) { struct watchpoint *watchpoint = target->watchpoints; @@ -490,7 +488,7 @@ void watchpoint_remove(struct target *target, uint32_t address) if (watchpoint) watchpoint_free(target, watchpoint); else - LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); } void watchpoint_clear_target(struct target *target) @@ -501,7 +499,8 @@ void watchpoint_clear_target(struct target *target) watchpoint_free(target, target->watchpoints); } -int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address) +int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, + target_addr_t *address) { int retval; struct watchpoint *hit_watchpoint; @@ -513,7 +512,7 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *addr *rw = hit_watchpoint->rw; *address = hit_watchpoint->address; - LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)", + LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT " (WPID: %d)", hit_watchpoint->address, hit_watchpoint->unique_id); diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 0246acd3d..51bd05abd 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -13,13 +13,13 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef BREAKPOINTS_H -#define BREAKPOINTS_H +#ifndef OPENOCD_TARGET_BREAKPOINTS_H +#define OPENOCD_TARGET_BREAKPOINTS_H + +#include struct target; @@ -33,7 +33,7 @@ enum watchpoint_rw { }; struct breakpoint { - uint32_t address; + target_addr_t address; uint32_t asid; int length; enum breakpoint_type type; @@ -45,7 +45,7 @@ struct breakpoint { }; struct watchpoint { - uint32_t address; + target_addr_t address; uint32_t length; uint32_t mask; uint32_t value; @@ -57,22 +57,23 @@ struct watchpoint { void breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, - uint32_t address, uint32_t length, enum breakpoint_type type); + target_addr_t address, uint32_t length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, - uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); -void breakpoint_remove(struct target *target, uint32_t address); + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); +void breakpoint_remove(struct target *target, target_addr_t address); -struct breakpoint *breakpoint_find(struct target *target, uint32_t address); +struct breakpoint *breakpoint_find(struct target *target, target_addr_t address); void watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, - uint32_t address, uint32_t length, + target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask); -void watchpoint_remove(struct target *target, uint32_t address); +void watchpoint_remove(struct target *target, target_addr_t address); /* report type and address of just hit watchpoint */ -int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address); +int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, + target_addr_t *address); -#endif /* BREAKPOINTS_H */ +#endif /* OPENOCD_TARGET_BREAKPOINTS_H */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 8a0d38bca..5d90e3416 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -18,7 +18,7 @@ * michel.jaouen@stericsson.com : smp minimum support * * * * Copyright (C) Broadcom 2012 * - * ehunter@broadcom.com : Cortex R4 support * + * ehunter@broadcom.com : Cortex-R4 support * * * * Copyright (C) 2013 Kamal Dasu * * kdasu.kdev@gmail.com * @@ -34,9 +34,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * * * * Cortex-A8(tm) TRM, ARM DDI 0344H * * Cortex-A9(tm) TRM, ARM DDI 0407F * @@ -55,6 +53,8 @@ #include "target_request.h" #include "target_type.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" +#include "jtag/swd.h" #include static int cortex_a_poll(struct target *target); @@ -75,8 +75,8 @@ static int cortex_a_dap_write_coreregister_u32(struct target *target, static int cortex_a_mmu(struct target *target, int *enabled); static int cortex_a_mmu_modify(struct target *target, int enable); static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys); -static int cortex_a_read_apb_ab_memory(struct target *target, + target_addr_t virt, target_addr_t *phys); +static int cortex_a_read_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); @@ -196,32 +196,6 @@ static int cortex_a_mmu_modify(struct target *target, int enable) return retval; } -/* - * Cortex-A Basic debug access, very low level assumes state is saved - */ -static int cortex_a8_init_debug_access(struct target *target) -{ - struct armv7a_common *armv7a = target_to_armv7a(target); - int retval; - - LOG_DEBUG(" "); - - /* Unlocking the debug registers for modification - * The debugport might be uninitialised so try twice */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval != ERROR_OK) { - /* try again */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval == ERROR_OK) - LOG_USER( - "Locking debug access failed on first, but succeeded on second try."); - } - - return retval; -} - /* * Cortex-A Basic debug access, very low level assumes state is saved */ @@ -229,47 +203,11 @@ static int cortex_a_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); int retval; - uint32_t dbg_osreg; - uint32_t cortex_part_num; - struct cortex_a_common *cortex_a = target_to_cortex_a(target); - - LOG_DEBUG(" "); - cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> - CORTEX_A_MIDR_PARTNUM_SHIFT; - - switch (cortex_part_num) { - case CORTEX_A7_PARTNUM: - case CORTEX_A15_PARTNUM: - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLSR, - &dbg_osreg); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg); - - if (dbg_osreg & CPUDBG_OSLAR_LK_MASK) - /* Unlocking the DEBUG OS registers for modification */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - break; - - case CORTEX_A5_PARTNUM: - case CORTEX_A8_PARTNUM: - case CORTEX_A9_PARTNUM: - default: - retval = cortex_a8_init_debug_access(target); - } - - if (retval != ERROR_OK) - return retval; - /* Clear Sticky Power Down status Bit in PRSR to enable access to - the registers in the Core Power Domain */ - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* lock memory-mapped access to debug registers to prevent + * software interference */ + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_LOCKACCESS, 0); if (retval != ERROR_OK) return retval; @@ -299,7 +237,7 @@ static int cortex_a_wait_instrcmpl(struct target *target, uint32_t *dscr, bool f * Writes final value of DSCR into *dscr. Pass force to force always * reading DSCR at least once. */ struct armv7a_common *armv7a = target_to_armv7a(target); - long long then = timeval_ms(); + int64_t then = timeval_ms(); while ((*dscr & DSCR_INSTR_COMP) == 0 || force) { force = false; int retval = mem_ap_read_atomic_u32(armv7a->debug_ap, @@ -342,7 +280,7 @@ static int cortex_a_exec_opcode(struct target *target, if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); do { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); @@ -431,7 +369,7 @@ static int cortex_a_dap_read_coreregister_u32(struct target *target, } /* Wait for DTRRXfull then read DTRRTX */ - long long then = timeval_ms(); + int64_t then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); @@ -574,7 +512,7 @@ static int cortex_a_read_dcc(struct cortex_a_common *a, uint32_t *data, dscr = *dscr_p; /* Wait for DTRRXfull */ - long long then = timeval_ms(); + int64_t then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, @@ -606,7 +544,7 @@ static int cortex_a_dpm_prepare(struct arm_dpm *dpm) int retval; /* set up invariant: INSTR_COMP is set after ever DPM operation */ - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(a->armv7a_common.debug_ap, a->armv7a_common.debug_base + CPUDBG_DSCR, @@ -854,7 +792,8 @@ static int cortex_a_halt_smp(struct target *target) head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_HALTED)) + if ((curr != target) && (curr->state != TARGET_HALTED) + && target_was_examined(curr)) retval += cortex_a_halt(curr); head = head->next; } @@ -917,6 +856,10 @@ static int cortex_a_poll(struct target *target) if (retval != ERROR_OK) return retval; } + + if (arm_semihosting(target, &retval) != 0) + return retval; + target_call_event_callbacks(target, TARGET_EVENT_HALTED); } @@ -936,12 +879,8 @@ static int cortex_a_poll(struct target *target) TARGET_EVENT_DEBUG_HALTED); } } - } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) + } else target->state = TARGET_RUNNING; - else { - LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); - target->state = TARGET_UNKNOWN; - } return retval; } @@ -974,7 +913,7 @@ static int cortex_a_halt(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); @@ -994,7 +933,7 @@ static int cortex_a_halt(struct target *target) } static int cortex_a_internal_restore(struct target *target, int current, - uint32_t *address, int handle_breakpoints, int debug_execution) + target_addr_t *address, int handle_breakpoints, int debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; @@ -1049,6 +988,9 @@ static int cortex_a_internal_restore(struct target *target, int current, case ARM_STATE_JAZELLE: LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; + case ARM_STATE_AARCH64: + LOG_ERROR("Shoudn't be in AARCH64 state"); + return ERROR_FAIL; } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(arm->pc->value, 0, 32, resume_pc); @@ -1121,7 +1063,7 @@ static int cortex_a_internal_restart(struct target *target) if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); @@ -1149,11 +1091,12 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) int retval = 0; struct target_list *head; struct target *curr; - uint32_t address; + target_addr_t address; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_RUNNING)) { + if ((curr != target) && (curr->state != TARGET_RUNNING) + && target_was_examined(curr)) { /* resume current address , not in step mode */ retval += cortex_a_internal_restore(curr, 1, &address, handle_breakpoints, 0); @@ -1166,7 +1109,7 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) } static int cortex_a_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ @@ -1190,11 +1133,11 @@ static int cortex_a_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIx32, address); + LOG_DEBUG("target resumed at " TARGET_ADDR_FMT, address); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIx32, address); + LOG_DEBUG("target debug resumed at " TARGET_ADDR_FMT, address); } return ERROR_OK; @@ -1203,7 +1146,7 @@ static int cortex_a_resume(struct target *target, int current, static int cortex_a_debug_entry(struct target *target) { int i; - uint32_t regfile[16], cpsr, dscr; + uint32_t regfile[16], cpsr, spsr, dscr; int retval = ERROR_OK; struct working_area *regfile_working_area = NULL; struct cortex_a_common *cortex_a = target_to_cortex_a(target); @@ -1252,6 +1195,7 @@ static int cortex_a_debug_entry(struct target *target) if (cortex_a->fast_reg_read) target_alloc_working_area(target, 64, ®file_working_area); + /* First load register acessible through core debug port*/ if (!regfile_working_area) retval = arm_dpm_read_current_registers(&armv7a->dpm); @@ -1296,6 +1240,19 @@ static int cortex_a_debug_entry(struct target *target) reg->dirty = reg->valid; } + if (arm->spsr) { + /* read Saved PSR */ + retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); + /* store current spsr */ + if (retval != ERROR_OK) + return retval; + + reg = arm->spsr; + buf_set_u32(reg->value, 0, 32, spsr); + reg->valid = 1; + reg->dirty = 0; + } + #if 0 /* TODO, Move this */ uint32_t cp15_control_register, cp15_cacr, cp15_nacr; @@ -1386,7 +1343,7 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign return retval; } -static int cortex_a_step(struct target *target, int current, uint32_t address, +static int cortex_a_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); @@ -1443,7 +1400,7 @@ static int cortex_a_step(struct target *target, int current, uint32_t address, if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); + int64_t then = timeval_ms(); while (target->state != TARGET_HALTED) { retval = cortex_a_poll(target); if (retval != ERROR_OK) @@ -1903,6 +1860,8 @@ static int cortex_a_assert_reset(struct target *target) /* FIXME when halt is requested, make it work somehow... */ + /* This function can be called in "target not examined" state */ + /* Issue some kind of warm reset. */ if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) target_handle_event(target, TARGET_EVENT_RESET_ASSERT); @@ -1910,14 +1869,23 @@ static int cortex_a_assert_reset(struct target *target) /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ - jtag_add_reset(0, 1); + + /* + * FIXME: fix reset when transport is SWD. This is a temporary + * work-around for release v0.10 that is not intended to stay! + */ + if (transport_is_swd() || + (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING))) + jtag_add_reset(0, 1); + } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; } /* registers are now invalid */ - register_cache_invalidate(armv7a->arm.core_cache); + if (target_was_examined(target)) + register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; @@ -1933,17 +1901,22 @@ static int cortex_a_deassert_reset(struct target *target) /* be certain SRST is off */ jtag_add_reset(0, 0); - retval = cortex_a_poll(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; + } if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); - retval = target_halt(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + } else + target->state = TARGET_UNKNOWN; } } @@ -1977,7 +1950,7 @@ static int cortex_a_wait_dscr_bits(struct target *target, uint32_t mask, { /* Waits until the specified bit(s) of DSCR take on a specified value. */ struct armv7a_common *armv7a = target_to_armv7a(target); - long long then = timeval_ms(); + int64_t then = timeval_ms(); int retval; while ((*dscr & mask) != value) { @@ -2123,13 +2096,13 @@ static int cortex_a_dfsr_to_error_code(uint32_t dfsr) } } -static int cortex_a_write_apb_ab_memory_slow(struct target *target, +static int cortex_a_write_cpu_memory_slow(struct target *target, uint32_t size, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size size from *buffer. Old value of DSCR must * be in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and - * the address is aligned, cortex_a_write_apb_ab_memory_fast should be + * the address is aligned, cortex_a_write_cpu_memory_fast should be * preferred. * Preconditions: * - Address is in R0. @@ -2198,7 +2171,7 @@ static int cortex_a_write_apb_ab_memory_slow(struct target *target, return ERROR_OK; } -static int cortex_a_write_apb_ab_memory_fast(struct target *target, +static int cortex_a_write_cpu_memory_fast(struct target *target, uint32_t count, const uint8_t *buffer, uint32_t *dscr) { /* Writes count objects of size 4 from *buffer. Old value of DSCR must be @@ -2227,17 +2200,17 @@ static int cortex_a_write_apb_ab_memory_fast(struct target *target, 4, count, armv7a->debug_base + CPUDBG_DTRRX); } -static int cortex_a_write_apb_ab_memory(struct target *target, +static int cortex_a_write_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - /* Write memory through APB-AP. */ + /* Write memory through the CPU. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, + LOG_DEBUG("Writing CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2283,10 +2256,10 @@ static int cortex_a_write_apb_ab_memory(struct target *target, if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ - retval = cortex_a_write_apb_ab_memory_fast(target, count, buffer, &dscr); + retval = cortex_a_write_cpu_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ - retval = cortex_a_write_apb_ab_memory_slow(target, size, count, buffer, &dscr); + retval = cortex_a_write_cpu_memory_slow(target, size, count, buffer, &dscr); } out: @@ -2305,7 +2278,7 @@ static int cortex_a_write_apb_ab_memory(struct target *target, /* Wait until DTRRX is empty (according to ARMv7-A/-R architecture manual * section C8.4.3, checking InstrCmpl_l is not sufficient; one must also * check RXfull_l). Most of the time this will be free because RXfull_l - * will be cleared immediately and cached in dscr. However, don’t do this + * will be cleared immediately and cached in dscr. However, don't do this * if there is fault, because then the instruction might not have completed * successfully. */ if (!(dscr & DSCR_STICKY_ABORT_PRECISE)) { @@ -2366,13 +2339,13 @@ static int cortex_a_write_apb_ab_memory(struct target *target, return final_retval; } -static int cortex_a_read_apb_ab_memory_slow(struct target *target, +static int cortex_a_read_cpu_memory_slow(struct target *target, uint32_t size, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size size into *buffer. Old value of DSCR must be * in *dscr; updated to new value. This is slow because it works for * non-word-sized objects and (maybe) unaligned accesses. If size == 4 and - * the address is aligned, cortex_a_read_apb_ab_memory_fast should be + * the address is aligned, cortex_a_read_cpu_memory_fast should be * preferred. * Preconditions: * - Address is in R0. @@ -2442,7 +2415,7 @@ static int cortex_a_read_apb_ab_memory_slow(struct target *target, return ERROR_OK; } -static int cortex_a_read_apb_ab_memory_fast(struct target *target, +static int cortex_a_read_cpu_memory_fast(struct target *target, uint32_t count, uint8_t *buffer, uint32_t *dscr) { /* Reads count objects of size 4 into *buffer. Old value of DSCR must be in @@ -2529,17 +2502,17 @@ static int cortex_a_read_apb_ab_memory_fast(struct target *target, return ERROR_OK; } -static int cortex_a_read_apb_ab_memory(struct target *target, +static int cortex_a_read_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - /* Read memory through APB-AP. */ + /* Read memory through the CPU. */ int retval, final_retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; uint32_t dscr, orig_dfar, orig_dfsr, fault_dscr, fault_dfar, fault_dfsr; - LOG_DEBUG("Reading APB-AP memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, + LOG_DEBUG("Reading CPU memory address 0x%" PRIx32 " size %" PRIu32 " count %" PRIu32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -2585,10 +2558,10 @@ static int cortex_a_read_apb_ab_memory(struct target *target, if (size == 4 && (address % 4) == 0) { /* We are doing a word-aligned transfer, so use fast mode. */ - retval = cortex_a_read_apb_ab_memory_fast(target, count, buffer, &dscr); + retval = cortex_a_read_cpu_memory_fast(target, count, buffer, &dscr); } else { /* Use slow path. */ - retval = cortex_a_read_apb_ab_memory_slow(target, size, count, buffer, &dscr); + retval = cortex_a_read_cpu_memory_slow(target, size, count, buffer, &dscr); } out: @@ -2660,49 +2633,57 @@ static int cortex_a_read_apb_ab_memory(struct target *target, /* * Cortex-A Memory access * - * This is same Cortex M3 but we must also use the correct + * This is same Cortex-M3 but we must also use the correct * ap number for every access. */ static int cortex_a_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - int retval = ERROR_COMMAND_SYNTAX_ERROR; + struct armv7a_common *armv7a = target_to_armv7a(target); + struct adiv5_dap *swjdp = armv7a->arm.dap; + uint8_t apsel = swjdp->apsel; + int retval; - LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, + if (!count || !buffer) + return ERROR_COMMAND_SYNTAX_ERROR; + + LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); - if (count && buffer) { - /* read memory through APB-AP */ - cortex_a_prep_memaccess(target, 1); - retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); - cortex_a_post_memaccess(target, 1); - } + if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) + return mem_ap_read_buf(armv7a->memory_ap, buffer, size, count, address); + + /* read memory through the CPU */ + cortex_a_prep_memaccess(target, 1); + retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); + cortex_a_post_memaccess(target, 1); + return retval; } -static int cortex_a_read_memory(struct target *target, uint32_t address, +static int cortex_a_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); cortex_a_prep_memaccess(target, 0); - retval = cortex_a_read_apb_ab_memory(target, address, size, count, buffer); + retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); return retval; } -static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, +static int cortex_a_read_memory_ahb(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int mmu_enabled = 0; - uint32_t virt, phys; + target_addr_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; @@ -2712,8 +2693,8 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, return target_read_memory(target, address, size, count, buffer); /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { @@ -2728,7 +2709,8 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, if (retval != ERROR_OK) return retval; - LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + LOG_DEBUG("Reading at virtual address. " + "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, virt, phys); address = phys; } @@ -2742,47 +2724,54 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, } static int cortex_a_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - int retval = ERROR_COMMAND_SYNTAX_ERROR; + struct armv7a_common *armv7a = target_to_armv7a(target); + struct adiv5_dap *swjdp = armv7a->arm.dap; + uint8_t apsel = swjdp->apsel; + int retval; + + if (!count || !buffer) + return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); - if (count && buffer) { - /* write memory through APB-AP */ - cortex_a_prep_memaccess(target, 1); - retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); - cortex_a_post_memaccess(target, 1); - } + if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) + return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); + + /* write memory through the CPU */ + cortex_a_prep_memaccess(target, 1); + retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); + cortex_a_post_memaccess(target, 1); return retval; } -static int cortex_a_write_memory(struct target *target, uint32_t address, +static int cortex_a_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* memory writes bypass the caches, must flush before writing */ armv7a_cache_auto_flush_on_write(target, address, size * count); cortex_a_prep_memaccess(target, 0); - retval = cortex_a_write_apb_ab_memory(target, address, size, count, buffer); + retval = cortex_a_write_cpu_memory(target, address, size, count, buffer); cortex_a_post_memaccess(target, 0); return retval; } -static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, +static int cortex_a_write_memory_ahb(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int mmu_enabled = 0; - uint32_t virt, phys; + target_addr_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; @@ -2792,8 +2781,8 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, return target_write_memory(target, address, size, count, buffer); /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { @@ -2808,7 +2797,8 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, if (retval != ERROR_OK) return retval; - LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + LOG_DEBUG("Writing to virtual address. " + "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, virt, phys); address = phys; @@ -2822,7 +2812,7 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, return retval; } -static int cortex_a_read_buffer(struct target *target, uint32_t address, +static int cortex_a_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; @@ -2856,7 +2846,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address, return ERROR_OK; } -static int cortex_a_write_buffer(struct target *target, uint32_t address, +static int cortex_a_write_buffer(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; @@ -2908,6 +2898,7 @@ static int cortex_a_handle_target_request(void *priv) armv7a->debug_base + CPUDBG_DSCR, &dscr); /* check if we have data */ + int64_t then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) { retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DTRTX, &request); @@ -2916,6 +2907,10 @@ static int cortex_a_handle_target_request(void *priv) retval = mem_ap_read_atomic_u32(armv7a->debug_ap, armv7a->debug_base + CPUDBG_DSCR, &dscr); } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for dtr tx full"); + return ERROR_FAIL; + } } } @@ -2931,9 +2926,10 @@ static int cortex_a_examine_first(struct target *target) struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *swjdp = armv7a->arm.dap; + int i; int retval = ERROR_OK; - uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg; + uint32_t didr, cpuid, dbg_osreg; retval = dap_dp_init(swjdp); if (retval != ERROR_OK) { @@ -2941,7 +2937,7 @@ static int cortex_a_examine_first(struct target *target) return retval; } - /* Search for the APB-AB - it is needed for access to debug registers */ + /* Search for the APB-AP - it is needed for access to debug registers */ retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap); if (retval != ERROR_OK) { LOG_ERROR("Could not find APB-AP for debug access"); @@ -2965,11 +2961,10 @@ static int cortex_a_examine_first(struct target *target) retval = mem_ap_init(armv7a->memory_ap); if (retval == ERROR_OK) armv7a->memory_ap_available = true; - else - LOG_WARNING("Could not initialize AHB-AP for memory access - using APB-AP"); - } else { - /* AHB-AP not found - use APB-AP */ - LOG_DEBUG("Could not find AHB-AP - using APB-AP for memory access"); + } + if (retval != ERROR_OK) { + /* AHB-AP not found or unavailable - use the CPU */ + LOG_DEBUG("No AHB-AP available for memory access"); } if (!target->dbgbase_set) { @@ -2996,79 +2991,69 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_base = target->dbgbase; retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CPUID"); - return retval; - } - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CTYPR, &ctypr); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CTYPR"); - return retval; - } - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_TTYPR, &ttypr); + armv7a->debug_base + CPUDBG_DIDR, &didr); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "TTYPR"); + LOG_DEBUG("Examine %s failed", "DIDR"); return retval; } retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DIDR, &didr); + armv7a->debug_base + CPUDBG_CPUID, &cpuid); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "DIDR"); + LOG_DEBUG("Examine %s failed", "CPUID"); return retval; } - LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); - LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); LOG_DEBUG("didr = 0x%08" PRIx32, didr); + LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - cortex_a->cpuid = cpuid; - cortex_a->ctypr = ctypr; - cortex_a->ttypr = ttypr; cortex_a->didr = didr; + cortex_a->cpuid = cpuid; - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A15_PARTNUM) { - - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - - if (retval != ERROR_OK) - return retval; + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) { + LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; } - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A7_PARTNUM) { - - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - if (retval != ERROR_OK) - return retval; + if (dbg_osreg & PRSR_STICKY_RESET_STATUS) + LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid); - } + /* Read DBGOSLSR and check if OSLK is implemented */ retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); - + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); if (retval != ERROR_OK) return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* check if OS Lock is implemented */ + if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) { + /* check if OS Lock is set */ + if (dbg_osreg & OSLSR_OSLK) { + LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid); + + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLAR, + 0); + if (retval == ERROR_OK) + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); + + /* if we fail to access the register or cannot reset the OSLK bit, bail out */ + if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) { + LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?", + target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; + } + } + } armv7a->arm.core_type = ARM_MODE_MON; @@ -3128,6 +3113,7 @@ static int cortex_a_init_target(struct command_context *cmd_ctx, struct target *target) { /* examine_first() does a bunch of this */ + arm_semihosting_init(target); return ERROR_OK; } @@ -3217,7 +3203,7 @@ static int cortex_a_mmu(struct target *target, int *enabled) } static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys) + target_addr_t virt, target_addr_t *phys) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); @@ -3235,7 +3221,8 @@ static int cortex_a_virt2phys(struct target *target, retval = cortex_a_mmu_modify(target, 1); if (retval != ERROR_OK) goto done; - retval = armv7a_mmu_translate_va_pa(target, virt, phys, 1); + retval = armv7a_mmu_translate_va_pa(target, (uint32_t)virt, + (uint32_t *)phys, 1); } done: return retval; @@ -3331,17 +3318,14 @@ COMMAND_HANDLER(handle_cortex_a_mask_interrupts_command) }; const Jim_Nvp *n; - if (target->state != TARGET_HALTED) { - command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME); - return ERROR_OK; - } - if (CMD_ARGC > 0) { n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]); - if (n->name == NULL) + if (n->name == NULL) { + LOG_ERROR("Unknown parameter: %s - should be off or on", CMD_ARGV[0]); return ERROR_COMMAND_SYNTAX_ERROR; - cortex_a->isrmasking_mode = n->value; + } + cortex_a->isrmasking_mode = n->value; } n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_a->isrmasking_mode); @@ -3413,7 +3397,7 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "maskisr", .handler = handle_cortex_a_mask_interrupts_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "mask cortex_a interrupts", .usage = "['on'|'off']", }, @@ -3550,8 +3534,8 @@ struct target_type cortexr4_target = { /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, - .read_memory = cortex_a_read_memory, - .write_memory = cortex_a_write_memory, + .read_memory = cortex_a_read_phys_memory, + .write_memory = cortex_a_write_phys_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index 1c63588e2..ff0343208 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -22,13 +22,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef CORTEX_A_H -#define CORTEX_A_H +#ifndef OPENOCD_TARGET_CORTEX_A_H +#define OPENOCD_TARGET_CORTEX_A_H #include "armv7a.h" @@ -99,8 +97,6 @@ struct cortex_a_common { int fast_reg_read; uint32_t cpuid; - uint32_t ctypr; - uint32_t ttypr; uint32_t didr; enum cortex_a_isrmasking_mode isrmasking_mode; @@ -116,4 +112,4 @@ target_to_cortex_a(struct target *target) return container_of(target->arch_info, struct cortex_a_common, armv7a_common.arm); } -#endif /* CORTEX_A_H */ +#endif /* OPENOCD_TARGET_CORTEX_A_H */ diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 6786c46c9..e80cd2356 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * * * * * * Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0) * @@ -684,7 +682,7 @@ void cortex_m_enable_breakpoints(struct target *target) } static int cortex_m_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct armv7m_common *armv7m = target_to_armv7m(target); struct breakpoint *breakpoint = NULL; @@ -752,7 +750,7 @@ static int cortex_m_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -784,7 +782,7 @@ static int cortex_m_resume(struct target *target, int current, /* int irqstepcount = 0; */ static int cortex_m_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; @@ -983,6 +981,18 @@ static int cortex_m_assert_reset(struct target *target) bool srst_asserted = false; + if (!target_was_examined(target)) { + if (jtag_reset_config & RESET_HAS_SRST) { + adapter_assert_reset(); + if (target->reset_halt) + LOG_ERROR("Target not examined, will not halt after reset!"); + return ERROR_OK; + } else { + LOG_ERROR("Target not examined, reset NOT asserted!"); + return ERROR_FAIL; + } + } + if ((jtag_reset_config & RESET_HAS_SRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { adapter_assert_reset(); @@ -992,34 +1002,24 @@ static int cortex_m_assert_reset(struct target *target) /* Enable debug requests */ int retval; retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr); - if (retval != ERROR_OK) - return retval; - if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) { + /* Store important errors instead of failing and proceed to reset assert */ + + if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN)) retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN); - if (retval != ERROR_OK) - return retval; - } /* If the processor is sleeping in a WFI or WFE instruction, the * C_HALT bit must be asserted to regain control */ - if (cortex_m->dcb_dhcsr & S_SLEEP) { + if (retval == ERROR_OK && (cortex_m->dcb_dhcsr & S_SLEEP)) retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); - if (retval != ERROR_OK) - return retval; - } - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0); - if (retval != ERROR_OK) - return retval; + mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0); + /* Ignore less important errors */ if (!target->reset_halt) { /* Set/Clear C_MASKINTS in a separate operation */ - if (cortex_m->dcb_dhcsr & C_MASKINTS) { - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, + if (cortex_m->dcb_dhcsr & C_MASKINTS) + mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT); - if (retval != ERROR_OK) - return retval; - } /* clear any debug flags before resuming */ cortex_m_clear_halt(target); @@ -1033,16 +1033,20 @@ static int cortex_m_assert_reset(struct target *target) * bad vector table entries. Should this include MMERR or * other flags too? */ - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, + int retval2; + retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); - if (retval != ERROR_OK) - return retval; + if (retval != ERROR_OK || retval2 != ERROR_OK) + LOG_INFO("AP write error, reset will not halt"); } if (jtag_reset_config & RESET_HAS_SRST) { /* default to asserting srst */ if (!srst_asserted) adapter_assert_reset(); + + /* srst is asserted, ignore AP access errors */ + retval = ERROR_OK; } else { /* Use a standard Cortex-M3 software reset mechanism. * We default to using VECRESET as it is supported on all current cores. @@ -1057,27 +1061,24 @@ static int cortex_m_assert_reset(struct target *target) "handler to reset any peripherals or configure hardware srst support."); } - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, + int retval3; + retval3 = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ) ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET)); - if (retval != ERROR_OK) + if (retval3 != ERROR_OK) LOG_DEBUG("Ignoring AP write error right after reset"); - retval = dap_dp_init(armv7m->debug_ap->dap); - if (retval != ERROR_OK) { + retval3 = dap_dp_init(armv7m->debug_ap->dap); + if (retval3 != ERROR_OK) LOG_ERROR("DP initialisation failed"); - return retval; - } - { + else { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI * after reset) on LM3S6918 -- Michael Schwingen */ uint32_t tmp; - retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, &tmp); - if (retval != ERROR_OK) - return retval; + mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, &tmp); } } @@ -1086,6 +1087,10 @@ static int cortex_m_assert_reset(struct target *target) register_cache_invalidate(cortex_m->armv7m.arm.core_cache); + /* now return stored error code if any */ + if (retval != ERROR_OK) + return retval; + if (target->reset_halt) { retval = target_halt(target); if (retval != ERROR_OK) @@ -1108,7 +1113,8 @@ static int cortex_m_deassert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_HAS_SRST) && - !(jtag_reset_config & RESET_SRST_NO_GATING)) { + !(jtag_reset_config & RESET_SRST_NO_GATING) && + target_was_examined(target)) { int retval = dap_dp_init(armv7m->debug_ap->dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); @@ -1192,7 +1198,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->set = true; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1213,7 +1219,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi return ERROR_OK; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1658,7 +1664,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, return ERROR_OK; } -static int cortex_m_read_memory(struct target *target, uint32_t address, +static int cortex_m_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -1672,7 +1678,7 @@ static int cortex_m_read_memory(struct target *target, uint32_t address, return mem_ap_read_buf(armv7m->debug_ap, buffer, size, count, address); } -static int cortex_m_write_memory(struct target *target, uint32_t address, +static int cortex_m_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -1690,6 +1696,7 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, struct target *target) { armv7m_build_reg_cache(target); + arm_semihosting_init(target); return ERROR_OK; } @@ -1702,6 +1709,7 @@ void cortex_m_deinit_target(struct target *target) cortex_m_dwt_free(target); armv7m_free_reg_cache(target); + free(target->private_config); free(cortex_m); } @@ -1882,6 +1890,11 @@ static void cortex_m_dwt_free(struct target *target) #define MVFR0_DEFAULT_M4 0x10110021 #define MVFR1_DEFAULT_M4 0x11000011 +#define MVFR0_DEFAULT_M7_SP 0x10110021 +#define MVFR0_DEFAULT_M7_DP 0x10110221 +#define MVFR1_DEFAULT_M7_SP 0x11000011 +#define MVFR1_DEFAULT_M7_DP 0x12000011 + int cortex_m_examine(struct target *target) { int retval; @@ -1900,11 +1913,15 @@ int cortex_m_examine(struct target *target) return retval; } - /* Search for the MEM-AP */ - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap); - if (retval != ERROR_OK) { - LOG_ERROR("Could not find MEM-AP to control the core"); - return retval; + if (cortex_m->apsel < 0) { + /* Search for the MEM-AP */ + retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap); + if (retval != ERROR_OK) { + LOG_ERROR("Could not find MEM-AP to control the core"); + return retval; + } + } else { + armv7m->debug_ap = dap_ap(swjdp, cortex_m->apsel); } /* Leave (only) generic DAP stuff for debugport_init(); */ @@ -1928,23 +1945,42 @@ int cortex_m_examine(struct target *target) LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected", i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf)); + if (i == 7) { + uint8_t rev, patch; + rev = (cpuid >> 20) & 0xf; + patch = (cpuid >> 0) & 0xf; + if ((rev == 0) && (patch < 2)) + LOG_WARNING("Silicon bug: single stepping will enter pending exception handler!"); + } LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid); - /* test for floating point feature on cortex-m4 */ if (i == 4) { target_read_u32(target, MVFR0, &mvfr0); target_read_u32(target, MVFR1, &mvfr1); + /* test for floating point feature on Cortex-M4 */ if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) { LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i); armv7m->fp_feature = FPv4_SP; } + } else if (i == 7) { + target_read_u32(target, MVFR0, &mvfr0); + target_read_u32(target, MVFR1, &mvfr1); + + /* test for floating point features on Cortex-M7 */ + if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) { + LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i); + armv7m->fp_feature = FPv5_SP; + } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) { + LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i); + armv7m->fp_feature = FPv5_DP; + } } else if (i == 0) { /* Cortex-M0 does not support unaligned memory access */ armv7m->arm.is_armv6m = true; } - if (armv7m->fp_feature != FPv4_SP && + if (armv7m->fp_feature == FP_NONE && armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) { /* free unavailable FPU registers */ size_t idx; @@ -1959,9 +1995,14 @@ int cortex_m_examine(struct target *target) armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; } - if ((i == 4 || i == 3) && !armv7m->stlink) { - /* Cortex-M3/M4 has 4096 bytes autoincrement range */ - armv7m->debug_ap->tar_autoincr_block = (1 << 12); + if (!armv7m->stlink) { + if (i == 3 || i == 4) + /* Cortex-M3/M4 have 4096 bytes autoincrement range, + * s. ARM IHI 0031C: MEM-AP 7.2.2 */ + armv7m->debug_ap->tar_autoincr_block = (1 << 12); + else if (i == 7) + /* Cortex-M7 has only 1024 bytes autoincrement range */ + armv7m->debug_ap->tar_autoincr_block = (1 << 10); } /* Configure trace modules */ @@ -2144,6 +2185,13 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp) cortex_m->common_magic = CORTEX_M_COMMON_MAGIC; cortex_m_init_arch_info(target, cortex_m, target->tap); + if (target->private_config != NULL) { + struct adiv5_private_config *pc = + (struct adiv5_private_config *)target->private_config; + cortex_m->apsel = pc->ap_num; + } else + cortex_m->apsel = -1; + return ERROR_OK; } @@ -2405,6 +2453,7 @@ struct target_type cortexm_target = { .commands = cortex_m_command_handlers, .target_create = cortex_m_target_create, + .target_jim_configure = adiv5_jim_configure, .init_target = cortex_m_init_target, .examine = cortex_m_examine, .deinit_target = cortex_m_deinit_target, diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index b09cc49a6..3d9714b90 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef CORTEX_M_H -#define CORTEX_M_H +#ifndef OPENOCD_TARGET_CORTEX_M_H +#define OPENOCD_TARGET_CORTEX_M_H #include "armv7m.h" @@ -190,6 +188,8 @@ struct cortex_m_common { enum cortex_m_isrmasking_mode isrmasking_mode; struct armv7m_common armv7m; + + int apsel; }; static inline struct cortex_m_common * @@ -213,4 +213,4 @@ void cortex_m_enable_watchpoints(struct target *target); void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target); void cortex_m_deinit_target(struct target *target); -#endif /* CORTEX_M_H */ +#endif /* OPENOCD_TARGET_CORTEX_M_H */ diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 1cb18cf11..1d728dff8 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -1119,7 +1117,7 @@ static int dsp563xx_halt(struct target *target) static int dsp563xx_resume(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints, int debug_execution) { @@ -1292,7 +1290,7 @@ static int dsp563xx_step_ex(struct target *target, static int dsp563xx_step(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints) { int err; @@ -1376,7 +1374,7 @@ static int dsp563xx_deassert_reset(struct target *target) static int dsp563xx_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info) { int i; @@ -1594,7 +1592,7 @@ static int dsp563xx_read_memory_core(struct target *target, static int dsp563xx_read_memory(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1662,7 +1660,7 @@ static int dsp563xx_read_memory(struct target *target, } static int dsp563xx_read_memory_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1673,7 +1671,7 @@ static int dsp563xx_read_memory_default(struct target *target, } static int dsp563xx_read_buffer_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint8_t *buffer) { @@ -1684,7 +1682,7 @@ static int dsp563xx_read_buffer_default(struct target *target, static int dsp563xx_write_memory_core(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1696,7 +1694,7 @@ static int dsp563xx_write_memory_core(struct target *target, const uint8_t *b; LOG_DEBUG( - "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + "memtype: %d address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", mem_type, address, size, @@ -1768,7 +1766,7 @@ static int dsp563xx_write_memory_core(struct target *target, static int dsp563xx_write_memory(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1836,7 +1834,7 @@ static int dsp563xx_write_memory(struct target *target, } static int dsp563xx_write_memory_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1846,7 +1844,7 @@ static int dsp563xx_write_memory_default(struct target *target, } static int dsp563xx_write_buffer_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, const uint8_t *buffer) { diff --git a/src/target/dsp563xx.h b/src/target/dsp563xx.h index 446ad3f53..4bb5aceaf 100644 --- a/src/target/dsp563xx.h +++ b/src/target/dsp563xx.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef DSP563XX_H -#define DSP563XX_H +#ifndef OPENOCD_TARGET_DSP563XX_H +#define OPENOCD_TARGET_DSP563XX_H #include #include @@ -72,4 +70,4 @@ static inline struct dsp563xx_common *target_to_dsp563xx(struct target *target) return target->arch_info; } -#endif /* DSP563XX_H */ +#endif /* OPENOCD_TARGET_DSP563XX_H */ diff --git a/src/target/dsp563xx_once.c b/src/target/dsp563xx_once.c index aa8c96910..fe4927ba3 100644 --- a/src/target/dsp563xx_once.c +++ b/src/target/dsp563xx_once.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/dsp563xx_once.h b/src/target/dsp563xx_once.h index 8835d553d..da7f5e9b8 100644 --- a/src/target/dsp563xx_once.h +++ b/src/target/dsp563xx_once.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef DSP563XX_ONCE_H -#define DSP563XX_ONCE_H +#ifndef OPENOCD_TARGET_DSP563XX_ONCE_H +#define OPENOCD_TARGET_DSP563XX_ONCE_H #include @@ -88,4 +86,4 @@ int dsp563xx_once_execute_sw_ir(struct jtag_tap *tap, int flush, uint32_t opcode /** double word instruction */ int dsp563xx_once_execute_dw_ir(struct jtag_tap *tap, int flush, uint32_t opcode, uint32_t operand); -#endif /* DSP563XX_ONCE_H */ +#endif /* OPENOCD_TARGET_DSP563XX_ONCE_H */ diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index 8a58cab47..a50f2cd47 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -1003,17 +1001,17 @@ static int dsp5680xx_poll(struct target *target) __func__); target->state = TARGET_UNKNOWN; return ERROR_TARGET_FAILURE; - }; + } if (target->state == TARGET_UNKNOWN) { LOG_ERROR("%s: Target status invalid - communication failure", __func__); return ERROR_TARGET_FAILURE; - }; + } return ERROR_OK; } static int dsp5680xx_resume(struct target *target, int current, - uint32_t address, int hb, int d) + target_addr_t address, int hb, int d) { if (target->state == TARGET_RUNNING) { LOG_USER("Target already running."); @@ -1170,7 +1168,7 @@ static int dsp5680xx_read_32_single(struct target *t, uint32_t a, return retval; } -static int dsp5680xx_read(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_read(struct target *t, target_addr_t a, uint32_t size, uint32_t count, uint8_t *buf) { struct target *target = t; @@ -1425,7 +1423,7 @@ static int dsp5680xx_write_32(struct target *t, uint32_t a, uint32_t c, * * @return */ -static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c, +static int dsp5680xx_write(struct target *t, target_addr_t a, uint32_t s, uint32_t c, const uint8_t *b) { /* TODO Cannot write 32bit to odd address, will write 0x12345678 as 0x5678 0x0012 */ @@ -1470,7 +1468,7 @@ static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c, return retval; } -static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_write_buffer(struct target *t, target_addr_t a, uint32_t size, const uint8_t *b) { check_halt_and_debug(t); @@ -1487,7 +1485,7 @@ static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size, * * @return */ -static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_read_buffer(struct target *t, target_addr_t a, uint32_t size, uint8_t *buf) { check_halt_and_debug(t); @@ -1507,7 +1505,7 @@ static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size, * * @return */ -static int dsp5680xx_checksum_memory(struct target *t, uint32_t a, uint32_t s, +static int dsp5680xx_checksum_memory(struct target *t, target_addr_t a, uint32_t s, uint32_t *checksum) { return ERROR_FAIL; @@ -2264,7 +2262,7 @@ int dsp5680xx_f_lock(struct target *target) return retval; } -static int dsp5680xx_step(struct target *target, int current, uint32_t address, +static int dsp5680xx_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP, diff --git a/src/target/dsp5680xx.h b/src/target/dsp5680xx.h index cb3bf2a4f..842796bc7 100644 --- a/src/target/dsp5680xx.h +++ b/src/target/dsp5680xx.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef DSP5680XX_H -#define DSP5680XX_H +#ifndef OPENOCD_TARGET_DSP5680XX_H +#define OPENOCD_TARGET_DSP5680XX_H #include @@ -381,4 +379,4 @@ int dsp5680xx_f_lock(struct target *target); */ int dsp5680xx_f_unlock(struct target *target); -#endif /* DSP5680XX_H */ +#endif /* OPENOCD_TARGET_DSP5680XX_H */ diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c index 4b3a05a83..09d6fc8a1 100644 --- a/src/target/embeddedice.c +++ b/src/target/embeddedice.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/embeddedice.h b/src/target/embeddedice.h index f110e82e6..39902fb3e 100644 --- a/src/target/embeddedice.h +++ b/src/target/embeddedice.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef EMBEDDED_ICE_H -#define EMBEDDED_ICE_H +#ifndef OPENOCD_TARGET_EMBEDDEDICE_H +#define OPENOCD_TARGET_EMBEDDEDICE_H #include "arm7_9_common.h" @@ -127,4 +125,4 @@ static inline void embeddedice_write_reg_inner(struct jtag_tap *tap, int reg_add void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, const uint8_t *buffer, int little, int count); -#endif /* EMBEDDED_ICE_H */ +#endif /* OPENOCD_TARGET_EMBEDDEDICE_H */ diff --git a/src/target/etb.c b/src/target/etb.c index 56f5795bd..dc25844b9 100644 --- a/src/target/etb.c +++ b/src/target/etb.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/etb.h b/src/target/etb.h index d5cbd85c1..680c8a1ab 100644 --- a/src/target/etb.h +++ b/src/target/etb.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ETB_H -#define ETB_H +#ifndef OPENOCD_TARGET_ETB_H +#define OPENOCD_TARGET_ETB_H /* ETB registers */ enum { @@ -57,4 +55,4 @@ extern struct etm_capture_driver etb_capture_driver; struct reg_cache *etb_build_reg_cache(struct etb *etb); -#endif /* ETB_H */ +#endif /* OPENOCD_TARGET_ETB_H */ diff --git a/src/target/etm.c b/src/target/etm.c index 0246ae25e..6a00c23a8 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1701,7 +1699,7 @@ COMMAND_HANDLER(handle_etm_image_command) COMMAND_HANDLER(handle_etm_dump_command) { - struct fileio file; + struct fileio *file; struct target *target; struct arm *arm; struct etm_context *etm_ctx; @@ -1741,24 +1739,24 @@ COMMAND_HANDLER(handle_etm_dump_command) if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) return ERROR_FAIL; - fileio_write_u32(&file, etm_ctx->capture_status); - fileio_write_u32(&file, etm_ctx->control); - fileio_write_u32(&file, etm_ctx->trace_depth); + fileio_write_u32(file, etm_ctx->capture_status); + fileio_write_u32(file, etm_ctx->control); + fileio_write_u32(file, etm_ctx->trace_depth); for (i = 0; i < etm_ctx->trace_depth; i++) { - fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat); - fileio_write_u32(&file, etm_ctx->trace_data[i].packet); - fileio_write_u32(&file, etm_ctx->trace_data[i].flags); + fileio_write_u32(file, etm_ctx->trace_data[i].pipestat); + fileio_write_u32(file, etm_ctx->trace_data[i].packet); + fileio_write_u32(file, etm_ctx->trace_data[i].flags); } - fileio_close(&file); + fileio_close(file); return ERROR_OK; } COMMAND_HANDLER(handle_etm_load_command) { - struct fileio file; + struct fileio *file; struct target *target; struct arm *arm; struct etm_context *etm_ctx; @@ -1789,15 +1787,15 @@ COMMAND_HANDLER(handle_etm_load_command) return ERROR_FAIL; size_t filesize; - int retval = fileio_size(&file, &filesize); + int retval = fileio_size(file, &filesize); if (retval != ERROR_OK) { - fileio_close(&file); + fileio_close(file); return retval; } if (filesize % 4) { command_print(CMD_CTX, "size isn't a multiple of 4, no valid trace data"); - fileio_close(&file); + fileio_close(file); return ERROR_FAIL; } @@ -1808,28 +1806,28 @@ COMMAND_HANDLER(handle_etm_load_command) { uint32_t tmp; - fileio_read_u32(&file, &tmp); etm_ctx->capture_status = tmp; - fileio_read_u32(&file, &tmp); etm_ctx->control = tmp; - fileio_read_u32(&file, &etm_ctx->trace_depth); + fileio_read_u32(file, &tmp); etm_ctx->capture_status = tmp; + fileio_read_u32(file, &tmp); etm_ctx->control = tmp; + fileio_read_u32(file, &etm_ctx->trace_depth); } etm_ctx->trace_data = malloc(sizeof(struct etmv1_trace_data) * etm_ctx->trace_depth); if (etm_ctx->trace_data == NULL) { command_print(CMD_CTX, "not enough memory to perform operation"); - fileio_close(&file); + fileio_close(file); return ERROR_FAIL; } for (i = 0; i < etm_ctx->trace_depth; i++) { uint32_t pipestat, packet, flags; - fileio_read_u32(&file, &pipestat); - fileio_read_u32(&file, &packet); - fileio_read_u32(&file, &flags); + fileio_read_u32(file, &pipestat); + fileio_read_u32(file, &packet); + fileio_read_u32(file, &flags); etm_ctx->trace_data[i].pipestat = pipestat & 0xff; etm_ctx->trace_data[i].packet = packet & 0xffff; etm_ctx->trace_data[i].flags = flags; } - fileio_close(&file); + fileio_close(file); return ERROR_OK; } diff --git a/src/target/etm.h b/src/target/etm.h index ff7925bf7..6a78b7564 100644 --- a/src/target/etm.h +++ b/src/target/etm.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ETM_H -#define ETM_H +#ifndef OPENOCD_TARGET_ETM_H +#define OPENOCD_TARGET_ETM_H #include "trace.h" #include "arm_jtag.h" @@ -223,4 +221,4 @@ extern const struct command_registration etm_command_handlers[]; #define ERROR_ETM_CAPTURE_INIT_FAILED (-1302) #define ERROR_ETM_ANALYSIS_FAILED (-1303) -#endif /* ETM_H */ +#endif /* OPENOCD_TARGET_ETM_H */ diff --git a/src/target/etm_dummy.c b/src/target/etm_dummy.c index 0533d1e0d..b18ce1744 100644 --- a/src/target/etm_dummy.c +++ b/src/target/etm_dummy.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/etm_dummy.h b/src/target/etm_dummy.h index 450b5c182..5a1955f37 100644 --- a/src/target/etm_dummy.h +++ b/src/target/etm_dummy.h @@ -13,16 +13,14 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef ETM_DUMMY_H -#define ETM_DUMMY_H +#ifndef OPENOCD_TARGET_ETM_DUMMY_H +#define OPENOCD_TARGET_ETM_DUMMY_H #include "etm.h" extern struct etm_capture_driver etm_dummy_capture_driver; -#endif /* ETB_H */ +#endif /* OPENOCD_TARGET_ETM_DUMMY_H */ diff --git a/src/target/fa526.c b/src/target/fa526.c index dfb29b8ee..9f6b80551 100644 --- a/src/target/fa526.c +++ b/src/target/fa526.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* diff --git a/src/target/feroceon.c b/src/target/feroceon.c index 9c204f04f..6b14ab6a8 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* @@ -64,6 +62,13 @@ static int feroceon_assert_reset(struct target *target) struct arm7_9_common *arm7_9 = arm->arch_info; int ud = arm7_9->use_dbgrq; + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } + arm7_9->use_dbgrq = 0; if (target->reset_halt) arm7_9_halt(target); @@ -455,7 +460,7 @@ static int feroceon_examine_debug_reason(struct target *target) } static int feroceon_bulk_write_memory(struct target *target, - uint32_t address, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t count, const uint8_t *buffer) { int retval; struct arm *arm = target->arch_info; @@ -560,7 +565,7 @@ static int feroceon_bulk_write_memory(struct target *target, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); if (endaddress != address + count*4) { LOG_ERROR("DCC write failed," - " expected end address 0x%08" PRIx32 + " expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32 "", address + count*4, endaddress); retval = ERROR_FAIL; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index d0be966c3..78dc8c512 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -18,9 +18,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -343,7 +341,7 @@ static int adapter_init_target(struct command_context *cmd_ctx, LOG_DEBUG("%s", __func__); armv7m_build_reg_cache(target); - + arm_semihosting_init(target); return ERROR_OK; } @@ -586,7 +584,7 @@ static int adapter_halt(struct target *target) } static int adapter_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, + target_addr_t address, int handle_breakpoints, int debug_execution) { int res; @@ -596,8 +594,8 @@ static int adapter_resume(struct target *target, int current, struct breakpoint *breakpoint = NULL; struct reg *pc; - LOG_DEBUG("%s %d 0x%08" PRIx32 " %d %d", __func__, current, address, - handle_breakpoints, debug_execution); + LOG_DEBUG("%s %d " TARGET_ADDR_FMT " %d %d", __func__, current, + address, handle_breakpoints, debug_execution); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -644,7 +642,7 @@ static int adapter_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -677,7 +675,7 @@ static int adapter_resume(struct target *target, int current, } static int adapter_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { int res; struct hl_interface_s *adapter = target_to_adapter(target); @@ -740,7 +738,7 @@ static int adapter_step(struct target *target, int current, return ERROR_OK; } -static int adapter_read_memory(struct target *target, uint32_t address, +static int adapter_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -749,12 +747,13 @@ static int adapter_read_memory(struct target *target, uint32_t address, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); + LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32, + __func__, address, size, count); return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer); } -static int adapter_write_memory(struct target *target, uint32_t address, +static int adapter_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { @@ -763,7 +762,8 @@ static int adapter_write_memory(struct target *target, uint32_t address, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); + LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32, + __func__, address, size, count); return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer); } diff --git a/src/target/image.c b/src/target/image.c index fa51ce33e..f97d90403 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -47,7 +45,7 @@ static int autodetect_image_type(struct image *image, const char *url) { int retval; - struct fileio fileio; + struct fileio *fileio; size_t read_bytes; uint8_t buffer[9]; @@ -55,13 +53,13 @@ static int autodetect_image_type(struct image *image, const char *url) retval = fileio_open(&fileio, url, FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) return retval; - retval = fileio_read(&fileio, 9, buffer, &read_bytes); + retval = fileio_read(fileio, 9, buffer, &read_bytes); if (retval == ERROR_OK) { if (read_bytes != 9) retval = ERROR_FILEIO_OPERATION_FAILED; } - fileio_close(&fileio); + fileio_close(fileio); if (retval != ERROR_OK) return retval; @@ -122,7 +120,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, struct imagesection *section) { struct image_ihex *ihex = image->type_private; - struct fileio *fileio = &ihex->fileio; + struct fileio *fileio = ihex->fileio; uint32_t full_address = 0x0; uint32_t cooked_bytes; int i; @@ -352,7 +350,7 @@ static int image_elf_read_headers(struct image *image) return ERROR_FILEIO_OPERATION_FAILED; } - retval = fileio_read(&elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); + retval = fileio_read(elf->fileio, sizeof(Elf32_Ehdr), (uint8_t *)elf->header, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF file header, read failed"); return ERROR_FILEIO_OPERATION_FAILED; @@ -384,7 +382,7 @@ static int image_elf_read_headers(struct image *image) return ERROR_IMAGE_FORMAT_ERROR; } - retval = fileio_seek(&elf->fileio, field32(elf, elf->header->e_phoff)); + retval = fileio_seek(elf->fileio, field32(elf, elf->header->e_phoff)); if (retval != ERROR_OK) { LOG_ERROR("cannot seek to ELF program header table, read failed"); return retval; @@ -396,7 +394,7 @@ static int image_elf_read_headers(struct image *image) return ERROR_FILEIO_OPERATION_FAILED; } - retval = fileio_read(&elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), + retval = fileio_read(elf->fileio, elf->segment_count*sizeof(Elf32_Phdr), (uint8_t *)elf->segments, &read_bytes); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF segment headers, read failed"); @@ -486,12 +484,12 @@ static int image_elf_read_section(struct image *image, LOG_DEBUG("read elf: size = 0x%zu at 0x%" PRIx32 "", read_size, field32(elf, segment->p_offset) + offset); /* read initialized area of the segment */ - retval = fileio_seek(&elf->fileio, field32(elf, segment->p_offset) + offset); + retval = fileio_seek(elf->fileio, field32(elf, segment->p_offset) + offset); if (retval != ERROR_OK) { LOG_ERROR("cannot find ELF segment content, seek failed"); return retval; } - retval = fileio_read(&elf->fileio, read_size, buffer, &really_read); + retval = fileio_read(elf->fileio, read_size, buffer, &really_read); if (retval != ERROR_OK) { LOG_ERROR("cannot read ELF segment content, read failed"); return retval; @@ -511,7 +509,7 @@ static int image_mot_buffer_complete_inner(struct image *image, struct imagesection *section) { struct image_mot *mot = image->type_private; - struct fileio *fileio = &mot->fileio; + struct fileio *fileio = mot->fileio; uint32_t full_address = 0x0; uint32_t cooked_bytes; int i; @@ -708,9 +706,9 @@ int image_open(struct image *image, const char *url, const char *type_string) if (retval != ERROR_OK) return retval; size_t filesize; - retval = fileio_size(&image_binary->fileio, &filesize); + retval = fileio_size(image_binary->fileio, &filesize); if (retval != ERROR_OK) { - fileio_close(&image_binary->fileio); + fileio_close(image_binary->fileio); return retval; } @@ -731,8 +729,8 @@ int image_open(struct image *image, const char *url, const char *type_string) retval = image_ihex_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( - "failed buffering IHEX image, check daemon output for additional information"); - fileio_close(&image_ihex->fileio); + "failed buffering IHEX image, check server output for additional information"); + fileio_close(image_ihex->fileio); return retval; } } else if (image->type == IMAGE_ELF) { @@ -746,7 +744,7 @@ int image_open(struct image *image, const char *url, const char *type_string) retval = image_elf_read_headers(image); if (retval != ERROR_OK) { - fileio_close(&image_elf->fileio); + fileio_close(image_elf->fileio); return retval; } } else if (image->type == IMAGE_MEMORY) { @@ -782,8 +780,8 @@ int image_open(struct image *image, const char *url, const char *type_string) retval = image_mot_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( - "failed buffering S19 image, check daemon output for additional information"); - fileio_close(&image_mot->fileio); + "failed buffering S19 image, check server output for additional information"); + fileio_close(image_mot->fileio); return retval; } } else if (image->type == IMAGE_BUILDER) { @@ -835,12 +833,12 @@ int image_read_section(struct image *image, return ERROR_COMMAND_SYNTAX_ERROR; /* seek to offset */ - retval = fileio_seek(&image_binary->fileio, offset); + retval = fileio_seek(image_binary->fileio, offset); if (retval != ERROR_OK) return retval; /* return requested bytes */ - retval = fileio_read(&image_binary->fileio, size, buffer, size_read); + retval = fileio_read(image_binary->fileio, size, buffer, size_read); if (retval != ERROR_OK) return retval; } else if (image->type == IMAGE_IHEX) { @@ -945,11 +943,11 @@ void image_close(struct image *image) if (image->type == IMAGE_BINARY) { struct image_binary *image_binary = image->type_private; - fileio_close(&image_binary->fileio); + fileio_close(image_binary->fileio); } else if (image->type == IMAGE_IHEX) { struct image_ihex *image_ihex = image->type_private; - fileio_close(&image_ihex->fileio); + fileio_close(image_ihex->fileio); if (image_ihex->buffer) { free(image_ihex->buffer); @@ -958,7 +956,7 @@ void image_close(struct image *image) } else if (image->type == IMAGE_ELF) { struct image_elf *image_elf = image->type_private; - fileio_close(&image_elf->fileio); + fileio_close(image_elf->fileio); if (image_elf->header) { free(image_elf->header); @@ -979,7 +977,7 @@ void image_close(struct image *image) } else if (image->type == IMAGE_SRECORD) { struct image_mot *image_mot = image->type_private; - fileio_close(&image_mot->fileio); + fileio_close(image_mot->fileio); if (image_mot->buffer) { free(image_mot->buffer); diff --git a/src/target/image.h b/src/target/image.h index 5aeba2f79..9907a5f3f 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef IMAGE_H -#define IMAGE_H +#ifndef OPENOCD_TARGET_IMAGE_H +#define OPENOCD_TARGET_IMAGE_H #include @@ -48,7 +46,7 @@ enum image_type { }; struct imagesection { - uint32_t base_address; + target_addr_t base_address; uint32_t size; int flags; void *private; /* private data */ @@ -66,11 +64,11 @@ struct image { }; struct image_binary { - struct fileio fileio; + struct fileio *fileio; }; struct image_ihex { - struct fileio fileio; + struct fileio *fileio; uint8_t *buffer; }; @@ -81,7 +79,7 @@ struct image_memory { }; struct image_elf { - struct fileio fileio; + struct fileio *fileio; Elf32_Ehdr *header; Elf32_Phdr *segments; uint32_t segment_count; @@ -89,7 +87,7 @@ struct image_elf { }; struct image_mot { - struct fileio fileio; + struct fileio *fileio; uint8_t *buffer; }; @@ -109,4 +107,4 @@ int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes, #define ERROR_IMAGE_TEMPORARILY_UNAVAILABLE (-1402) #define ERROR_IMAGE_CHECKSUM (-1403) -#endif /* IMAGE_H */ +#endif /* OPENOCD_TARGET_IMAGE_H */ diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 055d94340..2bd12fd41 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -1,11 +1,12 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) * Ivan De Cesaris (ivan.de.cesaris@intel.com) * Julien Carreno (julien.carreno@intel.com) * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com) + * Jessica Gomez (jessica.gomez.hernandez@intel.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,8 +19,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . * * Contact Information: * Intel Corporation @@ -498,6 +498,12 @@ static int halt_prep(struct target *t) if (write_hw_reg(t, DSAR, PM_DSAR, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DSAR 0x%08" PRIx32, PM_DSAR); + if (write_hw_reg(t, CSB, PM_DSB, 0) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSB].name, PM_DSB); + if (write_hw_reg(t, CSL, PM_DSL, 0) != ERROR_OK) + return ERROR_FAIL; + LOG_DEBUG("write %s 0x%08" PRIx32, regs[CSL].name, PM_DSL); if (write_hw_reg(t, DR7, PM_DR7, 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write DR7 0x%08" PRIx32, PM_DR7); @@ -511,8 +517,7 @@ static int halt_prep(struct target *t) LOG_DEBUG("EFLAGS = 0x%08" PRIx32 ", VM86 = %d, IF = %d", eflags, eflags & EFLAGS_VM86 ? 1 : 0, eflags & EFLAGS_IF ? 1 : 0); - if (eflags & EFLAGS_VM86 - || eflags & EFLAGS_IF) { + if ((eflags & EFLAGS_VM86) || (eflags & EFLAGS_IF)) { x86_32->pm_regs[I(EFLAGS)] = eflags & ~(EFLAGS_VM86 | EFLAGS_IF); if (write_hw_reg(t, EFLAGS, x86_32->pm_regs[I(EFLAGS)], 0) != ERROR_OK) return ERROR_FAIL; @@ -530,14 +535,14 @@ static int halt_prep(struct target *t) LOG_DEBUG("write CSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(CSAR)]); } if (ssar & SSAR_DPL) { - x86_32->pm_regs[I(SSAR)] = ssar & ~CSAR_DPL; + x86_32->pm_regs[I(SSAR)] = ssar & ~SSAR_DPL; if (write_hw_reg(t, SSAR, x86_32->pm_regs[I(SSAR)], 0) != ERROR_OK) return ERROR_FAIL; LOG_DEBUG("write SSAR_CPL to 0 0x%08" PRIx32, x86_32->pm_regs[I(SSAR)]); } - /* if cache's are enabled, disable and flush */ - if (!(cr0 & CR0_CD)) { + /* if cache's are enabled, disable and flush, depending on the core version */ + if (!(x86_32->core_type == LMT3_5) && !(cr0 & CR0_CD)) { LOG_DEBUG("caching enabled CR0 = 0x%08" PRIx32, cr0); if (cr0 & CR0_PG) { x86_32->pm_regs[I(CR0)] = cr0 & ~CR0_PG; @@ -563,6 +568,13 @@ static int do_halt(struct target *t) t->state = TARGET_DEBUG_RUNNING; if (enter_probemode(t) != ERROR_OK) return ERROR_FAIL; + + return lakemont_update_after_probemode_entry(t); +} + +/* we need to expose the update to be able to complete the reset at SoC level */ +int lakemont_update_after_probemode_entry(struct target *t) +{ if (save_context(t) != ERROR_OK) return ERROR_FAIL; if (halt_prep(t) != ERROR_OK) @@ -677,16 +689,16 @@ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cach arch_info->op, regval); - scan.out[0] = RDWRPDR; x86_32->flush = 0; /* dont flush scans till we have a batch */ - if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) - return ERROR_FAIL; - if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) - return ERROR_FAIL; if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; + scan.out[0] = RDWRPDR; + if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) + return ERROR_FAIL; + if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) + return ERROR_FAIL; x86_32->flush = 1; if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK) return ERROR_FAIL; @@ -982,7 +994,7 @@ int lakemont_halt(struct target *t) } } -int lakemont_resume(struct target *t, int current, uint32_t address, +int lakemont_resume(struct target *t, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { struct breakpoint *bp = NULL; @@ -1024,7 +1036,7 @@ int lakemont_resume(struct target *t, int current, uint32_t address, } int lakemont_step(struct target *t, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); diff --git a/src/target/lakemont.h b/src/target/lakemont.h index 30b34b3f2..98efd44a9 100644 --- a/src/target/lakemont.h +++ b/src/target/lakemont.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -18,8 +18,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . * * Contact Information: * Intel Corporation @@ -30,8 +29,9 @@ * This is the interface to the probemode operations for Lakemont 1 (LMT1). */ -#ifndef LAKEMONT_H -#define LAKEMONT_H +#ifndef OPENOCD_TARGET_LAKEMONT_H +#define OPENOCD_TARGET_LAKEMONT_H + #include #include @@ -95,11 +95,12 @@ int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32); int lakemont_poll(struct target *t); int lakemont_arch_state(struct target *t); int lakemont_halt(struct target *t); -int lakemont_resume(struct target *t, int current, uint32_t address, +int lakemont_resume(struct target *t, int current, target_addr_t address, int handle_breakpoints, int debug_execution); int lakemont_step(struct target *t, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); +int lakemont_update_after_probemode_entry(struct target *t); -#endif /* LAKEMONT_H */ +#endif /* OPENOCD_TARGET_LAKEMONT_H */ diff --git a/src/target/mips32.c b/src/target/mips32.c index 5a0e2a3a1..93fb4e646 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -21,9 +21,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -36,7 +34,7 @@ #include "register.h" static const char *mips_isa_strings[] = { - "MIPS32", "MIPS16e" + "MIPS32", "MIPS16", "", "MICRO MIPS32", }; #define MIPS32_GDB_DUMMY_FP_REG 1 @@ -377,6 +375,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s target->arch_info = mips32; mips32->common_magic = MIPS32_COMMON_MAGIC; mips32->fast_data_area = NULL; + mips32->isa_imp = MIPS32_ONLY; /* default */ /* has breakpoint/watchpoint unit been scanned */ mips32->bp_scanned = 0; @@ -385,16 +384,18 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s mips32->ejtag_info.tap = tap; mips32->read_core_reg = mips32_read_core_reg; mips32->write_core_reg = mips32_write_core_reg; - - mips32->ejtag_info.scan_delay = 2000000; /* Initial default value */ + /* if unknown endianness defaults to little endian, 1 */ + mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1; + mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; mips32->ejtag_info.mode = 0; /* Initial default value */ - + mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */ + mips32->ejtag_info.config_regs = 0; /* no config register read */ return ERROR_OK; } /* run to exit point. return error if exit point was not reached. */ -static int mips32_run_and_wait(struct target *target, uint32_t entry_point, - int timeout_ms, uint32_t exit_point, struct mips32_common *mips32) +static int mips32_run_and_wait(struct target *target, target_addr_t entry_point, + int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32) { uint32_t pc; int retval; @@ -427,8 +428,8 @@ static int mips32_run_and_wait(struct target *target, uint32_t entry_point, int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_params, uint32_t entry_point, - uint32_t exit_point, int timeout_ms, void *arch_info) + struct reg_param *reg_params, target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info) { struct mips32_common *mips32 = target_to_mips32(target); struct mips32_algorithm *mips32_algorithm_info = arch_info; @@ -698,57 +699,109 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } -int mips32_checksum_memory(struct target *target, uint32_t address, +/* read config to config3 cp0 registers and log isa implementation */ +int mips32_read_config_regs(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + if (ejtag_info->config_regs == 0) + for (int i = 0; i != 4; i++) { + int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i); + if (retval != ERROR_OK) { + LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i); + ejtag_info->config_regs = 0; + return retval; + } + ejtag_info->config_regs = i + 1; + if ((ejtag_info->config[i] & (1 << 31)) == 0) + break; /* no more config registers implemented */ + } + else + return ERROR_OK; /* already succesfully read */ + + LOG_DEBUG("read %"PRId32" config registers", ejtag_info->config_regs); + + if (ejtag_info->impcode & EJTAG_IMP_MIPS16) { + mips32->isa_imp = MIPS32_MIPS16; + LOG_USER("MIPS32 with MIPS16 support implemented"); + + } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */ + unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; + if (isa_imp == 1) { + mips32->isa_imp = MMIPS32_ONLY; + LOG_USER("MICRO MIPS32 only implemented"); + + } else if (isa_imp != 0) { + mips32->isa_imp = MIPS32_MMIPS32; + LOG_USER("MIPS32 and MICRO MIPS32 implemented"); + } + } + + if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */ + LOG_USER("MIPS32 only implemented"); + + return ERROR_OK; +} +int mips32_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct reg_param reg_params[2]; struct mips32_algorithm mips32_info; - /* see contrib/loaders/checksum/mips32.s for src */ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - static const uint32_t mips_crc_code[] = { - 0x248C0000, /* addiu $t4, $a0, 0 */ - 0x24AA0000, /* addiu $t2, $a1, 0 */ - 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */ - 0x10000010, /* beq $zero, $zero, ncomp */ - 0x240B0000, /* addiu $t3, $zero, 0 */ + /* see contrib/loaders/checksum/mips32.s for src */ + uint32_t isa = ejtag_info->isa ? 1 : 0; + + uint32_t mips_crc_code[] = { + MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */ + MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */ + MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */ + MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */ + MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */ /* nbyte: */ - 0x81850000, /* lb $a1, ($t4) */ - 0x218C0001, /* addi $t4, $t4, 1 */ - 0x00052E00, /* sll $a1, $a1, 24 */ - 0x3C0204C1, /* lui $v0, 0x04c1 */ - 0x00852026, /* xor $a0, $a0, $a1 */ - 0x34471DB7, /* ori $a3, $v0, 0x1db7 */ - 0x00003021, /* addu $a2, $zero, $zero */ - /* loop: */ - 0x00044040, /* sll $t0, $a0, 1 */ - 0x24C60001, /* addiu $a2, $a2, 1 */ - 0x28840000, /* slti $a0, $a0, 0 */ - 0x01074826, /* xor $t1, $t0, $a3 */ - 0x0124400B, /* movn $t0, $t1, $a0 */ - 0x28C30008, /* slti $v1, $a2, 8 */ - 0x1460FFF9, /* bne $v1, $zero, loop */ - 0x01002021, /* addu $a0, $t0, $zero */ - /* ncomp: */ - 0x154BFFF0, /* bne $t2, $t3, nbyte */ - 0x256B0001, /* addiu $t3, $t3, 1 */ - 0x7000003F, /* sdbbp */ + MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */ + MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */ + MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */ + MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */ + MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */ + MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */ + MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */ + /* loop */ + MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */ + MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */ + MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */ + MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */ + MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */ + MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */ + MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */ + MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */ + /* ncomp */ + MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */ + MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */ + MIPS32_SDBBP(isa), }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code)); + /* convert mips crc code into a buffer in target endianness */ uint8_t mips_crc_code_8[sizeof(mips_crc_code)]; target_buffer_set_u32_array(target, mips_crc_code_8, ARRAY_SIZE(mips_crc_code), mips_crc_code); - target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8); + int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8); + if (retval != ERROR_OK) + return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; - mips32_info.isa_mode = MIPS32_ISA_MIPS32; + mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */ init_reg_param(®_params[0], "r4", 32, PARAM_IN_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); @@ -758,9 +811,8 @@ int mips32_checksum_memory(struct target *target, uint32_t address, int timeout = 20000 * (1 + (count / (1024 * 1024))); - int retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, - &mips32_info); + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, + crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); @@ -773,37 +825,51 @@ int mips32_checksum_memory(struct target *target, uint32_t address, return retval; } -/** Checks whether a memory region is zeroed. */ +/** Checks whether a memory region is erased. */ int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct mips32_algorithm mips32_info; - static const uint32_t erase_check_code[] = { + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + if (erased_value != 0xff) { + LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32", + erased_value); + return ERROR_FAIL; + } + uint32_t isa = ejtag_info->isa ? 1 : 0; + uint32_t erase_check_code[] = { /* nbyte: */ - 0x80880000, /* lb $t0, ($a0) */ - 0x00C83024, /* and $a2, $a2, $t0 */ - 0x24A5FFFF, /* addiu $a1, $a1, -1 */ - 0x14A0FFFC, /* bne $a1, $zero, nbyte */ - 0x24840001, /* addiu $a0, $a0, 1 */ - 0x7000003F /* sdbbp */ + MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */ + MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */ + MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */ + MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */ + MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */ + MIPS32_SDBBP(isa) /* sdbbp */ }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code)); + /* convert erase check code into a buffer in target endianness */ uint8_t erase_check_code_8[sizeof(erase_check_code)]; target_buffer_set_u32_array(target, erase_check_code_8, ARRAY_SIZE(erase_check_code), erase_check_code); - target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), erase_check_code_8); + int retval = target_write_buffer(target, erase_check_algorithm->address, + sizeof(erase_check_code), erase_check_code_8); + if (retval != ERROR_OK) + return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; - mips32_info.isa_mode = MIPS32_ISA_MIPS32; + mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; init_reg_param(®_params[0], "r4", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); @@ -812,12 +878,10 @@ int mips32_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); - int retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 4), - 10000, &mips32_info); + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, + erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info); if (retval == ERROR_OK) *blank = buf_get_u32(reg_params[2].value, 0, 32); @@ -913,7 +977,7 @@ COMMAND_HANDLER(mips32_handle_scan_delay_command) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); - if (ejtag_info->scan_delay >= 2000000) { + if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { diff --git a/src/target/mips32.h b/src/target/mips32.h index 56f4fb4e1..928598f4c 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -18,13 +18,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MIPS32_H -#define MIPS32_H +#ifndef OPENOCD_TARGET_MIPS32_H +#define OPENOCD_TARGET_MIPS32_H #include "target.h" #include "mips32_pracc.h" @@ -60,9 +58,14 @@ #define MIPS32_CONFIG1_DL_SHIFT 10 #define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT) +#define MIPS32_CONFIG3_ISA_SHIFT 14 +#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT) + #define MIPS32_ARCH_REL1 0x0 #define MIPS32_ARCH_REL2 0x1 +#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 + /* offsets into mips32 core register cache */ enum { MIPS32_PC = 37, @@ -73,6 +76,14 @@ enum { enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, + MIPS32_ISA_MMIPS32 = 3, +}; + +enum mips32_isa_imp { + MIPS32_ONLY = 0, + MMIPS32_ONLY = 1, + MIPS32_MIPS16 = 2, + MIPS32_MMIPS32 = 3, }; struct mips32_comparator { @@ -88,6 +99,7 @@ struct mips32_common { struct mips_ejtag ejtag_info; uint32_t core_regs[MIPS32NUMCOREREGS]; enum mips32_isa_mode isa_mode; + enum mips32_isa_imp isa_imp; /* working area for fastdata access */ struct working_area *fast_data_area; @@ -122,44 +134,49 @@ struct mips32_algorithm { enum mips32_isa_mode isa_mode; }; -#define MIPS32_OP_ADDIU 0x21 -#define MIPS32_OP_ANDI 0x0C -#define MIPS32_OP_BEQ 0x04 -#define MIPS32_OP_BGTZ 0x07 -#define MIPS32_OP_BNE 0x05 -#define MIPS32_OP_ADDI 0x08 -#define MIPS32_OP_AND 0x24 -#define MIPS32_OP_CACHE 0x2F -#define MIPS32_OP_COP0 0x10 -#define MIPS32_OP_J 0x02 -#define MIPS32_OP_JR 0x08 -#define MIPS32_OP_LUI 0x0F -#define MIPS32_OP_LW 0x23 -#define MIPS32_OP_LBU 0x24 -#define MIPS32_OP_LHU 0x25 -#define MIPS32_OP_MFHI 0x10 -#define MIPS32_OP_MTHI 0x11 -#define MIPS32_OP_MFLO 0x12 -#define MIPS32_OP_MTLO 0x13 -#define MIPS32_OP_RDHWR 0x3B -#define MIPS32_OP_SB 0x28 -#define MIPS32_OP_SH 0x29 -#define MIPS32_OP_SW 0x2B -#define MIPS32_OP_ORI 0x0D -#define MIPS32_OP_XORI 0x0E -#define MIPS32_OP_XOR 0x26 -#define MIPS32_OP_SLTU 0x2B -#define MIPS32_OP_SRL 0x03 -#define MIPS32_OP_SYNCI 0x1F - -#define MIPS32_OP_REGIMM 0x01 -#define MIPS32_OP_SDBBP 0x3F -#define MIPS32_OP_SPECIAL 0x00 -#define MIPS32_OP_SPECIAL2 0x07 -#define MIPS32_OP_SPECIAL3 0x1F - -#define MIPS32_COP0_MF 0x00 -#define MIPS32_COP0_MT 0x04 +#define MIPS32_OP_ADDU 0x21u +#define MIPS32_OP_ADDIU 0x09u +#define MIPS32_OP_ANDI 0x0Cu +#define MIPS32_OP_BEQ 0x04u +#define MIPS32_OP_BGTZ 0x07u +#define MIPS32_OP_BNE 0x05u +#define MIPS32_OP_ADDI 0x08u +#define MIPS32_OP_AND 0x24u +#define MIPS32_OP_CACHE 0x2Fu +#define MIPS32_OP_COP0 0x10u +#define MIPS32_OP_J 0x02u +#define MIPS32_OP_JR 0x08u +#define MIPS32_OP_LUI 0x0Fu +#define MIPS32_OP_LW 0x23u +#define MIPS32_OP_LB 0x20u +#define MIPS32_OP_LBU 0x24u +#define MIPS32_OP_LHU 0x25u +#define MIPS32_OP_MFHI 0x10u +#define MIPS32_OP_MTHI 0x11u +#define MIPS32_OP_MFLO 0x12u +#define MIPS32_OP_MTLO 0x13u +#define MIPS32_OP_RDHWR 0x3Bu +#define MIPS32_OP_SB 0x28u +#define MIPS32_OP_SH 0x29u +#define MIPS32_OP_SW 0x2Bu +#define MIPS32_OP_ORI 0x0Du +#define MIPS32_OP_XORI 0x0Eu +#define MIPS32_OP_XOR 0x26u +#define MIPS32_OP_SLTU 0x2Bu +#define MIPS32_OP_SRL 0x03u +#define MIPS32_OP_SYNCI 0x1Fu +#define MIPS32_OP_SLL 0x00u +#define MIPS32_OP_SLTI 0x0Au +#define MIPS32_OP_MOVN 0x0Bu + +#define MIPS32_OP_REGIMM 0x01u +#define MIPS32_OP_SDBBP 0x3Fu +#define MIPS32_OP_SPECIAL 0x00u +#define MIPS32_OP_SPECIAL2 0x07u +#define MIPS32_OP_SPECIAL3 0x1Fu + +#define MIPS32_COP0_MF 0x00u +#define MIPS32_COP0_MT 0x04u #define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct)) @@ -167,41 +184,52 @@ struct mips32_algorithm { (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd)) #define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr)) -#define MIPS32_NOP 0 -#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) -#define MIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDIU) -#define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND) -#define MIPS32_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) -#define MIPS32_B(off) MIPS32_BEQ(0, 0, off) -#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) -#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) -#define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) -#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) -#define MIPS32_J(tar) MIPS32_J_INST(MIPS32_OP_J, tar) -#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) -#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) -#define MIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) -#define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) -#define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) -#define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) -#define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) -#define MIPS32_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) -#define MIPS32_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) -#define MIPS32_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) -#define MIPS32_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) -#define MIPS32_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) -#define MIPS32_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) -#define MIPS32_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) -#define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) -#define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) -#define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) -#define MIPS32_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) -#define MIPS32_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) -#define MIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) -#define MIPS32_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) - -#define MIPS32_SYNC 0xF -#define MIPS32_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ +#define MIPS32_ISA_NOP 0 +#define MIPS32_ISA_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) +#define MIPS32_ISA_ADDIU(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDIU, src, tar, val) +#define MIPS32_ISA_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDU) +#define MIPS32_ISA_AND(dst, src, tar) MIPS32_R_INST(0, src, tar, dst, 0, MIPS32_OP_AND) +#define MIPS32_ISA_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) + +#define MIPS32_ISA_B(off) MIPS32_ISA_BEQ(0, 0, off) +#define MIPS32_ISA_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) +#define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) +#define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) +#define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) +#define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) +#define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) + +#define MIPS32_ISA_LB(reg, off, base) MIPS32_I_INST(MIPS32_OP_LB, base, reg, off) +#define MIPS32_ISA_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) +#define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) +#define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) +#define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) + +#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) +#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) +#define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) +#define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) +#define MIPS32_ISA_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) + +#define MIPS32_ISA_MOVN(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_MOVN) +#define MIPS32_ISA_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) +#define MIPS32_ISA_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) +#define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) +#define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) +#define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) + +#define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) +#define MIPS32_ISA_SLTI(tar, src, val) MIPS32_I_INST(MIPS32_OP_SLTI, src, tar, val) +#define MIPS32_ISA_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) +#define MIPS32_ISA_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) +#define MIPS32_ISA_SYNC 0xFu +#define MIPS32_ISA_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) + +#define MIPS32_ISA_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) +#define MIPS32_ISA_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) + +#define MIPS32_ISA_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ /** * Cache operations definitions @@ -213,9 +241,158 @@ struct mips32_algorithm { #define MIPS32_CACHE_I_HIT_INVALIDATE ((0x0 << 0) | (0x4 << 2)) /* ejtag specific instructions */ -#define MIPS32_DRET 0x4200001F -#define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */ -#define MIPS16_SDBBP 0xE801 +#define MIPS32_ISA_DRET 0x4200001Fu +/* MIPS32_ISA_J_INST(MIPS32_ISA_OP_SPECIAL2, MIPS32_ISA_OP_SDBBP) */ +#define MIPS32_ISA_SDBBP 0x7000003Fu +#define MIPS16_ISA_SDBBP 0xE801u + +/*MICRO MIPS INSTRUCTIONS, see doc MD00582 */ +#define POOL32A 0X00u +#define POOL32AXf 0x3Cu +#define POOL32B 0x08u +#define POOL32I 0x10u +#define MMIPS32_OP_ADDI 0x04u +#define MMIPS32_OP_ADDIU 0x0Cu +#define MMIPS32_OP_ADDU 0x150u +#define MMIPS32_OP_AND 0x250u +#define MMIPS32_OP_ANDI 0x34u +#define MMIPS32_OP_BEQ 0x25u +#define MMIPS32_OP_BGTZ 0x06u +#define MMIPS32_OP_BNE 0x2Du +#define MMIPS32_OP_CACHE 0x06u +#define MMIPS32_OP_J 0x35u +#define MMIPS32_OP_JALR 0x03Cu +#define MMIPS32_OP_LB 0x07u +#define MMIPS32_OP_LBU 0x05u +#define MMIPS32_OP_LHU 0x0Du +#define MMIPS32_OP_LUI 0x0Du +#define MMIPS32_OP_LW 0x3Fu +#define MMIPS32_OP_MFC0 0x03u +#define MMIPS32_OP_MTC0 0x0Bu +#define MMIPS32_OP_MFLO 0x075u +#define MMIPS32_OP_MFHI 0x035u +#define MMIPS32_OP_MTLO 0x0F5u +#define MMIPS32_OP_MTHI 0x0B5u +#define MMIPS32_OP_MOVN 0x018u +#define MMIPS32_OP_ORI 0x14u +#define MMIPS32_OP_RDHWR 0x1ACu +#define MMIPS32_OP_SB 0x06u +#define MMIPS32_OP_SH 0x0Eu +#define MMIPS32_OP_SW 0x3Eu +#define MMIPS32_OP_SLTU 0x390u +#define MMIPS32_OP_SLL 0x000u +#define MMIPS32_OP_SLTI 0x24u +#define MMIPS32_OP_SRL 0x040u +#define MMIPS32_OP_SYNCI 0x10u +#define MMIPS32_OP_XOR 0x310u +#define MMIPS32_OP_XORI 0x1Cu + +#define MMIPS32_ADDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDI, tar, src, val) +#define MMIPS32_ADDIU(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDIU, tar, src, val) +#define MMIPS32_ADDU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_ADDU) +#define MMIPS32_AND(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_AND) +#define MMIPS32_ANDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ANDI, tar, src, val) + +#define MMIPS32_B(off) MMIPS32_BEQ(0, 0, off) +#define MMIPS32_BEQ(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BEQ, tar, src, off) +#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(POOL32I, MMIPS32_OP_BGTZ, reg, off) +#define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) +#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) + +#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) +#define MMIPS32_JR(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_JALR, POOL32AXf) +#define MMIPS32_LB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LB, reg, base, off) +#define MMIPS32_LBU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LBU, reg, base, off) +#define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) +#define MMIPS32_LUI(reg, val) MIPS32_I_INST(POOL32I, MMIPS32_OP_LUI, reg, val) +#define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) + +#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MFC0, POOL32AXf) +#define MMIPS32_MFLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, POOL32AXf) +#define MMIPS32_MFHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, POOL32AXf) +#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MTC0, POOL32AXf) +#define MMIPS32_MTLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, POOL32AXf) +#define MMIPS32_MTHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, POOL32AXf) + +#define MMIPS32_MOVN(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_MOVN) +#define MMIPS32_NOP 0 +#define MMIPS32_ORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ORI, tar, src, val) +#define MMIPS32_RDHWR(tar, dst) MIPS32_R_INST(POOL32A, dst, tar, 0, MMIPS32_OP_RDHWR, POOL32AXf) +#define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) +#define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) +#define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) + +#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) +#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) +#define MMIPS32_SYNCI(off, base) MIPS32_I_INST(POOL32I, MMIPS32_OP_SYNCI, base, off) +#define MMIPS32_SLL(dst, src, sa) MIPS32_R_INST(POOL32A, dst, src, sa, 0, MMIPS32_OP_SLL) +#define MMIPS32_SLTI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_SLTI, tar, src, val) +#define MMIPS32_SYNC 0x00001A7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1ADu, POOL32AXf) */ + +#define MMIPS32_XOR(reg, val1, val2) MIPS32_R_INST(POOL32A, val1, val2, reg, 0, MMIPS32_OP_XOR) +#define MMIPS32_XORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_XORI, tar, src, val) + +#define MMIPS32_SYNCI_STEP 0x1u /* reg num od address step size to be used with synci instruction */ + + +/* ejtag specific instructions */ +#define MMIPS32_DRET 0x0000E37Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x38D, POOL32AXf) */ +#define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1BD, POOL32AXf) */ +#define MMIPS16_SDBBP 0x46C0u /* POOL16C instr */ + +/* instruction code with isa selection */ +#define MIPS32_NOP 0 /* same for both isa's */ +#define MIPS32_ADDI(isa, tar, src, val) (isa ? MMIPS32_ADDI(tar, src, val) : MIPS32_ISA_ADDI(tar, src, val)) +#define MIPS32_ADDIU(isa, tar, src, val) (isa ? MMIPS32_ADDIU(tar, src, val) : MIPS32_ISA_ADDIU(tar, src, val)) +#define MIPS32_ADDU(isa, dst, src, tar) (isa ? MMIPS32_ADDU(dst, src, tar) : MIPS32_ISA_ADDU(dst, src, tar)) +#define MIPS32_AND(isa, dst, src, tar) (isa ? MMIPS32_AND(dst, src, tar) : MIPS32_ISA_AND(dst, src, tar)) +#define MIPS32_ANDI(isa, tar, src, val) (isa ? MMIPS32_ANDI(tar, src, val) : MIPS32_ISA_ANDI(tar, src, val)) + +#define MIPS32_B(isa, off) (isa ? MMIPS32_B(off) : MIPS32_ISA_B(off)) +#define MIPS32_BEQ(isa, src, tar, off) (isa ? MMIPS32_BEQ(src, tar, off) : MIPS32_ISA_BEQ(src, tar, off)) +#define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) +#define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) +#define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) + +#define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) +#define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) +#define MIPS32_LB(isa, reg, off, base) (isa ? MMIPS32_LB(reg, off, base) : MIPS32_ISA_LB(reg, off, base)) +#define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) +#define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) +#define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) +#define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) + +#define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) +#define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) +#define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) +#define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) +#define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) +#define MIPS32_MTHI(isa, reg) (isa ? MMIPS32_MTHI(reg) : MIPS32_ISA_MTHI(reg)) + +#define MIPS32_MOVN(isa, dst, src, tar) (isa ? MMIPS32_MOVN(dst, src, tar) : MIPS32_ISA_MOVN(dst, src, tar)) +#define MIPS32_ORI(isa, tar, src, val) (isa ? MMIPS32_ORI(tar, src, val) : MIPS32_ISA_ORI(tar, src, val)) +#define MIPS32_RDHWR(isa, tar, dst) (isa ? MMIPS32_RDHWR(tar, dst) : MIPS32_ISA_RDHWR(tar, dst)) +#define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) +#define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) +#define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) + +#define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) +#define MIPS32_SLTI(isa, tar, src, val) (isa ? MMIPS32_SLTI(tar, src, val) : MIPS32_ISA_SLTI(tar, src, val)) +#define MIPS32_SLTU(isa, dst, src, tar) (isa ? MMIPS32_SLTU(dst, src, tar) : MIPS32_ISA_SLTU(dst, src, tar)) +#define MIPS32_SRL(isa, reg, src, off) (isa ? MMIPS32_SRL(reg, src, off) : MIPS32_ISA_SRL(reg, src, off)) + +#define MIPS32_SYNCI(isa, off, base) (isa ? MMIPS32_SYNCI(off, base) : MIPS32_ISA_SYNCI(off, base)) +#define MIPS32_SYNC(isa) (isa ? MMIPS32_SYNC : MIPS32_ISA_SYNC) +#define MIPS32_XOR(isa, reg, val1, val2) (isa ? MMIPS32_XOR(reg, val1, val2) : MIPS32_ISA_XOR(reg, val1, val2)) +#define MIPS32_XORI(isa, tar, src, val) (isa ? MMIPS32_XORI(tar, src, val) : MIPS32_ISA_XORI(tar, src, val)) + +#define MIPS32_SYNCI_STEP 0x1 + +/* ejtag specific instructions */ +#define MIPS32_DRET(isa) (isa ? MMIPS32_DRET : MIPS32_ISA_DRET) +#define MIPS32_SDBBP(isa) (isa ? MMIPS32_SDBBP : MIPS32_ISA_SDBBP) + +#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP) extern const struct command_registration mips32_command_handlers[]; @@ -232,7 +409,7 @@ struct reg_cache *mips32_build_reg_cache(struct target *target); int mips32_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info); int mips32_configure_break_unit(struct target *target); @@ -241,14 +418,16 @@ int mips32_enable_interrupts(struct target *target, int enable); int mips32_examine(struct target *target); +int mips32_read_config_regs(struct target *target); + int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); -int mips32_checksum_memory(struct target *target, uint32_t address, +int mips32_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum); int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); -#endif /*MIPS32_H*/ +#endif /* OPENOCD_TARGET_MIPS32_H */ diff --git a/src/target/mips32_dmaacc.c b/src/target/mips32_dmaacc.c index c2fea21dd..220ea94f9 100644 --- a/src/target/mips32_dmaacc.c +++ b/src/target/mips32_dmaacc.c @@ -18,9 +18,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/mips32_dmaacc.h b/src/target/mips32_dmaacc.h index 45d5b3614..70fe2a77e 100644 --- a/src/target/mips32_dmaacc.h +++ b/src/target/mips32_dmaacc.h @@ -18,13 +18,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MIPS32_DMAACC_H -#define MIPS32_DMAACC_H +#ifndef OPENOCD_TARGET_MIPS32_DMAACC_H +#define OPENOCD_TARGET_MIPS32_DMAACC_H #include "mips_ejtag.h" @@ -40,4 +38,4 @@ int mips32_dmaacc_read_mem(struct mips_ejtag *ejtag_info, int mips32_dmaacc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf); -#endif +#endif /* OPENOCD_TARGET_MIPS32_DMAACC_H */ diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index e97626cb2..790c8dc93 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -20,9 +20,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* @@ -75,77 +73,61 @@ #include "mips32.h" #include "mips32_pracc.h" -struct mips32_pracc_context { - uint32_t *local_oparam; - int num_oparam; - const uint32_t *code; - int code_len; - uint32_t stack[32]; - int stack_offset; - struct mips_ejtag *ejtag_info; -}; - -static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) +static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info) { - uint32_t ejtag_ctrl; - long long then = timeval_ms(); + int64_t then = timeval_ms(); /* wait for the PrAcc to become "1" */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); while (1) { - ejtag_ctrl = ejtag_info->ejtag_ctrl; - int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); + ejtag_info->pa_ctrl = ejtag_info->ejtag_ctrl; + int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_ctrl); if (retval != ERROR_OK) return retval; - if (ejtag_ctrl & EJTAG_CTRL_PRACC) + if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRACC) break; - int timeout = timeval_ms() - then; + int64_t timeout = timeval_ms() - then; if (timeout > 1000) { LOG_DEBUG("DEBUGMODULE: No memory access in progress!"); return ERROR_JTAG_DEVICE_ERROR; } } - *ctrl = ejtag_ctrl; return ERROR_OK; } /* Shift in control and address for a new processor access, save them in ejtag_info */ static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info) { - int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - ejtag_info->pa_addr = 0; - retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr); - return retval; + ejtag_info->pa_addr = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr); } /* Finish processor access */ -static int mips32_pracc_finish(struct mips_ejtag *ejtag_info) +static void mips32_pracc_finish(struct mips_ejtag *ejtag_info) { uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ctrl); - - return jtag_execute_queue(); } int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) { - uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2); - int retval; - + uint32_t jt_code = MIPS32_J(ejtag_info->isa, MIPS32_PRACC_TEXT); + pracc_swap16_array(ejtag_info, &jt_code, 1); /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */ for (int i = 0; i != 5; i++) { /* Wait for pracc */ - retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -155,33 +137,33 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) mips_ejtag_drscan_32_out(ejtag_info, data); /* finish pa */ - retval = mips32_pracc_finish(ejtag_info); - if (retval != ERROR_OK) - return retval; + mips32_pracc_finish(ejtag_info); } - if (ejtag_info->mode != 0) /* done, queued mode won't work with lexra cores */ + if (ejtag_info->mode != 0) /* async mode support only for MIPS ... */ return ERROR_OK; - retval = mips32_pracc_read_ctrl_addr(ejtag_info); - if (retval != ERROR_OK) - return retval; - - if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP */ - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); - mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP); - retval = mips32_pracc_finish(ejtag_info); + for (int i = 0; i != 2; i++) { + int retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; + + if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */ + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); + mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP); + mips32_pracc_finish(ejtag_info); + } else + break; } return ERROR_OK; } -int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out) +int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *param_out, bool check_last) { int code_count = 0; - int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */ + int store_pending = 0; /* increases with every store instr at dmseg, decreases with every store pa */ uint32_t max_store_addr = 0; /* for store pa address testing */ bool restart = 0; /* restarting control */ int restart_count = 0; @@ -204,12 +186,12 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct LOG_DEBUG("restarting code"); } - retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */ + retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */ if (retval != ERROR_OK) return retval; /* Check for read or write access */ - if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */ + if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */ /* Check for pending store from a previous store instruction at dmseg */ if (store_pending == 0) { LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr); @@ -220,8 +202,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct return ERROR_JTAG_DEVICE_ERROR; } else { /* check address */ - if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) { - + if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || + ejtag_info->pa_addr > max_store_addr) { LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr); return ERROR_JTAG_DEVICE_ERROR; } @@ -245,7 +227,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); /* restart code execution only in some cases */ - if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) { + if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && + restart_count == 0) { LOG_DEBUG("restarting, without clean jump"); restart_count++; code_count = 0; @@ -254,18 +237,17 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct restart = 1; continue; } - return ERROR_JTAG_DEVICE_ERROR; } /* check for store instruction at dmseg */ - uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count]; + uint32_t store_addr = ctx->pracc_list[code_count].addr; if (store_addr != 0) { if (store_addr > max_store_addr) max_store_addr = store_addr; store_pending++; } - instr = ctx->pracc_list[code_count++]; + instr = ctx->pracc_list[code_count++].instr; if (code_count == ctx->code_count) /* last instruction, start final check */ final_check = 1; @@ -283,13 +265,14 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct } } else { if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { - LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x", - ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); + LOG_DEBUG("unexpected read address in final check: %" + PRIx32 ", expected: %x", ejtag_info->pa_addr, + MIPS32_PRACC_TEXT + code_count * 4); return ERROR_JTAG_DEVICE_ERROR; } } if (!pass) { - if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */ + if ((code_count - ctx->code_count) > 1) { /* allow max 2 instr delay slot */ LOG_DEBUG("failed to jump back to pracc text"); return ERROR_JTAG_DEVICE_ERROR; } @@ -307,12 +290,10 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct mips_ejtag_drscan_32_out(ejtag_info, instr); } /* finish processor access, let the processor eat! */ - retval = mips32_pracc_finish(ejtag_info); - if (retval != ERROR_OK) - return retval; + mips32_pracc_finish(ejtag_info); - if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */ - return ERROR_OK; + if (final_check && !check_last) /* last instr, don't check, execute and exit */ + return jtag_execute_queue(); if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */ LOG_DEBUG("warning: store access pass pracc text"); @@ -326,34 +307,63 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) ctx->retval = ERROR_OK; ctx->code_count = 0; ctx->store_count = 0; - - ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t)); - if (ctx->pracc_list == NULL) { - LOG_ERROR("Out of memory"); - ctx->retval = ERROR_FAIL; - } + ctx->max_code = 0; + ctx->pracc_list = NULL; + ctx->isa = ctx->ejtag_info->isa ? 1 : 0; } -inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) +void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) { - ctx->pracc_list[ctx->max_code + ctx->code_count] = addr; - ctx->pracc_list[ctx->code_count++] = instr; + if (ctx->retval != ERROR_OK) /* On previous out of memory, return */ + return; + if (ctx->code_count == ctx->max_code) { + void *p = realloc(ctx->pracc_list, sizeof(pa_list) * (ctx->max_code + PRACC_BLOCK)); + if (p) { + ctx->max_code += PRACC_BLOCK; + ctx->pracc_list = p; + } else { + ctx->retval = ERROR_FAIL; /* Out of memory */ + return; + } + } + ctx->pracc_list[ctx->code_count].instr = instr; + ctx->pracc_list[ctx->code_count++].addr = addr; if (addr) ctx->store_count++; } +void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize) +{ + if (LOWER16(data) == 0 && optimize) + pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load only upper value */ + else if (UPPER16(data) == 0 && optimize) + pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, 0, LOWER16(data))); /* load only lower */ + else { + pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load upper and lower */ + pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, reg_num, LOWER16(data))); + } +} + inline void pracc_queue_free(struct pracc_queue_info *ctx) { - if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */ - LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code); if (ctx->pracc_list != NULL) free(ctx->pracc_list); } -int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf) +int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *buf, bool check_last) { + if (ctx->retval != ERROR_OK) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + if (ejtag_info->isa && ejtag_info->endianness) + for (int i = 0; i != ctx->code_count; i++) + ctx->pracc_list[i].instr = SWAP16(ctx->pracc_list[i].instr); + if (ejtag_info->mode == 0) - return mips32_pracc_exec(ejtag_info, ctx, buf); + return mips32_pracc_exec(ejtag_info, ctx, buf, check_last); union scan_in { uint8_t scan_96[12]; @@ -376,16 +386,16 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); int scan_count = 0; - for (int i = 0; i != 2 * ctx->code_count; i++) { - uint32_t data = 0; - if (i & 1u) { /* Check store address from previous instruction, if not the first */ - if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1]) - continue; - } else - data = ctx->pracc_list[i / 2]; - + for (int i = 0; i != ctx->code_count; i++) { jtag_add_clocks(num_clocks); - mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96); + mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, ctx->pracc_list[i].instr, + scan_in[scan_count++].scan_96); + + /* Check store address from previous instruction, if not the first */ + if (i > 0 && ctx->pracc_list[i - 1].addr) { + jtag_add_clocks(num_clocks); + mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, 0, scan_in[scan_count++].scan_96); + } } int retval = jtag_execute_queue(); /* execute queued scans */ @@ -394,24 +404,35 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */ scan_count = 0; - for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */ - uint32_t store_addr = 0; - if (i & 1u) { /* Read store addres from previous instruction, if not the first */ - store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1]; - if (i < 2 || 0 == store_addr) - continue; - } - + for (int i = 0; i != ctx->code_count; i++) { /* verify every pracc access */ + /* check pracc bit */ ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); + uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) { LOG_ERROR("Error: access not pending count: %d", scan_count); retval = ERROR_FAIL; goto exit; } + if (ejtag_ctrl & EJTAG_CTRL_PRNW) { + LOG_ERROR("Not a fetch/read access, count: %d", scan_count); + retval = ERROR_FAIL; + goto exit; + } + if (addr != fetch_addr) { + LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", + addr, fetch_addr, scan_count); + retval = ERROR_FAIL; + goto exit; + } + fetch_addr += 4; + scan_count++; - uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); + /* check if previous intrucction is a store instruction at dmesg */ + if (i > 0 && ctx->pracc_list[i - 1].addr) { + uint32_t store_addr = ctx->pracc_list[i - 1].addr; + ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); + addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); - if (store_addr != 0) { if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) { LOG_ERROR("Not a store/write access, count: %d", scan_count); retval = ERROR_FAIL; @@ -419,28 +440,14 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in } if (addr != store_addr) { LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", - addr, store_addr, scan_count); + addr, store_addr, scan_count); retval = ERROR_FAIL; goto exit; } int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4; buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32); - - } else { - if (ejtag_ctrl & EJTAG_CTRL_PRNW) { - LOG_ERROR("Not a fetch/read access, count: %d", scan_count); - retval = ERROR_FAIL; - goto exit; - } - if (addr != fetch_addr) { - LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", - addr, fetch_addr, scan_count); - retval = ERROR_FAIL; - goto exit; - } - fetch_addr += 4; + scan_count++; } - scan_count++; } exit: free(scan_in); @@ -449,23 +456,19 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) { - struct pracc_queue_info ctx = {.max_code = 8}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */ - pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper addr */ + pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* move COP0 DeSave to $15 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf); -exit: + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -475,12 +478,10 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size if (count == 1 && size == 4) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf); - uint32_t *data = NULL; - struct pracc_queue_info ctx = {.max_code = 256 * 3 + 8 + 1}; /* alloc memory for the worst case */ + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; + uint32_t *data = NULL; if (size != 4) { data = malloc(256 * sizeof(uint32_t)); if (data == NULL) { @@ -496,45 +497,44 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size while (count) { ctx.code_count = 0; ctx.store_count = 0; + int this_round_count = (count > 256) ? 256 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, last_upper_base_addr)); /* upper memory addr to $9 */ for (int i = 0; i != this_round_count; i++) { /* Main code loop */ uint32_t upper_base_addr = UPPER16((addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */ - pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr)); + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, upper_base_addr)); last_upper_base_addr = upper_base_addr; } - if (size == 4) - pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */ + if (size == 4) /* load from memory to $8 */ + pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 9)); else if (size == 2) - pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9)); + pracc_add(&ctx, 0, MIPS32_LHU(ctx.isa, 8, LOWER16(addr), 9)); else - pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9)); + pracc_add(&ctx, 0, MIPS32_LBU(ctx.isa, 8, LOWER16(addr), 9)); - pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, - MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, /* store $8 at param out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + i * 4, 15)); addr += size; } - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 bits of reg 9 */ - pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 bits of reg 9 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ + pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ if (size == 4) { - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1); if (ctx.retval != ERROR_OK) goto exit; buf32 += this_round_count; } else { - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data, 1); if (ctx.retval != ERROR_OK) goto exit; @@ -557,68 +557,37 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx = {.max_code = 7}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg << 11) | cp0_sel); /* move COP0 [cp0_reg select] to $8 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val); -exit: + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); pracc_queue_free(&ctx); return ctx.retval; - - /** - * Note that our input parametes cp0_reg and cp0_sel - * are numbers (not gprs) which make part of mfc0 instruction opcode. - * - * These are not fix, but can be different for each mips32_cp0_read() function call, - * and that is why we must insert them directly into opcode, - * i.e. we can not pass it on EJTAG microprogram stack (via param_in), - * and put them into the gprs later from MIPS32_PRACC_STACK - * because mfc0 do not use gpr as a parameter for the cp0_reg and select part, - * but plain (immediate) number. - * - * MIPS32_MTC0 is implemented via MIPS32_R_INST macro. - * In order to insert our parameters, we must change rd and funct fields. - * - * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro - **/ } int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx = {.max_code = 6}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */ - pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val))); + pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ - pracc_add(&ctx, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg << 11) | cp0_sel); /* write cp0 reg / sel */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ - - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -exit: + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); return ctx.retval; - - /** - * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro. - * In order to insert our parameters, we must change rd and funct fields. - * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro - **/ } /** @@ -651,26 +620,25 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr, int cached, int rel) { - struct pracc_queue_info ctx = {.max_code = 256 * 2 + 5}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; + /** Find cache line size in bytes */ uint32_t clsiz; if (rel) { /* Release 2 (rel = 1) */ - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ + pracc_add(&ctx, 0, MIPS32_RDHWR(ctx.isa, 8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz); + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1); if (ctx.retval != ERROR_OK) goto exit; @@ -703,47 +671,50 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, end_addr |= clsiz - 1; ctx.code_count = 0; + ctx.store_count = 0; + int count = 0; uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000)); - pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load upper memory base address to $15 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); /* load upper memory base addr to $15 */ while (start_addr <= end_addr) { /* main loop */ uint32_t upper_base_addr = UPPER16((start_addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15 */ - pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $15 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr)); last_upper_base_addr = upper_base_addr; } - if (rel) - pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15)); /* synci instruction, offset($15) */ + if (rel) /* synci instruction, offset($15) */ + pracc_add(&ctx, 0, MIPS32_SYNCI(ctx.isa, LOWER16(start_addr), 15)); else { - if (cached == 3) - pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, - LOWER16(start_addr), 15)); /* cache Hit_Writeback_D, offset($15) */ - - pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, - LOWER16(start_addr), 15)); /* cache Hit_Invalidate_I, offset($15) */ + if (cached == 3) /* cache Hit_Writeback_D, offset($15) */ + pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_D_HIT_WRITEBACK, + LOWER16(start_addr), 15)); + /* cache Hit_Invalidate_I, offset($15) */ + pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_I_HIT_INVALIDATE, + LOWER16(start_addr), 15)); } start_addr += clsiz; count++; - if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ + if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* to start */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) goto exit; - ctx.code_count = 0; + ctx.code_count = 0; /* reset counters for another loop */ + ctx.store_count = 0; count = 0; } } - pracc_add(&ctx, 0, MIPS32_SYNC); - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/ + pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa)); + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave*/ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); exit: pracc_queue_free(&ctx); return ctx.retval; @@ -752,10 +723,8 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { - struct pracc_queue_info ctx = {.max_code = 128 * 3 + 5 + 1}; /* alloc memory for the worst case */ + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; const uint32_t *buf32 = buf; const uint16_t *buf16 = buf; @@ -764,50 +733,43 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, while (count) { ctx.code_count = 0; ctx.store_count = 0; + int this_round_count = (count > 128) ? 128 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); - - pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */ + /* load $15 with memory base address */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); for (int i = 0; i != this_round_count; i++) { uint32_t upper_base_addr = UPPER16((addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { - pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/ + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15*/ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr)); last_upper_base_addr = upper_base_addr; } - if (size == 4) { /* for word writes check if one half word is 0 and load it accordingly */ - if (LOWER16(*buf32) == 0) - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load only upper value */ - else if (UPPER16(*buf32) == 0) - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32))); /* load only lower */ - else { - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load upper and lower */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32))); - } - pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */ + if (size == 4) { + pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */ + pracc_add(&ctx, 0, MIPS32_SW(ctx.isa, 8, LOWER16(addr), 15)); /* store word to mem */ buf32++; } else if (size == 2) { - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */ - pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf16)); /* load lower value */ + pracc_add(&ctx, 0, MIPS32_SH(ctx.isa, 8, LOWER16(addr), 15)); /* store half word */ buf16++; } else { - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */ - pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf8)); /* load lower value */ + pracc_add(&ctx, 0, MIPS32_SB(ctx.isa, 8, LOWER16(addr), 15)); /* store byte */ buf8++; } addr += size; } - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) goto exit; count -= this_round_count; @@ -874,95 +836,77 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { - static const uint32_t cp0_write_code[] = { - MIPS32_MTC0(1, 12, 0), /* move $1 to status */ - MIPS32_MTLO(1), /* move $1 to lo */ - MIPS32_MTHI(1), /* move $1 to hi */ - MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */ - MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/ - MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */ - }; - - struct pracc_queue_info ctx = {.max_code = 37 * 2 + 7 + 1}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */ - for (int i = 2; i < 32; i++) { - if (LOWER16((regs[i])) == 0) /* if lower half word is 0, lui instruction only */ - pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); - else if (UPPER16((regs[i])) == 0) /* if upper half word is 0, ori with $0 only*/ - pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i])))); - else { /* default, load with lui and ori instructions */ - pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); - pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i])))); - } - } + uint32_t cp0_write_code[] = { + MIPS32_MTC0(ctx.isa, 1, 12, 0), /* move $1 to status */ + MIPS32_MTLO(ctx.isa, 1), /* move $1 to lo */ + MIPS32_MTHI(ctx.isa, 1), /* move $1 to hi */ + MIPS32_MTC0(ctx.isa, 1, 8, 0), /* move $1 to badvaddr */ + MIPS32_MTC0(ctx.isa, 1, 13, 0), /* move $1 to cause*/ + MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */ + }; + + /* load registers 2 to 31 with li32, optimize */ + for (int i = 2; i < 32; i++) + pracc_add_li32(&ctx, i, regs[i], 1); for (int i = 0; i != 6; i++) { - pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32])))); /* load CPO value in $1, with lui and ori */ - pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32])))); - pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ + pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */ + pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ } - pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ - pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1])))); /* load upper half word in $1 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); ejtag_info->reg8 = regs[8]; ejtag_info->reg9 = regs[9]; -exit: pracc_queue_free(&ctx); return ctx.retval; } int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { - static int cp0_read_code[] = { - MIPS32_MFC0(8, 12, 0), /* move status to $8 */ - MIPS32_MFLO(8), /* move lo to $8 */ - MIPS32_MFHI(8), /* move hi to $8 */ - MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */ - MIPS32_MFC0(8, 13, 0), /* move cause to $8 */ - MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */ - }; - - struct pracc_queue_info ctx = {.max_code = 49}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */ - pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ + uint32_t cp0_read_code[] = { + MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */ + MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */ + MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */ + MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */ + MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */ + MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */ + }; + + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0)); /* move $1 to COP0 DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4), - MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1)); + MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1)); for (int i = 0; i != 6; i++) { pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */ - MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1)); + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1)); } - pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */ - pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */ - MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1)); + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0)); /* move DeSave to $8, reg1 value */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1)); - pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */ - if (ejtag_info->mode == 0) - ctx.store_count++; /* Needed by legacy code, due to offset from reg0 */ - - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1); ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */ ejtag_info->reg9 = regs[9]; -exit: pracc_queue_free(&ctx); return ctx.retval; } @@ -977,70 +921,61 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, int write_t, uint32_t addr, int count, uint32_t *buf) { + uint32_t isa = ejtag_info->isa ? 1 : 0; uint32_t handler_code[] = { - /* caution when editing, table is modified below */ /* r15 points to the start of this code */ - MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), - MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), - MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), - MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), + MIPS32_SW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), + MIPS32_SW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS32_SW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), + MIPS32_SW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), /* start of fastdata area in t0 */ - MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_LW(9, 0, 8), /* start addr in t1 */ - MIPS32_LW(10, 0, 8), /* end addr to t2 */ - /* loop: */ - /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */ - /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */ - MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ - MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ - - MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), - MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), - MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), - MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), - - MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)), - MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)), - MIPS32_JR(15), /* jr start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ + MIPS32_LUI(isa, 8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), + MIPS32_ORI(isa, 8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), + MIPS32_LW(isa, 9, 0, 8), /* start addr in t1 */ + MIPS32_LW(isa, 10, 0, 8), /* end addr to t2 */ + /* loop: */ + write_t ? MIPS32_LW(isa, 11, 0, 8) : MIPS32_LW(isa, 11, 0, 9), /* from xfer area : from memory */ + write_t ? MIPS32_SW(isa, 11, 0, 9) : MIPS32_SW(isa, 11, 0, 8), /* to memory : to xfer area */ + + MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)), /* bne $t2,t1,loop */ + MIPS32_ADDI(isa, 9, 9, 4), /* addi t1,t1,4 */ + + MIPS32_LW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), + MIPS32_LW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS32_LW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), + MIPS32_LW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), + + MIPS32_LUI(isa, 15, UPPER16(MIPS32_PRACC_TEXT)), + MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_PRACC_TEXT) | isa), /* isa bit for JR instr */ + MIPS32_JR(isa, 15), /* jr start */ + MIPS32_MFC0(isa, 15, 31, 0), /* move COP0 DeSave to $15 */ }; - uint32_t jmp_code[] = { - /* 0 */ MIPS32_LUI(15, 0), /* addr of working area added below */ - /* 1 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */ - MIPS32_JR(15), /* jump to ram program */ - MIPS32_NOP, - }; - - int retval, i; - uint32_t val, ejtag_ctrl, address; - if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - if (write_t) { - handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */ - handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */ - } else { - handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */ - handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */ - } - - /* write program into RAM */ + pracc_swap16_array(ejtag_info, handler_code, ARRAY_SIZE(handler_code)); + /* write program into RAM */ if (write_t != ejtag_info->fast_access_save) { mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); /* save previous operation to speed to any consecutive read/writes */ ejtag_info->fast_access_save = write_t; } - LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address); + LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address); + + uint32_t jmp_code[] = { + MIPS32_LUI(isa, 15, UPPER16(source->address)), /* load addr of jump in $15 */ + MIPS32_ORI(isa, 15, 15, LOWER16(source->address) | isa), /* isa bit for JR instr */ + MIPS32_JR(isa, 15), /* jump to ram program */ + isa ? MIPS32_XORI(isa, 15, 15, 1) : MIPS32_NOP, /* drop isa bit, needed for LW/SW instructions */ + }; - jmp_code[0] |= UPPER16(source->address); - jmp_code[1] |= LOWER16(source->address); + pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code)); - for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) { - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + /* execute jump code, with no address check */ + for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1048,32 +983,24 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]); /* Clear the access pending bit (let the processor eat!) */ - ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); - mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); + mips32_pracc_finish(ejtag_info); } - /* wait PrAcc pending bit for FASTDATA write */ - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + /* wait PrAcc pending bit for FASTDATA write, read address */ + int retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; /* next fetch to dmseg should be in FASTDATA_AREA, check */ - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); - if (retval != ERROR_OK) - return retval; - - if (address != MIPS32_PRACC_FASTDATA_AREA) + if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA) return ERROR_FAIL; /* Send the load start address */ - val = addr; + uint32_t val = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1086,11 +1013,9 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { jtag_add_clocks(num_clocks); - retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); - if (retval != ERROR_OK) - return retval; + mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); } retval = jtag_execute_queue(); @@ -1099,17 +1024,11 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are return retval; } - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); - if (retval != ERROR_OK) - return retval; - - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); + retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; - if (address != MIPS32_PRACC_TEXT) + if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); return retval; diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index eab5f73ec..888c847c0 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -18,13 +18,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MIPS32_PRACC_H -#define MIPS32_PRACC_H +#ifndef OPENOCD_TARGET_MIPS32_PRACC_H +#define OPENOCD_TARGET_MIPS32_PRACC_H #include #include @@ -36,26 +34,40 @@ #define MIPS32_PRACC_PARAM_OUT 0xFF202000 #define PRACC_UPPER_BASE_ADDR (MIPS32_PRACC_BASE_ADDR >> 16) +#define PRACC_MAX_CODE (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_TEXT) +#define PRACC_MAX_INSTRUCTIONS (PRACC_MAX_CODE / 4) #define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR) #define MIPS32_FASTDATA_HANDLER_SIZE 0x80 #define UPPER16(uint32_t) (uint32_t >> 16) #define LOWER16(uint32_t) (uint32_t & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF) +#define SWAP16(v) ((LOWER16(v) << 16) | (UPPER16(v))) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ +#define PRACC_BLOCK 128 /* 1 Kbyte */ + +typedef struct { + uint32_t instr; + uint32_t addr; +} pa_list; + struct pracc_queue_info { + struct mips_ejtag *ejtag_info; + unsigned isa; int retval; - const int max_code; int code_count; int store_count; - uint32_t *pracc_list; /* Code and store addresses */ + int max_code; /* max intstructions with currently allocated memory */ + pa_list *pracc_list; /* Code and store addresses at dmseg */ }; + void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); +void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize); void pracc_queue_free(struct pracc_queue_info *ctx); int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, - struct pracc_queue_info *ctx, uint32_t *buf); + struct pracc_queue_info *ctx, uint32_t *buf, bool check_last); int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf); @@ -67,7 +79,8 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); -int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out); +int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *param_out, bool check_last); /** * \b mips32_cp0_read @@ -101,4 +114,11 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); -#endif +static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) +{ + if (ejtag_info->isa && ejtag_info->endianness) + for (int i = 0; i != count; i++) + buf[i] = SWAP16(buf[i]); +} + +#endif /* OPENOCD_TARGET_MIPS32_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 2a16193f8..03a09529c 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -17,9 +17,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -30,74 +28,40 @@ #include "mips_ejtag.h" #include "mips32_dmaacc.h" -void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr) +void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr) { - struct jtag_tap *tap; + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; - tap = ejtag_info->tap; - assert(tap != NULL); + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { - if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) { struct scan_field field; - uint8_t t[4]; - field.num_bits = tap->ir_length; + + uint8_t t[4]; field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); + field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); } } -int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode) +int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info) { - struct scan_field field; - uint8_t r[4]; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE); - field.num_bits = 32; - field.out_value = NULL; - field.in_value = r; - - jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); - - int retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("register read failed"); - return retval; - } - - *idcode = buf_get_u32(field.in_value, 0, 32); - - return ERROR_OK; + ejtag_info->idcode = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->idcode); } -static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode) +int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info) { - struct scan_field field; - uint8_t r[4]; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE); - field.num_bits = 32; - field.out_value = NULL; - field.in_value = r; - - jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); - - int retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("register read failed"); - return retval; - } - - *impcode = buf_get_u32(field.in_value, 0, 32); - - return ERROR_OK; + ejtag_info->impcode = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->impcode); } void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf) @@ -123,91 +87,73 @@ void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32 keep_alive(); } -int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) +void mips_ejtag_drscan_32_queued(struct mips_ejtag *ejtag_info, uint32_t data_out, uint8_t *data_in) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - uint8_t t[4], r[4]; - int retval; - field.num_bits = 32; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, *data); - field.in_value = r; + uint8_t scan_out[4]; + field.out_value = scan_out; + buf_set_u32(scan_out, 0, field.num_bits, data_out); + + field.in_value = data_in; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); - retval = jtag_execute_queue(); + keep_alive(); +} + +int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) +{ + uint8_t scan_in[4]; + mips_ejtag_drscan_32_queued(ejtag_info, *data, scan_in); + + int retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } - *data = buf_get_u32(field.in_value, 0, 32); - - keep_alive(); - + *data = buf_get_u32(scan_in, 0, 32); return ERROR_OK; } void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data) { - uint8_t t[4]; - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); - - struct scan_field field; - - field.num_bits = 32; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, data); - - field.in_value = NULL; - - jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); + mips_ejtag_drscan_32_queued(ejtag_info, data, NULL); } -int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data) +int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - uint8_t t[4] = {0, 0, 0, 0}, r[4]; - int retval; - field.num_bits = 8; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, *data); - field.in_value = r; + + field.out_value = data; + field.in_value = data; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); - retval = jtag_execute_queue(); + int retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } - - *data = buf_get_u32(field.in_value, 0, 32); - return ERROR_OK; } void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - field.num_bits = 8; + field.out_value = &data; field.in_value = NULL; @@ -217,23 +163,20 @@ void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) /* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { - struct pracc_queue_info ctx = {.max_code = 7}; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; - pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 23, 0)); /* move COP0 Debug to $8 */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, 0x0100)); /* set SSt bit in debug reg */ if (!enable_step) - pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_XORI(ctx.isa, 8, 8, 0x0100)); /* clear SSt bit in debug reg */ - pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 8, 23, 0)); /* move $8 to COP0 Debug */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -exit: + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -292,11 +235,11 @@ int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info) int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { - uint32_t pracc_list[] = {MIPS32_DRET, 0}; - struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0}; + pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0}; + struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); @@ -391,12 +334,11 @@ static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) int mips_ejtag_init(struct mips_ejtag *ejtag_info) { - int retval; - - retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode); - if (retval != ERROR_OK) + int retval = mips_ejtag_get_impcode(ejtag_info); + if (retval != ERROR_OK) { + LOG_ERROR("impcode read failed"); return retval; - LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode); + } /* get ejtag version */ ejtag_info->ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); @@ -446,22 +388,22 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info) int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data) { - struct jtag_tap *tap; - - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field fields[2]; - uint8_t spracc = 0; - uint8_t t[4] = {0, 0, 0, 0}; /* fastdata 1-bit register */ fields[0].num_bits = 1; + + uint8_t spracc = 0; fields[0].out_value = &spracc; fields[0].in_value = NULL; /* processor access data register 32 bit */ fields[1].num_bits = 32; + + uint8_t t[4] = {0, 0, 0, 0}; fields[1].out_value = t; if (write_t) { diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 3e0d83101..71f5c1b4b 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -15,13 +15,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MIPS_EJTAG -#define MIPS_EJTAG +#ifndef OPENOCD_TARGET_MIPS_EJTAG_H +#define OPENOCD_TARGET_MIPS_EJTAG_H #include @@ -60,6 +58,7 @@ #define EJTAG_CTRL_DERR (1 << 10) #define EJTAG_CTRL_DSTRT (1 << 11) #define EJTAG_CTRL_JTAGBRK (1 << 12) +#define EJTAG_CTRL_DBGISA (1 << 13) #define EJTAG_CTRL_SETDEV (1 << 14) #define EJTAG_CTRL_PROBEN (1 << 15) #define EJTAG_CTRL_PRRST (1 << 16) @@ -144,7 +143,7 @@ #define EJTAG_V20_IBC_OFFS 0x4 /* IBC Offset */ #define EJTAG_V20_IBM_OFFS 0x8 #define EJTAG_V20_IBAn_STEP 0x10 /* Offset for next channel */ -#define EJTAG_V20_DBS 0xFF30008 +#define EJTAG_V20_DBS 0xFF300008 #define EJTAG_V20_DBA0 0xFF300200 #define EJTAG_V20_DBC_OFFS 0x4 #define EJTAG_V20_DBM_OFFS 0x8 @@ -184,6 +183,9 @@ struct mips_ejtag { uint32_t idcode; uint32_t ejtag_ctrl; int fast_access_save; + uint32_t config_regs; /* number of config registers read */ + uint32_t config[4]; /* cp0 config to config3 */ + uint32_t reg8; uint32_t reg9; unsigned scan_delay; @@ -191,6 +193,8 @@ struct mips_ejtag { uint32_t pa_ctrl; uint32_t pa_addr; unsigned int ejtag_version; + uint32_t isa; + uint32_t endianness; /* Memory-Mapped Registers. This addresses are not same on different * EJTAG versions. */ @@ -212,17 +216,16 @@ struct mips_ejtag { uint32_t ejtag_dba_step_size; /* size of step till next *DBAn register. */ }; -void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, - int new_instr); +void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr); int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info); -int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode); +int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info); void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf); void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data); int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data); void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data); -int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data); +int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data); int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data); int mips_ejtag_init(struct mips_ejtag *ejtag_info); @@ -234,4 +237,4 @@ static inline void mips_le_to_h_u32(jtag_callback_data_t arg) *((uint32_t *)arg) = le_to_h_u32(in); } -#endif /* MIPS_EJTAG */ +#endif /* OPENOCD_TARGET_MIPS_EJTAG_H */ diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 5b740cc45..7d1c06cf0 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -20,9 +20,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -43,10 +41,10 @@ static int mips_m4k_set_breakpoint(struct target *target, static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_internal_restore(struct target *target, int current, - uint32_t address, int handle_breakpoints, + target_addr_t address, int handle_breakpoints, int debug_execution); static int mips_m4k_halt(struct target *target); -static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, +static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); static int mips_m4k_examine_debug_reason(struct target *target) @@ -110,11 +108,14 @@ static int mips_m4k_debug_entry(struct target *target) /* attempt to find halt reason */ mips_m4k_examine_debug_reason(target); + mips32_read_config_regs(target); + /* default to mips32 isa, it will be changed below if required */ mips32->isa_mode = MIPS32_ISA_MIPS32; - if (ejtag_info->impcode & EJTAG_IMP_MIPS16) - mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1); + /* other than mips32 only and isa bit set ? */ + if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1)) + mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32; LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s", buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32), @@ -197,6 +198,8 @@ static int mips_m4k_poll(struct target *target) if (retval != ERROR_OK) return retval; + ejtag_info->isa = (ejtag_ctrl & EJTAG_CTRL_DBGISA) ? 1 : 0; + /* clear this bit before handling polling * as after reset registers will read zero */ if (ejtag_ctrl & EJTAG_CTRL_ROCC) { @@ -302,6 +305,13 @@ static int mips_m4k_assert_reset(struct target *target) struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } + LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -424,7 +434,7 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han } static int mips_m4k_internal_restore(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -444,12 +454,13 @@ static int mips_m4k_internal_restore(struct target *target, int current, /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { + mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; } - if (ejtag_info->impcode & EJTAG_IMP_MIPS16) + if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */ buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode); if (!current) @@ -464,7 +475,8 @@ static int mips_m4k_internal_restore(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); mips_m4k_unset_breakpoint(target, breakpoint); mips_m4k_single_step_core(target); mips_m4k_set_breakpoint(target, breakpoint); @@ -495,7 +507,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, } static int mips_m4k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = ERROR_OK; @@ -522,7 +534,7 @@ static int mips_m4k_resume(struct target *target, int current, } static int mips_m4k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); @@ -536,6 +548,7 @@ static int mips_m4k_step(struct target *target, int current, /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { + mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; @@ -618,6 +631,11 @@ static int mips_m4k_set_breakpoint(struct target *target, comparator_list[bp_num].used = 1; comparator_list[bp_num].bp_value = breakpoint->address; + if (breakpoint->length != 4) /* make sure isa bit set */ + comparator_list[bp_num].bp_value |= 1; + else /* make sure isa bit cleared */ + comparator_list[bp_num].bp_value &= ~1; + /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved. * Warning: there is no IB ASID registers in 2.0. * Do not set it! :) */ @@ -635,41 +653,77 @@ static int mips_m4k_set_breakpoint(struct target *target, bp_num, comparator_list[bp_num].bp_value); } else if (breakpoint->type == BKPT_SOFT) { LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); - if (breakpoint->length == 4) { + + uint32_t isa_req = breakpoint->length & 1; /* micro mips request bit */ + uint32_t bplength = breakpoint->length & ~1; /* drop micro mips request bit for length */ + uint32_t bpaddr = breakpoint->address & ~1; /* drop isa bit from address, if set */ + + if (bplength == 4) { uint32_t verify = 0xffffffff; + uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req); + if (ejtag_info->endianness && isa_req) + sdbbp32_instr = SWAP16(sdbbp32_instr); - retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, - breakpoint->orig_instr); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP); - if (retval != ERROR_OK) - return retval; + if ((breakpoint->address & 3) == 0) { /* word alligned */ - retval = target_read_u32(target, breakpoint->address, &verify); - if (retval != ERROR_OK) - return retval; - if (verify != MIPS32_SDBBP) { - LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32 - " - check that memory is read/writable", breakpoint->address); + retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + + retval = target_write_u32(target, bpaddr, sdbbp32_instr); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u32(target, bpaddr, &verify); + if (retval != ERROR_OK) + return retval; + + if (verify != sdbbp32_instr) + verify = 0; + + } else { /* 16 bit aligned */ + retval = target_read_memory(target, bpaddr, 2, 2, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + + uint8_t sdbbp_buf[4]; + target_buffer_set_u32(target, sdbbp_buf, sdbbp32_instr); + + retval = target_write_memory(target, bpaddr, 2, 2, sdbbp_buf); + if (retval != ERROR_OK) + return retval; + + retval = target_read_memory(target, bpaddr, 2, 2, sdbbp_buf); + if (retval != ERROR_OK) + return retval; + + if (target_buffer_get_u32(target, sdbbp_buf) != sdbbp32_instr) + verify = 0; + } + + if (verify == 0) { + LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx64 + " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } + } else { uint16_t verify = 0xffff; - retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, - breakpoint->orig_instr); + retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP); + + retval = target_write_u16(target, bpaddr, MIPS16_SDBBP(isa_req)); if (retval != ERROR_OK) return retval; - retval = target_read_u16(target, breakpoint->address, &verify); + retval = target_read_u16(target, bpaddr, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS16_SDBBP) { - LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32 + + if (verify != MIPS16_SDBBP(isa_req)) { + LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx64 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -712,46 +766,58 @@ static int mips_m4k_unset_breakpoint(struct target *target, } else { /* restore original instruction (kept in target endianness) */ + uint32_t isa_req = breakpoint->length & 1; + uint32_t bplength = breakpoint->length & ~1; + uint8_t current_instr[4]; LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); - if (breakpoint->length == 4) { - uint32_t current_instr; - - /* check that user program has not modified breakpoint instruction */ - retval = target_read_memory(target, breakpoint->address, 4, 1, - (uint8_t *)¤t_instr); - if (retval != ERROR_OK) - return retval; - - /** - * target_read_memory() gets us data in _target_ endianess. - * If we want to use this data on the host for comparisons with some macros - * we must first transform it to _host_ endianess using target_buffer_get_u32(). - */ - current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); - - if (current_instr == MIPS32_SDBBP) { - retval = target_write_memory(target, breakpoint->address, 4, 1, - breakpoint->orig_instr); + if (bplength == 4) { + uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req); + if (ejtag_info->endianness && isa_req) + sdbbp32_instr = SWAP16(sdbbp32_instr); + + if ((breakpoint->address & 3) == 0) { /* 32bit aligned */ + /* check that user program has not modified breakpoint instruction */ + retval = target_read_memory(target, breakpoint->address, 4, 1, current_instr); + if (retval != ERROR_OK) + return retval; + /** + * target_read_memory() gets us data in _target_ endianess. + * If we want to use this data on the host for comparisons with some macros + * we must first transform it to _host_ endianess using target_buffer_get_u16(). + */ + if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) { + retval = target_write_memory(target, breakpoint->address, 4, 1, + breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } + } else { /* 16bit alligned */ + retval = target_read_memory(target, breakpoint->address, 2, 2, current_instr); if (retval != ERROR_OK) return retval; + + if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) { + retval = target_write_memory(target, breakpoint->address, 2, 2, + breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } } } else { - uint16_t current_instr; - /* check that user program has not modified breakpoint instruction */ - retval = target_read_memory(target, breakpoint->address, 2, 1, - (uint8_t *)¤t_instr); + retval = target_read_memory(target, breakpoint->address, 2, 1, current_instr); if (retval != ERROR_OK) return retval; - current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS16_SDBBP) { + + if (target_buffer_get_u16(target, current_instr) == MIPS16_SDBBP(isa_req)) { retval = target_write_memory(target, breakpoint->address, 2, 1, - breakpoint->orig_instr); + breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } } + breakpoint->set = 0; return ERROR_OK; @@ -761,6 +827,12 @@ static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *bre { struct mips32_common *mips32 = target_to_mips32(target); + if ((breakpoint->length > 5 || breakpoint->length < 2) || /* out of range */ + (breakpoint->length == 4 && (breakpoint->address & 2)) || /* mips32 unaligned */ + (mips32->isa_imp == MIPS32_ONLY && breakpoint->length != 4) || /* misp32 specific */ + ((mips32->isa_imp & 1) != (breakpoint->length & 1))) /* isa not implemented */ + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + if (breakpoint->type == BKPT_HARD) { if (mips32->num_inst_bpoints_avail < 1) { LOG_INFO("no hardware breakpoint available"); @@ -944,13 +1016,13 @@ static void mips_m4k_enable_watchpoints(struct target *target) } } -static int mips_m4k_read_memory(struct target *target, uint32_t address, +static int mips_m4k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -1003,13 +1075,13 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address, return retval; } -static int mips_m4k_write_memory(struct target *target, uint32_t address, +static int mips_m4k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -1102,39 +1174,33 @@ static int mips_m4k_target_create(struct target *target, Jim_Interp *interp) static int mips_m4k_examine(struct target *target) { - int retval; struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; - uint32_t idcode = 0; if (!target_was_examined(target)) { - retval = mips_ejtag_get_idcode(ejtag_info, &idcode); - if (retval != ERROR_OK) + int retval = mips_ejtag_get_idcode(ejtag_info); + if (retval != ERROR_OK) { + LOG_ERROR("idcode read failed"); return retval; - ejtag_info->idcode = idcode; - - if (((idcode >> 1) & 0x7FF) == 0x29) { + } + if (((ejtag_info->idcode >> 1) & 0x7FF) == 0x29) { /* we are using a pic32mx so select ejtag port * as it is not selected by default */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); - LOG_DEBUG("PIC32MX Detected - using EJTAG Interface"); + LOG_DEBUG("PIC32 Detected - using EJTAG Interface"); mips_m4k->is_pic32mx = true; } } /* init rest of ejtag interface */ - retval = mips_ejtag_init(ejtag_info); + int retval = mips_ejtag_init(ejtag_info); if (retval != ERROR_OK) return retval; - retval = mips32_examine(target); - if (retval != ERROR_OK) - return retval; - - return ERROR_OK; + return mips32_examine(target); } -static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, +static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); @@ -1143,7 +1209,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, int retval; int write_t = 1; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count); + LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "", + address, count); /* check alignment */ if (address & 0x3u) @@ -1170,8 +1237,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, if (address <= fast_data_area->address + fast_data_area->size && fast_data_area->address <= address + count) { - LOG_ERROR("fast_data (0x%8.8" PRIx32 ") is within write area " - "(0x%8.8" PRIx32 "-0x%8.8" PRIx32 ").", + LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area " + "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").", fast_data_area->address, address, address + count); LOG_ERROR("Change work-area-phys or load_image address!"); return ERROR_FAIL; @@ -1334,7 +1401,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); - if (ejtag_info->scan_delay >= 20000000) { + if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h index de990599c..ea09ae527 100644 --- a/src/target/mips_m4k.h +++ b/src/target/mips_m4k.h @@ -18,13 +18,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef MIPS_M4K_H -#define MIPS_M4K_H +#ifndef OPENOCD_TARGET_MIPS_M4K_H +#define OPENOCD_TARGET_MIPS_M4K_H struct target; @@ -43,6 +41,17 @@ target_to_m4k(struct target *target) struct mips_m4k_common, mips32); } +static inline void mips_m4k_isa_filter(enum mips32_isa_imp isa_imp, target_addr_t *addr) +{ + if (isa_imp <= 1) { /* if only one isa implemented */ + target_addr_t address = (*addr & ~1) | isa_imp; + + if (address != *addr) { + LOG_USER("Warning: isa bit changed due to isa not implemented"); + *addr = address; + } + } +} extern const struct command_registration mips_m4k_command_handlers[]; -#endif /*MIPS_M4K_H*/ +#endif /* OPENOCD_TARGET_MIPS_M4K_H */ diff --git a/src/target/nds32.c b/src/target/nds32.c index b6c5f6122..e4bb17f9d 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -825,7 +823,7 @@ int nds32_read_memory(struct target *target, uint32_t address, return aice_read_mem_unit(aice, address, size, count, buffer); } -int nds32_read_phys_memory(struct target *target, uint32_t address, +int nds32_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); @@ -934,7 +932,7 @@ int nds32_write_memory(struct target *target, uint32_t address, return aice_write_mem_unit(aice, address, size, count, buffer); } -int nds32_write_phys_memory(struct target *target, uint32_t address, +int nds32_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); @@ -1676,7 +1674,7 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) return ERROR_OK; } -int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical) +int nds32_virtual_to_physical(struct target *target, target_addr_t address, target_addr_t *physical) { struct nds32 *nds32 = target_to_nds32(target); @@ -1694,7 +1692,7 @@ int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t return ERROR_FAIL; } -int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) +int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length) { struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); @@ -1740,7 +1738,7 @@ int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) /* Because PSW.IT is turned off under debug exception, address MUST * be physical address. L1I_VA_INVALIDATE uses PSW.IT to decide * address translation or not. */ - uint32_t physical_addr; + target_addr_t physical_addr; if (ERROR_FAIL == target->type->virt2phys(target, cur_address, &physical_addr)) return ERROR_FAIL; @@ -1766,7 +1764,7 @@ uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address) } int nds32_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -1780,7 +1778,7 @@ int nds32_step(struct target *target, int current, address = nds32_nextpc(nds32, current, address); - LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /** set DSSIM */ uint32_t ir14_value; @@ -2122,9 +2120,9 @@ int nds32_poll(struct target *target) } int nds32_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { - LOG_DEBUG("current %d address %08" PRIx32 + LOG_DEBUG("current %d address %08" TARGET_PRIxADDR " handle_breakpoints %d" " debug_execution %d", current, address, handle_breakpoints, debug_execution); @@ -2138,7 +2136,7 @@ int nds32_resume(struct target *target, int current, address = nds32_nextpc(nds32, current, address); - LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); if (!debug_execution) target_free_all_working_areas(target); @@ -2199,6 +2197,13 @@ int nds32_assert_reset(struct target *target) struct aice_port_s *aice = target_to_aice(target); struct nds32_cpu_version *cpu_version = &(nds32->cpu_version); + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } + if (target->reset_halt) { if ((nds32->soft_reset_halt) || (nds32->edm.version < 0x51) diff --git a/src/target/nds32.h b/src/target/nds32.h index e4161e93b..141dbf4cb 100644 --- a/src/target/nds32.h +++ b/src/target/nds32.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_H__ -#define __NDS32_H__ +#ifndef OPENOCD_TARGET_NDS32_H +#define OPENOCD_TARGET_NDS32_H #include #include "target.h" @@ -402,23 +400,23 @@ extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t * extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value); extern int nds32_edm_config(struct nds32 *nds32); -extern int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length); +extern int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length); extern int nds32_mmu(struct target *target, int *enabled); -extern int nds32_virtual_to_physical(struct target *target, uint32_t address, - uint32_t *physical); -extern int nds32_read_phys_memory(struct target *target, uint32_t address, +extern int nds32_virtual_to_physical(struct target *target, target_addr_t address, + target_addr_t *physical); +extern int nds32_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -extern int nds32_write_phys_memory(struct target *target, uint32_t address, +extern int nds32_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address); extern int nds32_examine_debug_reason(struct nds32 *nds32); extern int nds32_step(struct target *target, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); extern int nds32_target_state(struct nds32 *nds32, enum target_state *state); extern int nds32_halt(struct target *target); extern int nds32_poll(struct target *target); extern int nds32_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution); + target_addr_t address, int handle_breakpoints, int debug_execution); extern int nds32_assert_reset(struct target *target); extern int nds32_init(struct nds32 *nds32); extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); @@ -456,4 +454,4 @@ static inline bool nds32_reach_max_interrupt_level(struct nds32 *nds32) return nds32->max_interrupt_level == nds32->current_interrupt_level; } -#endif /* __NDS32_H__ */ +#endif /* OPENOCD_TARGET_NDS32_H */ diff --git a/src/target/nds32_aice.c b/src/target/nds32_aice.c index cfb6d86c8..e494a3e1c 100644 --- a/src/target/nds32_aice.c +++ b/src/target/nds32_aice.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -44,8 +42,8 @@ int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val) return aice->port->api->write_reg_64(aice->coreid, num, val); } -int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, - uint32_t *physical_address) +int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address, + target_addr_t *physical_address) { if (aice->port->api->read_tlb == NULL) { LOG_WARNING("Not implemented: %s", __func__); diff --git a/src/target/nds32_aice.h b/src/target/nds32_aice.h index d53564330..5ea3b1611 100644 --- a/src/target/nds32_aice.h +++ b/src/target/nds32_aice.h @@ -13,19 +13,18 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_AICE_H__ -#define __NDS32_AICE_H__ + +#ifndef OPENOCD_TARGET_NDS32_AICE_H +#define OPENOCD_TARGET_NDS32_AICE_H #include int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val); int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val); -int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, - uint32_t *physical_address); +int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address, + target_addr_t *physical_address); int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address); int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times); int aice_program_edm(struct aice_port_s *aice, char *command_sequence); @@ -159,4 +158,4 @@ static inline int aice_set_data_endian(struct aice_port_s *aice, return aice->port->api->set_data_endian(aice->coreid, target_data_endian); } -#endif +#endif /* OPENOCD_TARGET_NDS32_AICE_H */ diff --git a/src/target/nds32_cmd.c b/src/target/nds32_cmd.c index faf9e0aef..edb4872e4 100644 --- a/src/target/nds32_cmd.c +++ b/src/target/nds32_cmd.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -846,7 +844,7 @@ static int jim_nds32_read_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const * } int e; - char *edm_sr_name; + const char *edm_sr_name; int edm_sr_name_len; e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len); if (e != JIM_OK) @@ -892,7 +890,7 @@ static int jim_nds32_write_edm_sr(Jim_Interp *interp, int argc, Jim_Obj * const } int e; - char *edm_sr_name; + const char *edm_sr_name; int edm_sr_name_len; e = Jim_GetOpt_String(&goi, &edm_sr_name, &edm_sr_name_len); if (e != JIM_OK) diff --git a/src/target/nds32_cmd.h b/src/target/nds32_cmd.h index 44d361e55..543ba54c6 100644 --- a/src/target/nds32_cmd.h +++ b/src/target/nds32_cmd.h @@ -13,15 +13,14 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_CMD_H__ -#define __NDS32_CMD_H__ +#ifndef OPENOCD_TARGET_NDS32_CMD_H +#define OPENOCD_TARGET_NDS32_CMD_H + #include extern const struct command_registration nds32_command_handlers[]; -#endif /* __NDS32_CMD_H__ */ +#endif /* OPENOCD_TARGET_NDS32_CMD_H */ diff --git a/src/target/nds32_disassembler.c b/src/target/nds32_disassembler.c index 8565f855f..f27aba2cc 100644 --- a/src/target/nds32_disassembler.c +++ b/src/target/nds32_disassembler.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/nds32_disassembler.h b/src/target/nds32_disassembler.h index ac0222e66..9117cbb08 100644 --- a/src/target/nds32_disassembler.h +++ b/src/target/nds32_disassembler.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_DISASSEMBLER_H__ -#define __NDS32_DISASSEMBLER_H__ +#ifndef OPENOCD_TARGET_NDS32_DISASSEMBLER_H +#define OPENOCD_TARGET_NDS32_DISASSEMBLER_H #include @@ -55,4 +53,4 @@ int nds32_read_opcode(struct nds32 *nds32, uint32_t address, uint32_t *value); int nds32_evaluate_opcode(struct nds32 *nds32, uint32_t opcode, uint32_t address, struct nds32_instruction *instruction); -#endif /* __NDS32_DISASSEMBLER_H__ */ +#endif /* OPENOCD_TARGET_NDS32_DISASSEMBLER_H */ diff --git a/src/target/nds32_edm.h b/src/target/nds32_edm.h index 1eab7b007..1dec190f1 100644 --- a/src/target/nds32_edm.h +++ b/src/target/nds32_edm.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_EDM_H__ -#define __NDS32_EDM_H__ + +#ifndef OPENOCD_TARGET_NDS32_EDM_H +#define OPENOCD_TARGET_NDS32_EDM_H /** * @file @@ -113,4 +112,4 @@ enum nds_memory_select { #define NDS_EDMSW_WDV (1 << 0) #define NDS_EDMSW_RDV (1 << 1) -#endif /* __NDS32_EDM_H__ */ +#endif /* OPENOCD_TARGET_NDS32_EDM_H */ diff --git a/src/target/nds32_insn.h b/src/target/nds32_insn.h index 08d3c5ca9..eb6664517 100644 --- a/src/target/nds32_insn.h +++ b/src/target/nds32_insn.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_INSN_H__ -#define __NDS32_INSN_H__ +#ifndef OPENOCD_TARGET_NDS32_INSN_H +#define OPENOCD_TARGET_NDS32_INSN_H #define NOP (0x40000009) #define DSB (0x64000008) @@ -77,5 +75,4 @@ extern const int NDS32_BREAK_16; extern const int NDS32_BREAK_32; - -#endif /* __NDS32_INSN_H__ */ +#endif /* OPENOCD_TARGET_NDS32_INSN_H */ diff --git a/src/target/nds32_reg.c b/src/target/nds32_reg.c index f82ffbfc4..7cefcb1a2 100644 --- a/src/target/nds32_reg.c +++ b/src/target/nds32_reg.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" diff --git a/src/target/nds32_reg.h b/src/target/nds32_reg.h index 1c61b6164..8808cd244 100644 --- a/src/target/nds32_reg.h +++ b/src/target/nds32_reg.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_REG_H__ -#define __NDS32_REG_H__ + +#ifndef OPENOCD_TARGET_NDS32_REG_H +#define OPENOCD_TARGET_NDS32_REG_H #define SRIDX(a, b, c) ((a << 7) | (b << 3) | c) #define NDS32_REGISTER_DISABLE (0x0) @@ -323,4 +322,4 @@ const char *nds32_reg_simple_name(uint32_t number); const char *nds32_reg_symbolic_name(uint32_t number); bool nds32_reg_exception(uint32_t number, uint32_t value); -#endif +#endif /* OPENOCD_TARGET_NDS32_REG_H */ diff --git a/src/target/nds32_tlb.c b/src/target/nds32_tlb.c index 58322cf1e..c4bce1a6a 100644 --- a/src/target/nds32_tlb.c +++ b/src/target/nds32_tlb.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -24,8 +22,8 @@ #include "nds32_aice.h" #include "nds32_tlb.h" -int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address) +int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address) { struct target *target = nds32->target; struct aice_port_s *aice = target_to_aice(target); @@ -40,8 +38,8 @@ struct page_table_walker_info_s page_table_info[PAGE_SIZE_NUM] = { {0xFF000000, 22, 0x00FFE000, 11, 0x00001FFF, 0xFFFFF000, 0xFFFFE000, 0xFFFFE000}, }; -int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address) +int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address) { struct target *target = nds32->target; uint32_t value_mr1; diff --git a/src/target/nds32_tlb.h b/src/target/nds32_tlb.h index 59e115730..62512c111 100644 --- a/src/target/nds32_tlb.h +++ b/src/target/nds32_tlb.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_TLB_H__ -#define __NDS32_TLB_H__ + +#ifndef OPENOCD_TARGET_NDS32_TLB_H +#define OPENOCD_TARGET_NDS32_TLB_H #include "nds32.h" @@ -40,9 +39,9 @@ struct page_table_walker_info_s { uint32_t ppn_mask; }; -extern int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address); -extern int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address); +extern int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address); +extern int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address); -#endif +#endif /* OPENOCD_TARGET_NDS32_TLB_H */ diff --git a/src/target/nds32_v2.c b/src/target/nds32_v2.c index ac2aad0b8..29489a034 100644 --- a/src/target/nds32_v2.c +++ b/src/target/nds32_v2.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -114,7 +112,7 @@ static int nds32_v2_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); - LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); hbr_index++; @@ -141,7 +139,7 @@ static int nds32_v2_deactivate_hardware_breakpoint(struct target *target) else return ERROR_FAIL; - LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); hbr_index++; @@ -186,7 +184,7 @@ static int nds32_v2_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); } @@ -206,7 +204,7 @@ static int nds32_v2_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); } @@ -407,7 +405,7 @@ static int nds32_v2_deassert_reset(struct target *target) } static int nds32_v2_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); @@ -563,8 +561,8 @@ static int nds32_v2_run_algorithm(struct target *target, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, - uint32_t exit_point, + target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info) { @@ -637,11 +635,11 @@ static int nds32_v2_examine(struct target *target) return ERROR_OK; } -static int nds32_v2_translate_address(struct target *target, uint32_t *address) +static int nds32_v2_translate_address(struct target *target, target_addr_t *address) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); - uint32_t physical_address; + target_addr_t physical_address; /* Following conditions need to do address translation * 1. BUS mode @@ -658,7 +656,7 @@ static int nds32_v2_translate_address(struct target *target, uint32_t *address) return ERROR_OK; } -static int nds32_v2_read_buffer(struct target *target, uint32_t address, +static int nds32_v2_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -678,7 +676,7 @@ static int nds32_v2_read_buffer(struct target *target, uint32_t address, return nds32_read_buffer(target, address, size, buffer); } -static int nds32_v2_write_buffer(struct target *target, uint32_t address, +static int nds32_v2_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -698,7 +696,7 @@ static int nds32_v2_write_buffer(struct target *target, uint32_t address, return nds32_write_buffer(target, address, size, buffer); } -static int nds32_v2_read_memory(struct target *target, uint32_t address, +static int nds32_v2_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -718,7 +716,7 @@ static int nds32_v2_read_memory(struct target *target, uint32_t address, return nds32_read_memory(target, address, size, count, buffer); } -static int nds32_v2_write_memory(struct target *target, uint32_t address, +static int nds32_v2_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); diff --git a/src/target/nds32_v2.h b/src/target/nds32_v2.h index b39805578..dcc08c29e 100644 --- a/src/target/nds32_v2.h +++ b/src/target/nds32_v2.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_V2_H__ -#define __NDS32_V2_H__ + +#ifndef OPENOCD_TARGET_NDS32_V2_H +#define OPENOCD_TARGET_NDS32_V2_H #include "nds32.h" @@ -40,5 +39,4 @@ static inline struct nds32_v2_common *target_to_nds32_v2(struct target *target) return container_of(target->arch_info, struct nds32_v2_common, nds32); } - -#endif /* __NDS32_V2_H__ */ +#endif /* OPENOCD_TARGET_NDS32_V2_H */ diff --git a/src/target/nds32_v3.c b/src/target/nds32_v3.c index 224665010..e5d146bb6 100644 --- a/src/target/nds32_v3.c +++ b/src/target/nds32_v3.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -55,7 +53,7 @@ static int nds32_v3_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); - LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); } else { return ERROR_FAIL; @@ -83,7 +81,7 @@ static int nds32_v3_deactivate_hardware_breakpoint(struct target *target) return ERROR_FAIL; } - LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); } @@ -130,7 +128,7 @@ static int nds32_v3_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -171,7 +169,7 @@ static int nds32_v3_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; diff --git a/src/target/nds32_v3.h b/src/target/nds32_v3.h index 7476b202c..a5df8fe52 100644 --- a/src/target/nds32_v3.h +++ b/src/target/nds32_v3.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_V3_H__ -#define __NDS32_V3_H__ + +#ifndef OPENOCD_TARGET_NDS32_V3_H +#define OPENOCD_TARGET_NDS32_V3_H #include "nds32.h" @@ -43,4 +42,4 @@ static inline struct nds32_v3_common *target_to_nds32_v3(struct target *target) return container_of(target->arch_info, struct nds32_v3_common, nds32); } -#endif /* __NDS32_V3_H__ */ +#endif /* OPENOCD_TARGET_NDS32_V3_H */ diff --git a/src/target/nds32_v3_common.c b/src/target/nds32_v3_common.c index 6dc20982d..271ffdd1c 100644 --- a/src/target/nds32_v3_common.c +++ b/src/target/nds32_v3_common.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -370,7 +368,7 @@ int nds32_v3_target_request_data(struct target *target, } int nds32_v3_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); @@ -436,8 +434,8 @@ int nds32_v3_run_algorithm(struct target *target, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, - uint32_t exit_point, + target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info) { @@ -446,7 +444,7 @@ int nds32_v3_run_algorithm(struct target *target, return ERROR_FAIL; } -int nds32_v3_read_buffer(struct target *target, uint32_t address, +int nds32_v3_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -458,7 +456,7 @@ int nds32_v3_read_buffer(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -504,7 +502,7 @@ int nds32_v3_read_buffer(struct target *target, uint32_t address, return result; } -int nds32_v3_write_buffer(struct target *target, uint32_t address, +int nds32_v3_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -516,7 +514,7 @@ int nds32_v3_write_buffer(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -566,7 +564,7 @@ int nds32_v3_write_buffer(struct target *target, uint32_t address, return nds32_write_buffer(target, address, size, buffer); } -int nds32_v3_read_memory(struct target *target, uint32_t address, +int nds32_v3_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -578,7 +576,7 @@ int nds32_v3_read_memory(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -624,7 +622,7 @@ int nds32_v3_read_memory(struct target *target, uint32_t address, return result; } -int nds32_v3_write_memory(struct target *target, uint32_t address, +int nds32_v3_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -636,7 +634,7 @@ int nds32_v3_write_memory(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ diff --git a/src/target/nds32_v3_common.h b/src/target/nds32_v3_common.h index fd4a59071..23393e55d 100644 --- a/src/target/nds32_v3_common.h +++ b/src/target/nds32_v3_common.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_V3_COMMON_H__ -#define __NDS32_V3_COMMON_H__ + +#ifndef OPENOCD_TARGET_NDS32_V3_COMMON_H +#define OPENOCD_TARGET_NDS32_V3_COMMON_H #include "target.h" @@ -35,7 +34,7 @@ void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback int nds32_v3_target_request_data(struct target *target, uint32_t size, uint8_t *buffer); int nds32_v3_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum); + target_addr_t address, uint32_t count, uint32_t *checksum); int nds32_v3_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint); int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32); @@ -44,19 +43,19 @@ int nds32_v3_run_algorithm(struct target *target, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, - uint32_t exit_point, + target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info); -int nds32_v3_read_buffer(struct target *target, uint32_t address, +int nds32_v3_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); -int nds32_v3_write_buffer(struct target *target, uint32_t address, +int nds32_v3_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); -int nds32_v3_read_memory(struct target *target, uint32_t address, +int nds32_v3_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int nds32_v3_write_memory(struct target *target, uint32_t address, +int nds32_v3_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int nds32_v3_init_target(struct command_context *cmd_ctx, struct target *target); -#endif /* __NDS32_V3_COMMON_H__ */ +#endif /* OPENOCD_TARGET_NDS32_V3_COMMON_H */ diff --git a/src/target/nds32_v3m.c b/src/target/nds32_v3m.c index accc8d056..86903a51b 100644 --- a/src/target/nds32_v3m.c +++ b/src/target/nds32_v3m.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -52,7 +50,7 @@ static int nds32_v3m_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0xA); - LOG_DEBUG("Add hardware BP %u at %08" PRIx32, brp_num, + LOG_DEBUG("Add hardware BP %u at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num--; @@ -80,7 +78,7 @@ static int nds32_v3m_deactivate_hardware_breakpoint(struct target *target) else return ERROR_FAIL; - LOG_DEBUG("Remove hardware BP %u at %08" PRIx32, brp_num, + LOG_DEBUG("Remove hardware BP %u at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num--; @@ -127,7 +125,7 @@ static int nds32_v3m_activate_hardware_watchpoint(struct target *target) /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -168,7 +166,7 @@ static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3m->nds32.global_stop) { diff --git a/src/target/nds32_v3m.h b/src/target/nds32_v3m.h index d72c2ad43..1e7427c48 100644 --- a/src/target/nds32_v3m.h +++ b/src/target/nds32_v3m.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef __NDS32_V3M_H__ -#define __NDS32_V3M_H__ + +#ifndef OPENOCD_TARGET_NDS32_V3M_H +#define OPENOCD_TARGET_NDS32_V3M_H #include "nds32.h" @@ -49,5 +48,4 @@ static inline struct nds32_v3m_common *target_to_nds32_v3m(struct target *target return container_of(target->arch_info, struct nds32_v3m_common, nds32); } - -#endif /* __NDS32_V3M_H__ */ +#endif /* OPENOCD_TARGET_NDS32_V3M_H */ diff --git a/src/target/oocd_trace.c b/src/target/oocd_trace.c index e723efe04..627366d5d 100644 --- a/src/target/oocd_trace.c +++ b/src/target/oocd_trace.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/oocd_trace.h b/src/target/oocd_trace.h index 5773674d3..e7584e4c9 100644 --- a/src/target/oocd_trace.h +++ b/src/target/oocd_trace.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef OOCD_TRACE_H -#define OOCD_TRACE_H +#ifndef OPENOCD_TARGET_OOCD_TRACE_H +#define OPENOCD_TARGET_OOCD_TRACE_H #include @@ -52,4 +50,4 @@ struct oocd_trace { extern struct etm_capture_driver oocd_trace_capture_driver; -#endif /* OOCD_TRACE_TRACE_H */ +#endif /* OPENOCD_TARGET_OOCD_TRACE_H */ diff --git a/src/target/openrisc/Makefile.am b/src/target/openrisc/Makefile.am index b00a30d6f..5a2549a51 100644 --- a/src/target/openrisc/Makefile.am +++ b/src/target/openrisc/Makefile.am @@ -1,18 +1,12 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libopenrisc.la -libopenrisc_la_SOURCES = $(OPENRISC_SRC) - -OPENRISC_SRC = \ - or1k.c \ - or1k_du_adv.c \ - or1k_tap_mohor.c \ - or1k_tap_vjtag.c \ - or1k_tap_xilinx_bscan.c \ - jsp_server.c - -noinst_HEADERS = \ - or1k.h \ - or1k_du.h \ - or1k_tap.h \ - jsp_server.h +noinst_LTLIBRARIES += %D%/libopenrisc.la +%C%_libopenrisc_la_SOURCES = \ + %D%/or1k.c \ + %D%/or1k_du_adv.c \ + %D%/or1k_tap_mohor.c \ + %D%/or1k_tap_vjtag.c \ + %D%/or1k_tap_xilinx_bscan.c \ + %D%/jsp_server.c \ + %D%/or1k.h \ + %D%/or1k_du.h \ + %D%/or1k_tap.h \ + %D%/jsp_server.h diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c index 83e03ae3e..e581fb870 100644 --- a/src/target/openrisc/jsp_server.c +++ b/src/target/openrisc/jsp_server.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/openrisc/jsp_server.h b/src/target/openrisc/jsp_server.h index 3e7c1145d..f8e71215a 100644 --- a/src/target/openrisc/jsp_server.h +++ b/src/target/openrisc/jsp_server.h @@ -1,5 +1,5 @@ -#ifndef _JSP_SERVER_H_ -#define _JSP_SERVER_H_ +#ifndef OPENOCD_TARGET_OPENRISC_JSP_SERVER_H +#define OPENOCD_TARGET_OPENRISC_JSP_SERVER_H #include "or1k_tap.h" #include "or1k.h" @@ -14,4 +14,4 @@ struct jsp_service { int jsp_init(struct or1k_jtag *jtag_info, char *banner); int jsp_register_commands(struct command_context *cmd_ctx); -#endif /* _JSP_SERVER_H_ */ +#endif /* OPENOCD_TARGET_OPENRISC_JSP_SERVER_H */ diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index 33de63e2d..3895ddfaf 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -18,6 +18,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -858,7 +861,7 @@ static int or1k_resume_or_step(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address); + LOG_DEBUG("Unset breakpoint at 0x%08" TARGET_PRIxADDR, breakpoint->address); retval = or1k_remove_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; @@ -894,7 +897,8 @@ static int or1k_resume_or_step(struct target *target, int current, } static int or1k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, + int debug_execution) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -903,7 +907,7 @@ static int or1k_resume(struct target *target, int current, } static int or1k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -919,7 +923,7 @@ static int or1k_add_breakpoint(struct target *target, struct or1k_du *du_core = or1k_to_du(or1k); uint8_t data; - LOG_DEBUG("Adding breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, + LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); @@ -934,7 +938,7 @@ static int or1k_add_breakpoint(struct target *target, 1, &data); if (retval != ERROR_OK) { - LOG_ERROR("Error while reading the instruction at 0x%08" PRIx32, + LOG_ERROR("Error while reading the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } @@ -955,14 +959,15 @@ static int or1k_add_breakpoint(struct target *target, or1k_trap_insn); if (retval != ERROR_OK) { - LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" PRIx32, + LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ + uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, - OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); + OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; @@ -977,7 +982,7 @@ static int or1k_remove_breakpoint(struct target *target, struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Removing breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, + LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); @@ -993,14 +998,15 @@ static int or1k_remove_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) { - LOG_ERROR("Error while writing back the instruction at 0x%08" PRIx32, + LOG_ERROR("Error while writing back the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ + uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, - OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); + OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; @@ -1023,13 +1029,13 @@ static int or1k_remove_watchpoint(struct target *target, return ERROR_OK; } -static int or1k_read_memory(struct target *target, uint32_t address, +static int or1k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Read memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); + LOG_DEBUG("Read memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -1050,13 +1056,13 @@ static int or1k_read_memory(struct target *target, uint32_t address, return du_core->or1k_jtag_read_memory(&or1k->jtag, address, size, count, buffer); } -static int or1k_write_memory(struct target *target, uint32_t address, +static int or1k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Write memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); + LOG_DEBUG("Write memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("Target not halted"); @@ -1200,7 +1206,7 @@ int or1k_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *file return ERROR_FAIL; } -static int or1k_checksum_memory(struct target *target, uint32_t address, +static int or1k_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum) { return ERROR_FAIL; diff --git a/src/target/openrisc/or1k.h b/src/target/openrisc/or1k.h index 25024dc3d..c456ccbe2 100644 --- a/src/target/openrisc/or1k.h +++ b/src/target/openrisc/or1k.h @@ -18,10 +18,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef OR1K_H -#define OR1K_H +#ifndef OPENOCD_TARGET_OPENRISC_OR1K_H +#define OPENOCD_TARGET_OPENRISC_OR1K_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -152,4 +155,4 @@ enum or1k_debug_reg_nums { */ #define OR1K_ICBIR_CPU_REG_ADD ((4 << 11) + 2) /* IC Block Invalidate Register 0x2002 */ -#endif +#endif /* OPENOCD_TARGET_OPENRISC_OR1K_H */ diff --git a/src/target/openrisc/or1k_du.h b/src/target/openrisc/or1k_du.h index cc22fdb94..9828b0d22 100644 --- a/src/target/openrisc/or1k_du.h +++ b/src/target/openrisc/or1k_du.h @@ -11,10 +11,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef OR1K_DU -#define OR1K_DU +#ifndef OPENOCD_TARGET_OPENRISC_OR1K_DU_H +#define OPENOCD_TARGET_OPENRISC_OR1K_DU_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -72,5 +75,4 @@ int or1k_adv_jtag_jsp_xfer(struct or1k_jtag *jtag_info, int *out_len, unsigned char *out_buffer, int *in_len, unsigned char *in_buffer); -#endif - +#endif /* OPENOCD_TARGET_OPENRISC_OR1K_DU_H */ diff --git a/src/target/openrisc/or1k_du_adv.c b/src/target/openrisc/or1k_du_adv.c index e4681ffba..bdd6fc8cb 100644 --- a/src/target/openrisc/or1k_du_adv.c +++ b/src/target/openrisc/or1k_du_adv.c @@ -19,6 +19,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/openrisc/or1k_tap.h b/src/target/openrisc/or1k_tap.h index cce118973..2cf7da804 100644 --- a/src/target/openrisc/or1k_tap.h +++ b/src/target/openrisc/or1k_tap.h @@ -11,10 +11,13 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef _OR1K_TAP_H_ -#define _OR1K_TAP_H_ +#ifndef OPENOCD_TARGET_OPENRISC_OR1K_TAP_H +#define OPENOCD_TARGET_OPENRISC_OR1K_TAP_H #ifdef HAVE_CONFIG_H #include "config.h" @@ -36,4 +39,4 @@ struct or1k_tap_ip { const char *name; }; -#endif +#endif /* OPENOCD_TARGET_OPENRISC_OR1K_TAP_H */ diff --git a/src/target/openrisc/or1k_tap_mohor.c b/src/target/openrisc/or1k_tap_mohor.c index b654b1b53..1415e321c 100644 --- a/src/target/openrisc/or1k_tap_mohor.c +++ b/src/target/openrisc/or1k_tap_mohor.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/openrisc/or1k_tap_vjtag.c b/src/target/openrisc/or1k_tap_vjtag.c index c3b942b2e..607451a7c 100644 --- a/src/target/openrisc/or1k_tap_vjtag.c +++ b/src/target/openrisc/or1k_tap_vjtag.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/openrisc/or1k_tap_xilinx_bscan.c b/src/target/openrisc/or1k_tap_xilinx_bscan.c index 1e90b9398..a77c65ef8 100644 --- a/src/target/openrisc/or1k_tap_xilinx_bscan.c +++ b/src/target/openrisc/or1k_tap_xilinx_bscan.c @@ -11,6 +11,9 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/quark_x10xx.c b/src/target/quark_x10xx.c index 9a1ccb65d..189f6cc65 100644 --- a/src/target/quark_x10xx.c +++ b/src/target/quark_x10xx.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -18,8 +18,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . * * Contact Information: * Intel Corporation @@ -61,6 +60,7 @@ int quark_x10xx_target_create(struct target *t, Jim_Interp *interp) } x86_32_common_init_arch_info(t, x86_32); lakemont_init_arch_info(t, x86_32); + x86_32->core_type = LMT1; return ERROR_OK; } diff --git a/src/target/register.c b/src/target/register.c index 1c1717c8f..1d63e12f7 100644 --- a/src/target/register.c +++ b/src/target/register.c @@ -16,9 +16,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/register.h b/src/target/register.h index 7bac69b5a..d4c328160 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef REGISTER_H -#define REGISTER_H +#ifndef OPENOCD_TARGET_REGISTER_H +#define OPENOCD_TARGET_REGISTER_H struct target; @@ -116,17 +114,32 @@ struct reg_data_type { }; struct reg { + /** Canonical name of the register. */ const char *name; + /** Number that gdb uses to access this register. */ uint32_t number; + /* TODO. This should probably be const. */ struct reg_feature *feature; + /* TODO: When true, the caller will save this register before running any algorithm. */ bool caller_save; + /* Pointer to place where the value is stored, in the format understood by + * the binarybuffer.h functions. */ void *value; + /* The stored value needs to be written to the target. */ bool dirty; + /* When true, value is valid. */ bool valid; + /* When false, the register doesn't actually exist in the target. */ bool exist; + /* Size of the register in bits. */ uint32_t size; + /* Used for generating XML description of registers. Can be set to NULL for + * targets that don't use that. */ struct reg_data_type *reg_data_type; + /* Used for generating XML description of registers. Can be set to NULL for + * targets that don't use that. */ const char *group; + /* Pointer to architecture-specific info for this register. */ void *arch_info; const struct reg_arch_type *type; }; @@ -151,4 +164,4 @@ void register_cache_invalidate(struct reg_cache *cache); void register_init_dummy(struct reg *reg); -#endif /* REGISTER_H */ +#endif /* OPENOCD_TARGET_REGISTER_H */ diff --git a/src/target/smp.c b/src/target/smp.c index da9ee8b46..bdf81a0ee 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -66,7 +64,8 @@ int gdb_read_smp_packet(struct connection *connection, char hex_buffer[len * 2 + 1]; uint8_t buffer[len]; buf_set_u32(buffer, 0, len * 8, target->gdb_service->core[0]); - int pkt_len = hexify(hex_buffer, (char *)buffer, sizeof(buffer), sizeof(hex_buffer)); + size_t pkt_len = hexify(hex_buffer, buffer, sizeof(buffer), + sizeof(hex_buffer)); retval = gdb_put_packet(connection, hex_buffer, pkt_len); } diff --git a/src/target/smp.h b/src/target/smp.h index 69a5cd855..c3e6c6cea 100644 --- a/src/target/smp.h +++ b/src/target/smp.h @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ +#ifndef OPENOCD_TARGET_SMP_H +#define OPENOCD_TARGET_SMP_H + #include "server/server.h" int gdb_read_smp_packet(struct connection *connection, @@ -25,3 +26,4 @@ int gdb_read_smp_packet(struct connection *connection, int gdb_write_smp_packet(struct connection *connection, char const *packet, int packet_size); +#endif /* OPENOCD_TARGET_SMP_H */ diff --git a/src/target/startup.tcl b/src/target/startup.tcl index cf2813ba8..9bbc6e32c 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -65,7 +65,7 @@ proc ocd_process_reset_inner { MODE } { foreach t $targets { if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t invoke-event examine-start - set err [catch "$t arp_examine"] + set err [catch "$t arp_examine allow-defer"] if { $err == 0 } { $t invoke-event examine-end } @@ -111,6 +111,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + # Wait upto 1 second for target to halt. Why 1sec? Cause # the JTAG tap reset signal might be hooked to a slow # resistor/capacitor circuit - and it might take a while @@ -135,6 +141,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { diff --git a/src/target/target.c b/src/target/target.c index 598d7d5a8..372255332 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -34,9 +34,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -60,21 +58,21 @@ /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 -static int target_read_buffer_default(struct target *target, uint32_t address, - uint32_t count, uint8_t *buffer); -static int target_write_buffer_default(struct target *target, uint32_t address, - uint32_t count, const uint8_t *buffer); +static int target_read_buffer_default(struct target *target, target_addr_t address, + uint32_t count, uint8_t *buffer); +static int target_write_buffer_default(struct target *target, target_addr_t address, + uint32_t count, const uint8_t *buffer); static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); + int argc, Jim_Obj * const *argv); static int target_mem2array(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj * const *argv); + int argc, Jim_Obj * const *argv); static int target_register_user_commands(struct command_context *cmd_ctx); static int target_get_gdb_fileio_info_default(struct target *target, - struct gdb_fileio_info *fileio_info); + struct gdb_fileio_info *fileio_info); static int target_gdb_fileio_end_default(struct target *target, int retcode, - int fileio_errno, bool ctrl_c); + int fileio_errno, bool ctrl_c); static int target_profiling_default(struct target *target, uint32_t *samples, - uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); /* targets */ extern struct target_type arm7tdmi_target; @@ -90,8 +88,10 @@ extern struct target_type dragonite_target; extern struct target_type xscale_target; extern struct target_type cortexm_target; extern struct target_type cortexa_target; +extern struct target_type aarch64_target; extern struct target_type cortexr4_target; extern struct target_type arm11_target; +extern struct target_type ls1_sap_target; extern struct target_type mips_m4k_target; extern struct target_type avr_target; extern struct target_type dsp563xx_target; @@ -104,6 +104,10 @@ extern struct target_type nds32_v3_target; extern struct target_type nds32_v3m_target; extern struct target_type or1k_target; extern struct target_type quark_x10xx_target; +extern struct target_type quark_d20xx_target; +#if BUILD_RISCV == 1 +extern struct target_type riscv_target; +#endif static struct target_type *target_types[] = { &arm7tdmi_target, @@ -121,6 +125,7 @@ static struct target_type *target_types[] = { &cortexa_target, &cortexr4_target, &arm11_target, + &ls1_sap_target, &mips_m4k_target, &avr_target, &dsp563xx_target, @@ -133,7 +138,14 @@ static struct target_type *target_types[] = { &nds32_v3m_target, &or1k_target, &quark_x10xx_target, - NULL, + &quark_d20xx_target, +#if BUILD_TARGET64 + &aarch64_target, +#endif +#if BUILD_RISCV == 1 + &riscv_target, +#endif + NULL, }; struct target *all_targets; @@ -144,421 +156,425 @@ LIST_HEAD(target_trace_callback_list); static const int polling_interval = 100; static const Jim_Nvp nvp_assert[] = { - { .name = "assert", NVP_ASSERT }, - { .name = "deassert", NVP_DEASSERT }, - { .name = "T", NVP_ASSERT }, - { .name = "F", NVP_DEASSERT }, - { .name = "t", NVP_ASSERT }, - { .name = "f", NVP_DEASSERT }, - { .name = NULL, .value = -1 } + { .name = "assert", NVP_ASSERT }, + { .name = "deassert", NVP_DEASSERT }, + { .name = "T", NVP_ASSERT }, + { .name = "F", NVP_DEASSERT }, + { .name = "t", NVP_ASSERT }, + { .name = "f", NVP_DEASSERT }, + { .name = NULL, .value = -1 } }; static const Jim_Nvp nvp_error_target[] = { - { .value = ERROR_TARGET_INVALID, .name = "err-invalid" }, - { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" }, - { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" }, - { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" }, - { .value = ERROR_TARGET_FAILURE, .name = "err-failure" }, - { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" }, - { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" }, - { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" }, - { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" }, - { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" }, - { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" }, - { .value = -1, .name = NULL } + { .value = ERROR_TARGET_INVALID, .name = "err-invalid" }, + { .value = ERROR_TARGET_INIT_FAILED, .name = "err-init-failed" }, + { .value = ERROR_TARGET_TIMEOUT, .name = "err-timeout" }, + { .value = ERROR_TARGET_NOT_HALTED, .name = "err-not-halted" }, + { .value = ERROR_TARGET_FAILURE, .name = "err-failure" }, + { .value = ERROR_TARGET_UNALIGNED_ACCESS , .name = "err-unaligned-access" }, + { .value = ERROR_TARGET_DATA_ABORT , .name = "err-data-abort" }, + { .value = ERROR_TARGET_RESOURCE_NOT_AVAILABLE , .name = "err-resource-not-available" }, + { .value = ERROR_TARGET_TRANSLATION_FAULT , .name = "err-translation-fault" }, + { .value = ERROR_TARGET_NOT_RUNNING, .name = "err-not-running" }, + { .value = ERROR_TARGET_NOT_EXAMINED, .name = "err-not-examined" }, + { .value = -1, .name = NULL } }; static const char *target_strerror_safe(int err) { - const Jim_Nvp *n; - - n = Jim_Nvp_value2name_simple(nvp_error_target, err); - if (n->name == NULL) - return "unknown"; - else - return n->name; + const Jim_Nvp *n; + + n = Jim_Nvp_value2name_simple(nvp_error_target, err); + if (n->name == NULL) + return "unknown"; + else + return n->name; } static const Jim_Nvp nvp_target_event[] = { - - { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, - { .value = TARGET_EVENT_HALTED, .name = "halted" }, - { .value = TARGET_EVENT_RESUMED, .name = "resumed" }, - { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, - { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" }, - - { .name = "gdb-start", .value = TARGET_EVENT_GDB_START }, - { .name = "gdb-end", .value = TARGET_EVENT_GDB_END }, - - { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, - { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, - { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, - { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, - { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, - { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, - { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" }, - { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, - { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, - { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, - { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, - { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, - - { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, - { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, - - { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" }, - { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" }, - - { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" }, - { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" }, - - { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" }, - { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" }, - - { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, - { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, - - { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" }, - - { .name = NULL, .value = -1 } + + { .value = TARGET_EVENT_GDB_HALT, .name = "gdb-halt" }, + { .value = TARGET_EVENT_HALTED, .name = "halted" }, + { .value = TARGET_EVENT_RESUMED, .name = "resumed" }, + { .value = TARGET_EVENT_RESUME_START, .name = "resume-start" }, + { .value = TARGET_EVENT_RESUME_END, .name = "resume-end" }, + + { .name = "gdb-start", .value = TARGET_EVENT_GDB_START }, + { .name = "gdb-end", .value = TARGET_EVENT_GDB_END }, + + { .value = TARGET_EVENT_RESET_START, .name = "reset-start" }, + { .value = TARGET_EVENT_RESET_ASSERT_PRE, .name = "reset-assert-pre" }, + { .value = TARGET_EVENT_RESET_ASSERT, .name = "reset-assert" }, + { .value = TARGET_EVENT_RESET_ASSERT_POST, .name = "reset-assert-post" }, + { .value = TARGET_EVENT_RESET_DEASSERT_PRE, .name = "reset-deassert-pre" }, + { .value = TARGET_EVENT_RESET_DEASSERT_POST, .name = "reset-deassert-post" }, + { .value = TARGET_EVENT_RESET_HALT_PRE, .name = "reset-halt-pre" }, + { .value = TARGET_EVENT_RESET_HALT_POST, .name = "reset-halt-post" }, + { .value = TARGET_EVENT_RESET_WAIT_PRE, .name = "reset-wait-pre" }, + { .value = TARGET_EVENT_RESET_WAIT_POST, .name = "reset-wait-post" }, + { .value = TARGET_EVENT_RESET_INIT, .name = "reset-init" }, + { .value = TARGET_EVENT_RESET_END, .name = "reset-end" }, + + { .value = TARGET_EVENT_EXAMINE_START, .name = "examine-start" }, + { .value = TARGET_EVENT_EXAMINE_END, .name = "examine-end" }, + + { .value = TARGET_EVENT_DEBUG_HALTED, .name = "debug-halted" }, + { .value = TARGET_EVENT_DEBUG_RESUMED, .name = "debug-resumed" }, + + { .value = TARGET_EVENT_GDB_ATTACH, .name = "gdb-attach" }, + { .value = TARGET_EVENT_GDB_DETACH, .name = "gdb-detach" }, + + { .value = TARGET_EVENT_GDB_FLASH_WRITE_START, .name = "gdb-flash-write-start" }, + { .value = TARGET_EVENT_GDB_FLASH_WRITE_END , .name = "gdb-flash-write-end" }, + + { .value = TARGET_EVENT_GDB_FLASH_ERASE_START, .name = "gdb-flash-erase-start" }, + { .value = TARGET_EVENT_GDB_FLASH_ERASE_END , .name = "gdb-flash-erase-end" }, + + { .value = TARGET_EVENT_TRACE_CONFIG, .name = "trace-config" }, + + { .name = NULL, .value = -1 } }; static const Jim_Nvp nvp_target_state[] = { - { .name = "unknown", .value = TARGET_UNKNOWN }, - { .name = "running", .value = TARGET_RUNNING }, - { .name = "halted", .value = TARGET_HALTED }, - { .name = "reset", .value = TARGET_RESET }, - { .name = "debug-running", .value = TARGET_DEBUG_RUNNING }, - { .name = NULL, .value = -1 }, + { .name = "unknown", .value = TARGET_UNKNOWN }, + { .name = "running", .value = TARGET_RUNNING }, + { .name = "halted", .value = TARGET_HALTED }, + { .name = "reset", .value = TARGET_RESET }, + { .name = "debug-running", .value = TARGET_DEBUG_RUNNING }, + { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_target_debug_reason[] = { - { .name = "debug-request" , .value = DBG_REASON_DBGRQ }, - { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT }, - { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT }, - { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT }, - { .name = "single-step" , .value = DBG_REASON_SINGLESTEP }, - { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED }, - { .name = "program-exit" , .value = DBG_REASON_EXIT }, - { .name = "undefined" , .value = DBG_REASON_UNDEFINED }, - { .name = NULL, .value = -1 }, + { .name = "debug-request" , .value = DBG_REASON_DBGRQ }, + { .name = "breakpoint" , .value = DBG_REASON_BREAKPOINT }, + { .name = "watchpoint" , .value = DBG_REASON_WATCHPOINT }, + { .name = "watchpoint-and-breakpoint", .value = DBG_REASON_WPTANDBKPT }, + { .name = "single-step" , .value = DBG_REASON_SINGLESTEP }, + { .name = "target-not-halted" , .value = DBG_REASON_NOTHALTED }, + { .name = "program-exit" , .value = DBG_REASON_EXIT }, + { .name = "undefined" , .value = DBG_REASON_UNDEFINED }, + { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_target_endian[] = { - { .name = "big", .value = TARGET_BIG_ENDIAN }, - { .name = "little", .value = TARGET_LITTLE_ENDIAN }, - { .name = "be", .value = TARGET_BIG_ENDIAN }, - { .name = "le", .value = TARGET_LITTLE_ENDIAN }, - { .name = NULL, .value = -1 }, + { .name = "big", .value = TARGET_BIG_ENDIAN }, + { .name = "little", .value = TARGET_LITTLE_ENDIAN }, + { .name = "be", .value = TARGET_BIG_ENDIAN }, + { .name = "le", .value = TARGET_LITTLE_ENDIAN }, + { .name = NULL, .value = -1 }, }; static const Jim_Nvp nvp_reset_modes[] = { - { .name = "unknown", .value = RESET_UNKNOWN }, - { .name = "run" , .value = RESET_RUN }, - { .name = "halt" , .value = RESET_HALT }, - { .name = "init" , .value = RESET_INIT }, - { .name = NULL , .value = -1 }, + { .name = "unknown", .value = RESET_UNKNOWN }, + { .name = "run" , .value = RESET_RUN }, + { .name = "halt" , .value = RESET_HALT }, + { .name = "init" , .value = RESET_INIT }, + { .name = NULL , .value = -1 }, }; const char *debug_reason_name(struct target *t) { - const char *cp; - - cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason, - t->debug_reason)->name; - if (!cp) { - LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason)); - cp = "(*BUG*unknown*BUG*)"; - } - return cp; + const char *cp; + + cp = Jim_Nvp_value2name_simple(nvp_target_debug_reason, + t->debug_reason)->name; + if (!cp) { + LOG_ERROR("Invalid debug reason: %d", (int)(t->debug_reason)); + cp = "(*BUG*unknown*BUG*)"; + } + return cp; } const char *target_state_name(struct target *t) { - const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name; - if (!cp) { - LOG_ERROR("Invalid target state: %d", (int)(t->state)); - cp = "(*BUG*unknown*BUG*)"; - } - return cp; + const char *cp; + cp = Jim_Nvp_value2name_simple(nvp_target_state, t->state)->name; + if (!cp) { + LOG_ERROR("Invalid target state: %d", (int)(t->state)); + cp = "(*BUG*unknown*BUG*)"; + } + + if (!target_was_examined(t) && t->defer_examine) + cp = "examine deferred"; + + return cp; } const char *target_event_name(enum target_event event) { - const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name; - if (!cp) { - LOG_ERROR("Invalid target event: %d", (int)(event)); - cp = "(*BUG*unknown*BUG*)"; - } - return cp; + const char *cp; + cp = Jim_Nvp_value2name_simple(nvp_target_event, event)->name; + if (!cp) { + LOG_ERROR("Invalid target event: %d", (int)(event)); + cp = "(*BUG*unknown*BUG*)"; + } + return cp; } const char *target_reset_mode_name(enum target_reset_mode reset_mode) { - const char *cp; - cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name; - if (!cp) { - LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode)); - cp = "(*BUG*unknown*BUG*)"; - } - return cp; + const char *cp; + cp = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name; + if (!cp) { + LOG_ERROR("Invalid target reset mode: %d", (int)(reset_mode)); + cp = "(*BUG*unknown*BUG*)"; + } + return cp; } /* determine the number of the new target */ static int new_target_number(void) { - struct target *t; - int x; - - /* number is 0 based */ - x = -1; - t = all_targets; - while (t) { - if (x < t->target_number) - x = t->target_number; - t = t->next; - } - return x + 1; + struct target *t; + int x; + + /* number is 0 based */ + x = -1; + t = all_targets; + while (t) { + if (x < t->target_number) + x = t->target_number; + t = t->next; + } + return x + 1; } /* read a uint64_t from a buffer in target memory endianness */ uint64_t target_buffer_get_u64(struct target *target, const uint8_t *buffer) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - return le_to_h_u64(buffer); - else - return be_to_h_u64(buffer); + if (target->endianness == TARGET_LITTLE_ENDIAN) + return le_to_h_u64(buffer); + else + return be_to_h_u64(buffer); } /* read a uint32_t from a buffer in target memory endianness */ uint32_t target_buffer_get_u32(struct target *target, const uint8_t *buffer) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - return le_to_h_u32(buffer); - else - return be_to_h_u32(buffer); + if (target->endianness == TARGET_LITTLE_ENDIAN) + return le_to_h_u32(buffer); + else + return be_to_h_u32(buffer); } /* read a uint24_t from a buffer in target memory endianness */ uint32_t target_buffer_get_u24(struct target *target, const uint8_t *buffer) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - return le_to_h_u24(buffer); - else - return be_to_h_u24(buffer); + if (target->endianness == TARGET_LITTLE_ENDIAN) + return le_to_h_u24(buffer); + else + return be_to_h_u24(buffer); } /* read a uint16_t from a buffer in target memory endianness */ uint16_t target_buffer_get_u16(struct target *target, const uint8_t *buffer) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - return le_to_h_u16(buffer); - else - return be_to_h_u16(buffer); + if (target->endianness == TARGET_LITTLE_ENDIAN) + return le_to_h_u16(buffer); + else + return be_to_h_u16(buffer); } /* read a uint8_t from a buffer in target memory endianness */ static uint8_t target_buffer_get_u8(struct target *target, const uint8_t *buffer) { - return *buffer & 0x0ff; + return *buffer & 0x0ff; } /* write a uint64_t to a buffer in target memory endianness */ void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t value) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - h_u64_to_le(buffer, value); - else - h_u64_to_be(buffer, value); + if (target->endianness == TARGET_LITTLE_ENDIAN) + h_u64_to_le(buffer, value); + else + h_u64_to_be(buffer, value); } /* write a uint32_t to a buffer in target memory endianness */ void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - h_u32_to_le(buffer, value); - else - h_u32_to_be(buffer, value); + if (target->endianness == TARGET_LITTLE_ENDIAN) + h_u32_to_le(buffer, value); + else + h_u32_to_be(buffer, value); } /* write a uint24_t to a buffer in target memory endianness */ void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - h_u24_to_le(buffer, value); - else - h_u24_to_be(buffer, value); + if (target->endianness == TARGET_LITTLE_ENDIAN) + h_u24_to_le(buffer, value); + else + h_u24_to_be(buffer, value); } /* write a uint16_t to a buffer in target memory endianness */ void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value) { - if (target->endianness == TARGET_LITTLE_ENDIAN) - h_u16_to_le(buffer, value); - else - h_u16_to_be(buffer, value); + if (target->endianness == TARGET_LITTLE_ENDIAN) + h_u16_to_le(buffer, value); + else + h_u16_to_be(buffer, value); } /* write a uint8_t to a buffer in target memory endianness */ static void target_buffer_set_u8(struct target *target, uint8_t *buffer, uint8_t value) { - *buffer = value; + *buffer = value; } /* write a uint64_t array to a buffer in target memory endianness */ void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf) { - uint32_t i; - for (i = 0; i < count; i++) - dstbuf[i] = target_buffer_get_u64(target, &buffer[i * 8]); + uint32_t i; + for (i = 0; i < count; i++) + dstbuf[i] = target_buffer_get_u64(target, &buffer[i * 8]); } /* write a uint32_t array to a buffer in target memory endianness */ void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf) { - uint32_t i; - for (i = 0; i < count; i++) - dstbuf[i] = target_buffer_get_u32(target, &buffer[i * 4]); + uint32_t i; + for (i = 0; i < count; i++) + dstbuf[i] = target_buffer_get_u32(target, &buffer[i * 4]); } /* write a uint16_t array to a buffer in target memory endianness */ void target_buffer_get_u16_array(struct target *target, const uint8_t *buffer, uint32_t count, uint16_t *dstbuf) { - uint32_t i; - for (i = 0; i < count; i++) - dstbuf[i] = target_buffer_get_u16(target, &buffer[i * 2]); + uint32_t i; + for (i = 0; i < count; i++) + dstbuf[i] = target_buffer_get_u16(target, &buffer[i * 2]); } /* write a uint64_t array to a buffer in target memory endianness */ void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_t count, const uint64_t *srcbuf) { - uint32_t i; - for (i = 0; i < count; i++) - target_buffer_set_u64(target, &buffer[i * 8], srcbuf[i]); + uint32_t i; + for (i = 0; i < count; i++) + target_buffer_set_u64(target, &buffer[i * 8], srcbuf[i]); } /* write a uint32_t array to a buffer in target memory endianness */ void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf) { - uint32_t i; - for (i = 0; i < count; i++) - target_buffer_set_u32(target, &buffer[i * 4], srcbuf[i]); + uint32_t i; + for (i = 0; i < count; i++) + target_buffer_set_u32(target, &buffer[i * 4], srcbuf[i]); } /* write a uint16_t array to a buffer in target memory endianness */ void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf) { - uint32_t i; - for (i = 0; i < count; i++) - target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]); + uint32_t i; + for (i = 0; i < count; i++) + target_buffer_set_u16(target, &buffer[i * 2], srcbuf[i]); } /* return a pointer to a configured target; id is name or number */ struct target *get_target(const char *id) { - struct target *target; - - /* try as tcltarget name */ - for (target = all_targets; target; target = target->next) { - if (target_name(target) == NULL) - continue; - if (strcmp(id, target_name(target)) == 0) - return target; - } - - /* It's OK to remove this fallback sometime after August 2010 or so */ - - /* no match, try as number */ - unsigned num; - if (parse_uint(id, &num) != ERROR_OK) - return NULL; - - for (target = all_targets; target; target = target->next) { - if (target->target_number == (int)num) { - LOG_WARNING("use '%s' as target identifier, not '%u'", - target_name(target), num); - return target; - } - } - - return NULL; + struct target *target; + + /* try as tcltarget name */ + for (target = all_targets; target; target = target->next) { + if (target_name(target) == NULL) + continue; + if (strcmp(id, target_name(target)) == 0) + return target; + } + + /* It's OK to remove this fallback sometime after August 2010 or so */ + + /* no match, try as number */ + unsigned num; + if (parse_uint(id, &num) != ERROR_OK) + return NULL; + + for (target = all_targets; target; target = target->next) { + if (target->target_number == (int)num) { + LOG_WARNING("use '%s' as target identifier, not '%u'", + target_name(target), num); + return target; + } + } + + return NULL; } /* returns a pointer to the n-th configured target */ struct target *get_target_by_num(int num) { - struct target *target = all_targets; - - while (target) { - if (target->target_number == num) - return target; - target = target->next; - } - - return NULL; + struct target *target = all_targets; + + while (target) { + if (target->target_number == num) + return target; + target = target->next; + } + + return NULL; } struct target *get_current_target(struct command_context *cmd_ctx) { - struct target *target = get_target_by_num(cmd_ctx->current_target); - - if (target == NULL) { - LOG_ERROR("BUG: current_target out of bounds"); - exit(-1); - } - - return target; + struct target *target = get_target_by_num(cmd_ctx->current_target); + + if (target == NULL) { + LOG_ERROR("BUG: current_target out of bounds"); + exit(-1); + } + + return target; } int target_poll(struct target *target) { - int retval; - - /* We can't poll until after examine */ - if (!target_was_examined(target)) { - /* Fail silently lest we pollute the log */ - return ERROR_FAIL; - } - - retval = target->type->poll(target); - if (retval != ERROR_OK) - return retval; - - if (target->halt_issued) { - if (target->state == TARGET_HALTED) - target->halt_issued = false; - else { - long long t = timeval_ms() - target->halt_issued_time; - if (t > DEFAULT_HALT_TIMEOUT) { - target->halt_issued = false; - LOG_INFO("Halt timed out, wake up GDB."); - target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); - } - } - } - - return ERROR_OK; + int retval; + + /* We can't poll until after examine */ + if (!target_was_examined(target)) { + /* Fail silently lest we pollute the log */ + return ERROR_FAIL; + } + + retval = target->type->poll(target); + if (retval != ERROR_OK) + return retval; + + if (target->halt_issued) { + if (target->state == TARGET_HALTED) + target->halt_issued = false; + else { + int64_t t = timeval_ms() - target->halt_issued_time; + if (t > DEFAULT_HALT_TIMEOUT) { + target->halt_issued = false; + LOG_INFO("Halt timed out, wake up GDB."); + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); + } + } + } + + return ERROR_OK; } int target_halt(struct target *target) { - int retval; - /* We can't poll until after examine */ - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - retval = target->type->halt(target); - if (retval != ERROR_OK) - return retval; - - target->halt_issued = true; - target->halt_issued_time = timeval_ms(); - - return ERROR_OK; + int retval; + /* We can't poll until after examine */ + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + retval = target->type->halt(target); + if (retval != ERROR_OK) + return retval; + + target->halt_issued = true; + target->halt_issued_time = timeval_ms(); + + return ERROR_OK; } /** @@ -591,124 +607,125 @@ int target_halt(struct target *target) * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ -int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) -{ - int retval; - - /* We can't poll until after examine */ - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - target_call_event_callbacks(target, TARGET_EVENT_RESUME_START); - - /* note that resume *must* be asynchronous. The CPU can halt before - * we poll. The CPU can even halt at the current PC as a result of - * a software breakpoint being inserted by (a bug?) the application. - */ - retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); - if (retval != ERROR_OK) - return retval; - - target_call_event_callbacks(target, TARGET_EVENT_RESUME_END); - - return retval; +int target_resume(struct target *target, int current, target_addr_t address, + int handle_breakpoints, int debug_execution) +{ + int retval; + + /* We can't poll until after examine */ + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + target_call_event_callbacks(target, TARGET_EVENT_RESUME_START); + + /* note that resume *must* be asynchronous. The CPU can halt before + * we poll. The CPU can even halt at the current PC as a result of + * a software breakpoint being inserted by (a bug?) the application. + */ + retval = target->type->resume(target, current, address, handle_breakpoints, debug_execution); + if (retval != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_RESUME_END); + + return retval; } static int target_process_reset(struct command_context *cmd_ctx, enum target_reset_mode reset_mode) { - char buf[100]; - int retval; - Jim_Nvp *n; - n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode); - if (n->name == NULL) { - LOG_ERROR("invalid reset mode"); - return ERROR_FAIL; - } - - struct target *target; - for (target = all_targets; target; target = target->next) - target_call_reset_callbacks(target, reset_mode); - - /* disable polling during reset to make reset event scripts - * more predictable, i.e. dr/irscan & pathmove in events will - * not have JTAG operations injected into the middle of a sequence. - */ - bool save_poll = jtag_poll_get_enabled(); - - jtag_poll_set_enabled(false); - - sprintf(buf, "ocd_process_reset %s", n->name); - retval = Jim_Eval(cmd_ctx->interp, buf); - - jtag_poll_set_enabled(save_poll); - - if (retval != JIM_OK) { - Jim_MakeErrorMessage(cmd_ctx->interp); - command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); - return ERROR_FAIL; - } - - /* We want any events to be processed before the prompt */ - retval = target_call_timer_callbacks_now(); - - for (target = all_targets; target; target = target->next) { - target->type->check_reset(target); - target->running_alg = false; - } - - return retval; + char buf[100]; + int retval; + Jim_Nvp *n; + n = Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode); + if (n->name == NULL) { + LOG_ERROR("invalid reset mode"); + return ERROR_FAIL; + } + + struct target *target; + for (target = all_targets; target; target = target->next) + target_call_reset_callbacks(target, reset_mode); + + /* disable polling during reset to make reset event scripts + * more predictable, i.e. dr/irscan & pathmove in events will + * not have JTAG operations injected into the middle of a sequence. + */ + bool save_poll = jtag_poll_get_enabled(); + + jtag_poll_set_enabled(false); + + sprintf(buf, "ocd_process_reset %s", n->name); + retval = Jim_Eval(cmd_ctx->interp, buf); + + jtag_poll_set_enabled(save_poll); + + if (retval != JIM_OK) { + Jim_MakeErrorMessage(cmd_ctx->interp); + command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL)); + return ERROR_FAIL; + } + + /* We want any events to be processed before the prompt */ + retval = target_call_timer_callbacks_now(); + + for (target = all_targets; target; target = target->next) { + target->type->check_reset(target); + target->running_alg = false; + } + + return retval; } static int identity_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { - *physical = virtual; - return ERROR_OK; + *physical = virtual; + return ERROR_OK; } static int no_mmu(struct target *target, int *enabled) { - *enabled = 0; - return ERROR_OK; + *enabled = 0; + return ERROR_OK; } static int default_examine(struct target *target) { - target_set_examined(target); - return ERROR_OK; + target_set_examined(target); + return ERROR_OK; } /* no check by default */ static int default_check_reset(struct target *target) { - return ERROR_OK; + return ERROR_OK; } int target_examine_one(struct target *target) { - target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); - - int retval = target->type->examine(target); - if (retval != ERROR_OK) - return retval; - - target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); - - return ERROR_OK; + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_START); + + int retval = target->type->examine(target); + if (retval != ERROR_OK) + return retval; + + target_call_event_callbacks(target, TARGET_EVENT_EXAMINE_END); + + return ERROR_OK; } static int jtag_enable_callback(enum jtag_event event, void *priv) { - struct target *target = priv; - - if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled) - return ERROR_OK; - - jtag_unregister_event_callback(jtag_enable_callback, target); - - return target_examine_one(target); + struct target *target = priv; + + if (event != JTAG_TAP_EVENT_ENABLE || !target->tap->enabled) + return ERROR_OK; + + jtag_unregister_event_callback(jtag_enable_callback, target); + + return target_examine_one(target); } /* Targets that correctly implement init + examine, i.e. @@ -718,41 +735,44 @@ static int jtag_enable_callback(enum jtag_event event, void *priv) */ int target_examine(void) { - int retval = ERROR_OK; - struct target *target; - - for (target = all_targets; target; target = target->next) { - /* defer examination, but don't skip it */ - if (!target->tap->enabled) { - jtag_register_event_callback(jtag_enable_callback, - target); - continue; - } - - retval = target_examine_one(target); - if (retval != ERROR_OK) - return retval; - } - return retval; + int retval = ERROR_OK; + struct target *target; + + for (target = all_targets; target; target = target->next) { + /* defer examination, but don't skip it */ + if (!target->tap->enabled) { + jtag_register_event_callback(jtag_enable_callback, + target); + continue; + } + + if (target->defer_examine) + continue; + + retval = target_examine_one(target); + if (retval != ERROR_OK) + return retval; + } + return retval; } const char *target_type_name(struct target *target) { - return target->type->name; + return target->type->name; } static int target_soft_reset_halt(struct target *target) { - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - if (!target->type->soft_reset_halt) { - LOG_ERROR("Target %s does not support soft_reset_halt", - target_name(target)); - return ERROR_FAIL; - } - return target->type->soft_reset_halt(target); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + if (!target->type->soft_reset_halt) { + LOG_ERROR("Target %s does not support soft_reset_halt", + target_name(target)); + return ERROR_FAIL; + } + return target->type->soft_reset_halt(target); } /** @@ -767,32 +787,32 @@ static int target_soft_reset_halt(struct target *target) * @param arch_info target-specific description of the algorithm. */ int target_run_algorithm(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_param, - uint32_t entry_point, uint32_t exit_point, - int timeout_ms, void *arch_info) -{ - int retval = ERROR_FAIL; - - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - goto done; - } - if (!target->type->run_algorithm) { - LOG_ERROR("Target type '%s' does not support %s", - target_type_name(target), __func__); - goto done; - } - - target->running_alg = true; - retval = target->type->run_algorithm(target, - num_mem_params, mem_params, - num_reg_params, reg_param, - entry_point, exit_point, timeout_ms, arch_info); - target->running_alg = false; - + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_param, + uint32_t entry_point, uint32_t exit_point, + int timeout_ms, void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + goto done; + } + if (!target->type->run_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + + target->running_alg = true; + retval = target->type->run_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_param, + entry_point, exit_point, timeout_ms, arch_info); + target->running_alg = false; + done: - return retval; + return retval; } /** @@ -803,35 +823,35 @@ int target_run_algorithm(struct target *target, * @param arch_info target-specific description of the algorithm. */ int target_start_algorithm(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, - void *arch_info) -{ - int retval = ERROR_FAIL; - - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - goto done; - } - if (!target->type->start_algorithm) { - LOG_ERROR("Target type '%s' does not support %s", - target_type_name(target), __func__); - goto done; - } - if (target->running_alg) { - LOG_ERROR("Target is already running an algorithm"); - goto done; - } - - target->running_alg = true; - retval = target->type->start_algorithm(target, - num_mem_params, mem_params, - num_reg_params, reg_params, - entry_point, exit_point, arch_info); - + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t entry_point, uint32_t exit_point, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + goto done; + } + if (!target->type->start_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (target->running_alg) { + LOG_ERROR("Target is already running an algorithm"); + goto done; + } + + target->running_alg = true; + retval = target->type->start_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, exit_point, arch_info); + done: - return retval; + return retval; } /** @@ -841,32 +861,32 @@ int target_start_algorithm(struct target *target, * @param arch_info target-specific description of the algorithm. */ int target_wait_algorithm(struct target *target, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, - void *arch_info) -{ - int retval = ERROR_FAIL; - - if (!target->type->wait_algorithm) { - LOG_ERROR("Target type '%s' does not support %s", - target_type_name(target), __func__); - goto done; - } - if (!target->running_alg) { - LOG_ERROR("Target is not running an algorithm"); - goto done; - } - - retval = target->type->wait_algorithm(target, - num_mem_params, mem_params, - num_reg_params, reg_params, - exit_point, timeout_ms, arch_info); - if (retval != ERROR_TARGET_TIMEOUT) - target->running_alg = false; - + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t exit_point, int timeout_ms, + void *arch_info) +{ + int retval = ERROR_FAIL; + + if (!target->type->wait_algorithm) { + LOG_ERROR("Target type '%s' does not support %s", + target_type_name(target), __func__); + goto done; + } + if (!target->running_alg) { + LOG_ERROR("Target is not running an algorithm"); + goto done; + } + + retval = target->type->wait_algorithm(target, + num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, timeout_ms, arch_info); + if (retval != ERROR_TARGET_TIMEOUT) + target->running_alg = false; + done: - return retval; + return retval; } /** @@ -879,305 +899,347 @@ int target_wait_algorithm(struct target *target, */ int target_run_flash_async_algorithm(struct target *target, - const uint8_t *buffer, uint32_t count, int block_size, - int num_mem_params, struct mem_param *mem_params, - int num_reg_params, struct reg_param *reg_params, - uint32_t buffer_start, uint32_t buffer_size, - uint32_t entry_point, uint32_t exit_point, void *arch_info) -{ - int retval; - int timeout = 0; - - const uint8_t *buffer_orig = buffer; - - /* Set up working area. First word is write pointer, second word is read pointer, - * rest is fifo data area. */ - uint32_t wp_addr = buffer_start; - uint32_t rp_addr = buffer_start + 4; - uint32_t fifo_start_addr = buffer_start + 8; - uint32_t fifo_end_addr = buffer_start + buffer_size; - - uint32_t wp = fifo_start_addr; - uint32_t rp = fifo_start_addr; - - /* validate block_size is 2^n */ - assert(!block_size || !(block_size & (block_size - 1))); - - retval = target_write_u32(target, wp_addr, wp); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, rp_addr, rp); - if (retval != ERROR_OK) - return retval; - - /* Start up algorithm on target and let it idle while writing the first chunk */ - retval = target_start_algorithm(target, num_mem_params, mem_params, - num_reg_params, reg_params, - entry_point, - exit_point, - arch_info); - - if (retval != ERROR_OK) { - LOG_ERROR("error starting target flash write algorithm"); - return retval; - } - - while (count > 0) { - - retval = target_read_u32(target, rp_addr, &rp); - if (retval != ERROR_OK) { - LOG_ERROR("failed to get read pointer"); - break; - } - - LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, - (size_t) (buffer - buffer_orig), count, wp, rp); - - if (rp == 0) { - LOG_ERROR("flash write algorithm aborted by target"); - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } - - if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) { - LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp); - break; - } - - /* Count the number of bytes available in the fifo without - * crossing the wrap around. Make sure to not fill it completely, - * because that would make wp == rp and that's the empty condition. */ - uint32_t thisrun_bytes; - if (rp > wp) - thisrun_bytes = rp - wp - block_size; - else if (rp > fifo_start_addr) - thisrun_bytes = fifo_end_addr - wp; - else - thisrun_bytes = fifo_end_addr - wp - block_size; - - if (thisrun_bytes == 0) { - /* Throttle polling a bit if transfer is (much) faster than flash - * programming. The exact delay shouldn't matter as long as it's - * less than buffer size / flash speed. This is very unlikely to - * run when using high latency connections such as USB. */ - alive_sleep(10); - - /* to stop an infinite loop on some targets check and increment a timeout - * this issue was observed on a stellaris using the new ICDI interface */ - if (timeout++ >= 500) { - LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); - return ERROR_FLASH_OPERATION_FAILED; - } - continue; - } - - /* reset our timeout */ - timeout = 0; - - /* Limit to the amount of data we actually want to write */ - if (thisrun_bytes > count * block_size) - thisrun_bytes = count * block_size; - - /* Write data to fifo */ - retval = target_write_buffer(target, wp, thisrun_bytes, buffer); - if (retval != ERROR_OK) - break; - - /* Update counters and wrap write pointer */ - buffer += thisrun_bytes; - count -= thisrun_bytes / block_size; - wp += thisrun_bytes; - if (wp >= fifo_end_addr) - wp = fifo_start_addr; - - /* Store updated write pointer to target */ - retval = target_write_u32(target, wp_addr, wp); - if (retval != ERROR_OK) - break; - } - - if (retval != ERROR_OK) { - /* abort flash write algorithm on target */ - target_write_u32(target, wp_addr, 0); - } - - int retval2 = target_wait_algorithm(target, num_mem_params, mem_params, - num_reg_params, reg_params, - exit_point, - 10000, - arch_info); - - if (retval2 != ERROR_OK) { - LOG_ERROR("error waiting for target flash write algorithm"); - retval = retval2; - } - - return retval; + const uint8_t *buffer, uint32_t count, int block_size, + int num_mem_params, struct mem_param *mem_params, + int num_reg_params, struct reg_param *reg_params, + uint32_t buffer_start, uint32_t buffer_size, + uint32_t entry_point, uint32_t exit_point, void *arch_info) +{ + int retval; + int timeout = 0; + + const uint8_t *buffer_orig = buffer; + + /* Set up working area. First word is write pointer, second word is read pointer, + * rest is fifo data area. */ + uint32_t wp_addr = buffer_start; + uint32_t rp_addr = buffer_start + 4; + uint32_t fifo_start_addr = buffer_start + 8; + uint32_t fifo_end_addr = buffer_start + buffer_size; + + uint32_t wp = fifo_start_addr; + uint32_t rp = fifo_start_addr; + + /* validate block_size is 2^n */ + assert(!block_size || !(block_size & (block_size - 1))); + + retval = target_write_u32(target, wp_addr, wp); + if (retval != ERROR_OK) + return retval; + retval = target_write_u32(target, rp_addr, rp); + if (retval != ERROR_OK) + return retval; + + /* Start up algorithm on target and let it idle while writing the first chunk */ + retval = target_start_algorithm(target, num_mem_params, mem_params, + num_reg_params, reg_params, + entry_point, + exit_point, + arch_info); + + if (retval != ERROR_OK) { + LOG_ERROR("error starting target flash write algorithm"); + return retval; + } + + while (count > 0) { + + retval = target_read_u32(target, rp_addr, &rp); + if (retval != ERROR_OK) { + LOG_ERROR("failed to get read pointer"); + break; + } + + LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, + (size_t) (buffer - buffer_orig), count, wp, rp); + + if (rp == 0) { + LOG_ERROR("flash write algorithm aborted by target"); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + if (((rp - fifo_start_addr) & (block_size - 1)) || rp < fifo_start_addr || rp >= fifo_end_addr) { + LOG_ERROR("corrupted fifo read pointer 0x%" PRIx32, rp); + break; + } + + /* Count the number of bytes available in the fifo without + * crossing the wrap around. Make sure to not fill it completely, + * because that would make wp == rp and that's the empty condition. */ + uint32_t thisrun_bytes; + if (rp > wp) + thisrun_bytes = rp - wp - block_size; + else if (rp > fifo_start_addr) + thisrun_bytes = fifo_end_addr - wp; + else + thisrun_bytes = fifo_end_addr - wp - block_size; + + if (thisrun_bytes == 0) { + /* Throttle polling a bit if transfer is (much) faster than flash + * programming. The exact delay shouldn't matter as long as it's + * less than buffer size / flash speed. This is very unlikely to + * run when using high latency connections such as USB. */ + alive_sleep(10); + + /* to stop an infinite loop on some targets check and increment a timeout + * this issue was observed on a stellaris using the new ICDI interface */ + if (timeout++ >= 500) { + LOG_ERROR("timeout waiting for algorithm, a target reset is recommended"); + return ERROR_FLASH_OPERATION_FAILED; + } + continue; + } + + /* reset our timeout */ + timeout = 0; + + /* Limit to the amount of data we actually want to write */ + if (thisrun_bytes > count * block_size) + thisrun_bytes = count * block_size; + + /* Write data to fifo */ + retval = target_write_buffer(target, wp, thisrun_bytes, buffer); + if (retval != ERROR_OK) + break; + + /* Update counters and wrap write pointer */ + buffer += thisrun_bytes; + count -= thisrun_bytes / block_size; + wp += thisrun_bytes; + if (wp >= fifo_end_addr) + wp = fifo_start_addr; + + /* Store updated write pointer to target */ + retval = target_write_u32(target, wp_addr, wp); + if (retval != ERROR_OK) + break; + } + + if (retval != ERROR_OK) { + /* abort flash write algorithm on target */ + target_write_u32(target, wp_addr, 0); + } + + int retval2 = target_wait_algorithm(target, num_mem_params, mem_params, + num_reg_params, reg_params, + exit_point, + 10000, + arch_info); + + if (retval2 != ERROR_OK) { + LOG_ERROR("error waiting for target flash write algorithm"); + retval = retval2; + } + + if (retval == ERROR_OK) { + /* check if algorithm set rp = 0 after fifo writer loop finished */ + retval = target_read_u32(target, rp_addr, &rp); + if (retval == ERROR_OK && rp == 0) { + LOG_ERROR("flash write algorithm aborted by target"); + retval = ERROR_FLASH_OPERATION_FAILED; + } + } + + return retval; } int target_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - if (!target->type->read_memory) { - LOG_ERROR("Target %s doesn't support read_memory", target_name(target)); - return ERROR_FAIL; - } - return target->type->read_memory(target, address, size, count, buffer); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + if (!target->type->read_memory) { + LOG_ERROR("Target %s doesn't support read_memory", target_name(target)); + return ERROR_FAIL; + } + return target->type->read_memory(target, address, size, count, buffer); } int target_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - if (!target->type->read_phys_memory) { - LOG_ERROR("Target %s doesn't support read_phys_memory", target_name(target)); - return ERROR_FAIL; - } - return target->type->read_phys_memory(target, address, size, count, buffer); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + if (!target->type->read_phys_memory) { + LOG_ERROR("Target %s doesn't support read_phys_memory", target_name(target)); + return ERROR_FAIL; + } + return target->type->read_phys_memory(target, address, size, count, buffer); } int target_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - if (!target->type->write_memory) { - LOG_ERROR("Target %s doesn't support write_memory", target_name(target)); - return ERROR_FAIL; - } - return target->type->write_memory(target, address, size, count, buffer); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + if (!target->type->write_memory) { + LOG_ERROR("Target %s doesn't support write_memory", target_name(target)); + return ERROR_FAIL; + } + return target->type->write_memory(target, address, size, count, buffer); } int target_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - if (!target->type->write_phys_memory) { - LOG_ERROR("Target %s doesn't support write_phys_memory", target_name(target)); - return ERROR_FAIL; - } - return target->type->write_phys_memory(target, address, size, count, buffer); + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + if (!target->type->write_phys_memory) { + LOG_ERROR("Target %s doesn't support write_phys_memory", target_name(target)); + return ERROR_FAIL; + } + return target->type->write_phys_memory(target, address, size, count, buffer); } int target_add_breakpoint(struct target *target, - struct breakpoint *breakpoint) + struct breakpoint *breakpoint) { - if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) { - LOG_WARNING("target %s is not halted", target_name(target)); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->add_breakpoint(target, breakpoint); + if ((target->state != TARGET_HALTED) && (breakpoint->type != BKPT_HARD)) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (add breakpoint)", target_name(target)); +#else + LOG_WARNING("target %s is not halted", target_name(target)); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_breakpoint(target, breakpoint); } int target_add_context_breakpoint(struct target *target, - struct breakpoint *breakpoint) + struct breakpoint *breakpoint) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->add_context_breakpoint(target, breakpoint); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (add context breakpoint)", target_name(target)); +#else + LOG_WARNING("target %s is not halted", target_name(target)); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_context_breakpoint(target, breakpoint); } int target_add_hybrid_breakpoint(struct target *target, - struct breakpoint *breakpoint) + struct breakpoint *breakpoint) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->add_hybrid_breakpoint(target, breakpoint); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (add hybrid breakpoint)", target_name(target)); +#else + LOG_WARNING("target %s is not halted", target_name(target)); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_hybrid_breakpoint(target, breakpoint); } int target_remove_breakpoint(struct target *target, - struct breakpoint *breakpoint) + struct breakpoint *breakpoint) { - return target->type->remove_breakpoint(target, breakpoint); + return target->type->remove_breakpoint(target, breakpoint); } int target_add_watchpoint(struct target *target, - struct watchpoint *watchpoint) + struct watchpoint *watchpoint) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target_name(target)); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->add_watchpoint(target, watchpoint); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (add watchpoint)", target_name(target)); +#else + LOG_WARNING("target %s is not halted", target_name(target)); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->add_watchpoint(target, watchpoint); } int target_remove_watchpoint(struct target *target, - struct watchpoint *watchpoint) + struct watchpoint *watchpoint) { - return target->type->remove_watchpoint(target, watchpoint); + return target->type->remove_watchpoint(target, watchpoint); } int target_hit_watchpoint(struct target *target, - struct watchpoint **hit_watchpoint) + struct watchpoint **hit_watchpoint) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); - return ERROR_TARGET_NOT_HALTED; - } - - if (target->type->hit_watchpoint == NULL) { - /* For backward compatible, if hit_watchpoint is not implemented, - * return ERROR_FAIL such that gdb_server will not take the nonsense - * information. */ - return ERROR_FAIL; - } - - return target->type->hit_watchpoint(target, hit_watchpoint); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (hit watchpoint)", target->cmd_name); +#else + LOG_WARNING("target %s is not halted", target->cmd_name); +#endif + + return ERROR_TARGET_NOT_HALTED; + } + + if (target->type->hit_watchpoint == NULL) { + /* For backward compatible, if hit_watchpoint is not implemented, + * return ERROR_FAIL such that gdb_server will not take the nonsense + * information. */ + return ERROR_FAIL; + } + + return target->type->hit_watchpoint(target, hit_watchpoint); } int target_get_gdb_reg_list(struct target *target, - struct reg **reg_list[], int *reg_list_size, - enum target_register_class reg_class) + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) { - return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); + return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } int target_step(struct target *target, - int current, uint32_t address, int handle_breakpoints) + int current, target_addr_t address, int handle_breakpoints) { - return target->type->step(target, current, address, handle_breakpoints); + return target->type->step(target, current, address, handle_breakpoints); } int target_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->get_gdb_fileio_info(target, fileio_info); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (gdb fileio)", target->cmd_name); +#else + LOG_WARNING("target %s is not halted", target->cmd_name); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->get_gdb_fileio_info(target, fileio_info); } int target_gdb_fileio_end(struct target *target, int retcode, int fileio_errno, bool ctrl_c) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (gdb fileio end)", target->cmd_name); +#else + LOG_WARNING("target %s is not halted", target->cmd_name); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->gdb_fileio_end(target, retcode, fileio_errno, ctrl_c); } int target_profiling(struct target *target, uint32_t *samples, - uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) { - if (target->state != TARGET_HALTED) { - LOG_WARNING("target %s is not halted", target->cmd_name); - return ERROR_TARGET_NOT_HALTED; - } - return target->type->profiling(target, samples, max_num_samples, - num_samples, seconds); + if (target->state != TARGET_HALTED) { +#if BUILD_RISCV == 1 + LOG_WARNING("target %s is not halted (profiling)", target->cmd_name); +#else + LOG_WARNING("target %s is not halted", target->cmd_name); +#endif + return ERROR_TARGET_NOT_HALTED; + } + return target->type->profiling(target, samples, max_num_samples, + num_samples, seconds); } /** @@ -1186,689 +1248,705 @@ int target_profiling(struct target *target, uint32_t *samples, */ static void target_reset_examined(struct target *target) { - target->examined = false; + target->examined = false; } static int handle_target(void *priv); static int target_init_one(struct command_context *cmd_ctx, - struct target *target) -{ - target_reset_examined(target); - - struct target_type *type = target->type; - if (type->examine == NULL) - type->examine = default_examine; - - if (type->check_reset == NULL) - type->check_reset = default_check_reset; - - assert(type->init_target != NULL); - - int retval = type->init_target(cmd_ctx, target); - if (ERROR_OK != retval) { - LOG_ERROR("target '%s' init failed", target_name(target)); - return retval; - } - - /* Sanity-check MMU support ... stub in what we must, to help - * implement it in stages, but warn if we need to do so. - */ - if (type->mmu) { - if (type->virt2phys == NULL) { - LOG_ERROR("type '%s' is missing virt2phys", type->name); - type->virt2phys = identity_virt2phys; - } - } else { - /* Make sure no-MMU targets all behave the same: make no - * distinction between physical and virtual addresses, and - * ensure that virt2phys() is always an identity mapping. - */ - if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) - LOG_WARNING("type '%s' has bad MMU hooks", type->name); - - type->mmu = no_mmu; - type->write_phys_memory = type->write_memory; - type->read_phys_memory = type->read_memory; - type->virt2phys = identity_virt2phys; - } - - if (target->type->read_buffer == NULL) - target->type->read_buffer = target_read_buffer_default; - - if (target->type->write_buffer == NULL) - target->type->write_buffer = target_write_buffer_default; - - if (target->type->get_gdb_fileio_info == NULL) - target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; - - if (target->type->gdb_fileio_end == NULL) - target->type->gdb_fileio_end = target_gdb_fileio_end_default; - - if (target->type->profiling == NULL) - target->type->profiling = target_profiling_default; - - return ERROR_OK; + struct target *target) +{ + target_reset_examined(target); + + struct target_type *type = target->type; + if (type->examine == NULL) + type->examine = default_examine; + + if (type->check_reset == NULL) + type->check_reset = default_check_reset; + + assert(type->init_target != NULL); + + int retval = type->init_target(cmd_ctx, target); + if (ERROR_OK != retval) { + LOG_ERROR("target '%s' init failed", target_name(target)); + return retval; + } + + /* Sanity-check MMU support ... stub in what we must, to help + * implement it in stages, but warn if we need to do so. + */ + if (type->mmu) { + if (type->virt2phys == NULL) { + LOG_ERROR("type '%s' is missing virt2phys", type->name); + type->virt2phys = identity_virt2phys; + } + } else { + /* Make sure no-MMU targets all behave the same: make no + * distinction between physical and virtual addresses, and + * ensure that virt2phys() is always an identity mapping. + */ + if (type->write_phys_memory || type->read_phys_memory || type->virt2phys) + LOG_WARNING("type '%s' has bad MMU hooks", type->name); + + type->mmu = no_mmu; + type->write_phys_memory = type->write_memory; + type->read_phys_memory = type->read_memory; + type->virt2phys = identity_virt2phys; + } + + if (target->type->read_buffer == NULL) + target->type->read_buffer = target_read_buffer_default; + + if (target->type->write_buffer == NULL) + target->type->write_buffer = target_write_buffer_default; + + if (target->type->get_gdb_fileio_info == NULL) + target->type->get_gdb_fileio_info = target_get_gdb_fileio_info_default; + + if (target->type->gdb_fileio_end == NULL) + target->type->gdb_fileio_end = target_gdb_fileio_end_default; + + if (target->type->profiling == NULL) + target->type->profiling = target_profiling_default; + + return ERROR_OK; } static int target_init(struct command_context *cmd_ctx) { - struct target *target; - int retval; - - for (target = all_targets; target; target = target->next) { - retval = target_init_one(cmd_ctx, target); - if (ERROR_OK != retval) - return retval; - } - - if (!all_targets) - return ERROR_OK; - - retval = target_register_user_commands(cmd_ctx); - if (ERROR_OK != retval) - return retval; - - retval = target_register_timer_callback(&handle_target, - polling_interval, 1, cmd_ctx->interp); - if (ERROR_OK != retval) - return retval; - - return ERROR_OK; + struct target *target; + int retval; + + for (target = all_targets; target; target = target->next) { + retval = target_init_one(cmd_ctx, target); + if (ERROR_OK != retval) + return retval; + } + + if (!all_targets) + return ERROR_OK; + + retval = target_register_user_commands(cmd_ctx); + if (ERROR_OK != retval) + return retval; + + retval = target_register_timer_callback(&handle_target, + polling_interval, 1, cmd_ctx->interp); + if (ERROR_OK != retval) + return retval; + + return ERROR_OK; } COMMAND_HANDLER(handle_target_init_command) { - int retval; - - if (CMD_ARGC != 0) - return ERROR_COMMAND_SYNTAX_ERROR; - - static bool target_initialized; - if (target_initialized) { - LOG_INFO("'target init' has already been called"); - return ERROR_OK; - } - target_initialized = true; - - retval = command_run_line(CMD_CTX, "init_targets"); - if (ERROR_OK != retval) - return retval; - - retval = command_run_line(CMD_CTX, "init_target_events"); - if (ERROR_OK != retval) - return retval; - - retval = command_run_line(CMD_CTX, "init_board"); - if (ERROR_OK != retval) - return retval; - - LOG_DEBUG("Initializing targets..."); - return target_init(CMD_CTX); + int retval; + + if (CMD_ARGC != 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + static bool target_initialized; + if (target_initialized) { + LOG_INFO("'target init' has already been called"); + return ERROR_OK; + } + target_initialized = true; + + retval = command_run_line(CMD_CTX, "init_targets"); + if (ERROR_OK != retval) + return retval; + + retval = command_run_line(CMD_CTX, "init_target_events"); + if (ERROR_OK != retval) + return retval; + + retval = command_run_line(CMD_CTX, "init_board"); + if (ERROR_OK != retval) + return retval; + + LOG_DEBUG("Initializing targets..."); + return target_init(CMD_CTX); } int target_register_event_callback(int (*callback)(struct target *target, - enum target_event event, void *priv), void *priv) -{ - struct target_event_callback **callbacks_p = &target_event_callbacks; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (*callbacks_p) { - while ((*callbacks_p)->next) - callbacks_p = &((*callbacks_p)->next); - callbacks_p = &((*callbacks_p)->next); - } - - (*callbacks_p) = malloc(sizeof(struct target_event_callback)); - (*callbacks_p)->callback = callback; - (*callbacks_p)->priv = priv; - (*callbacks_p)->next = NULL; - - return ERROR_OK; + enum target_event event, void *priv), void *priv) +{ + struct target_event_callback **callbacks_p = &target_event_callbacks; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (*callbacks_p) { + while ((*callbacks_p)->next) + callbacks_p = &((*callbacks_p)->next); + callbacks_p = &((*callbacks_p)->next); + } + + (*callbacks_p) = malloc(sizeof(struct target_event_callback)); + (*callbacks_p)->callback = callback; + (*callbacks_p)->priv = priv; + (*callbacks_p)->next = NULL; + + return ERROR_OK; } int target_register_reset_callback(int (*callback)(struct target *target, - enum target_reset_mode reset_mode, void *priv), void *priv) -{ - struct target_reset_callback *entry; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - entry = malloc(sizeof(struct target_reset_callback)); - if (entry == NULL) { - LOG_ERROR("error allocating buffer for reset callback entry"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - entry->callback = callback; - entry->priv = priv; - list_add(&entry->list, &target_reset_callback_list); - - - return ERROR_OK; + enum target_reset_mode reset_mode, void *priv), void *priv) +{ + struct target_reset_callback *entry; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + entry = malloc(sizeof(struct target_reset_callback)); + if (entry == NULL) { + LOG_ERROR("error allocating buffer for reset callback entry"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + entry->callback = callback; + entry->priv = priv; + list_add(&entry->list, &target_reset_callback_list); + + + return ERROR_OK; } int target_register_trace_callback(int (*callback)(struct target *target, - size_t len, uint8_t *data, void *priv), void *priv) -{ - struct target_trace_callback *entry; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - entry = malloc(sizeof(struct target_trace_callback)); - if (entry == NULL) { - LOG_ERROR("error allocating buffer for trace callback entry"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - - entry->callback = callback; - entry->priv = priv; - list_add(&entry->list, &target_trace_callback_list); - - - return ERROR_OK; + size_t len, uint8_t *data, void *priv), void *priv) +{ + struct target_trace_callback *entry; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + entry = malloc(sizeof(struct target_trace_callback)); + if (entry == NULL) { + LOG_ERROR("error allocating buffer for trace callback entry"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + entry->callback = callback; + entry->priv = priv; + list_add(&entry->list, &target_trace_callback_list); + + + return ERROR_OK; } int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv) { - struct target_timer_callback **callbacks_p = &target_timer_callbacks; - struct timeval now; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (*callbacks_p) { - while ((*callbacks_p)->next) - callbacks_p = &((*callbacks_p)->next); - callbacks_p = &((*callbacks_p)->next); - } - - (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); - (*callbacks_p)->callback = callback; - (*callbacks_p)->periodic = periodic; - (*callbacks_p)->time_ms = time_ms; - (*callbacks_p)->removed = false; - - gettimeofday(&now, NULL); - (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; - time_ms -= (time_ms % 1000); - (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000); - if ((*callbacks_p)->when.tv_usec > 1000000) { - (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000; - (*callbacks_p)->when.tv_sec += 1; - } - - (*callbacks_p)->priv = priv; - (*callbacks_p)->next = NULL; - - return ERROR_OK; + struct target_timer_callback **callbacks_p = &target_timer_callbacks; + struct timeval now; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (*callbacks_p) { + while ((*callbacks_p)->next) + callbacks_p = &((*callbacks_p)->next); + callbacks_p = &((*callbacks_p)->next); + } + + (*callbacks_p) = malloc(sizeof(struct target_timer_callback)); + (*callbacks_p)->callback = callback; + (*callbacks_p)->periodic = periodic; + (*callbacks_p)->time_ms = time_ms; + (*callbacks_p)->removed = false; + + gettimeofday(&now, NULL); + (*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000; + time_ms -= (time_ms % 1000); + (*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000); + if ((*callbacks_p)->when.tv_usec > 1000000) { + (*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000; + (*callbacks_p)->when.tv_sec += 1; + } + + (*callbacks_p)->priv = priv; + (*callbacks_p)->next = NULL; + + return ERROR_OK; } int target_unregister_event_callback(int (*callback)(struct target *target, - enum target_event event, void *priv), void *priv) -{ - struct target_event_callback **p = &target_event_callbacks; - struct target_event_callback *c = target_event_callbacks; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - while (c) { - struct target_event_callback *next = c->next; - if ((c->callback == callback) && (c->priv == priv)) { - *p = next; - free(c); - return ERROR_OK; - } else - p = &(c->next); - c = next; - } - - return ERROR_OK; + enum target_event event, void *priv), void *priv) +{ + struct target_event_callback **p = &target_event_callbacks; + struct target_event_callback *c = target_event_callbacks; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + while (c) { + struct target_event_callback *next = c->next; + if ((c->callback == callback) && (c->priv == priv)) { + *p = next; + free(c); + return ERROR_OK; + } else + p = &(c->next); + c = next; + } + + return ERROR_OK; } int target_unregister_reset_callback(int (*callback)(struct target *target, - enum target_reset_mode reset_mode, void *priv), void *priv) -{ - struct target_reset_callback *entry; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - list_for_each_entry(entry, &target_reset_callback_list, list) { - if (entry->callback == callback && entry->priv == priv) { - list_del(&entry->list); - free(entry); - break; - } - } - - return ERROR_OK; + enum target_reset_mode reset_mode, void *priv), void *priv) +{ + struct target_reset_callback *entry; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + list_for_each_entry(entry, &target_reset_callback_list, list) { + if (entry->callback == callback && entry->priv == priv) { + list_del(&entry->list); + free(entry); + break; + } + } + + return ERROR_OK; } int target_unregister_trace_callback(int (*callback)(struct target *target, - size_t len, uint8_t *data, void *priv), void *priv) -{ - struct target_trace_callback *entry; - - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - list_for_each_entry(entry, &target_trace_callback_list, list) { - if (entry->callback == callback && entry->priv == priv) { - list_del(&entry->list); - free(entry); - break; - } - } - - return ERROR_OK; + size_t len, uint8_t *data, void *priv), void *priv) +{ + struct target_trace_callback *entry; + + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + list_for_each_entry(entry, &target_trace_callback_list, list) { + if (entry->callback == callback && entry->priv == priv) { + list_del(&entry->list); + free(entry); + break; + } + } + + return ERROR_OK; } int target_unregister_timer_callback(int (*callback)(void *priv), void *priv) { - if (callback == NULL) - return ERROR_COMMAND_SYNTAX_ERROR; - - for (struct target_timer_callback *c = target_timer_callbacks; - c; c = c->next) { - if ((c->callback == callback) && (c->priv == priv)) { - c->removed = true; - return ERROR_OK; - } - } - - return ERROR_FAIL; + if (callback == NULL) + return ERROR_COMMAND_SYNTAX_ERROR; + + for (struct target_timer_callback *c = target_timer_callbacks; + c; c = c->next) { + if ((c->callback == callback) && (c->priv == priv)) { + c->removed = true; + return ERROR_OK; + } + } + + return ERROR_FAIL; } int target_call_event_callbacks(struct target *target, enum target_event event) { - struct target_event_callback *callback = target_event_callbacks; - struct target_event_callback *next_callback; - - if (event == TARGET_EVENT_HALTED) { - /* execute early halted first */ - target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); - } - - LOG_DEBUG("target event %i (%s)", event, - Jim_Nvp_value2name_simple(nvp_target_event, event)->name); - - target_handle_event(target, event); - - while (callback) { - next_callback = callback->next; - callback->callback(target, event, callback->priv); - callback = next_callback; - } - - return ERROR_OK; + struct target_event_callback *callback = target_event_callbacks; + struct target_event_callback *next_callback; + + if (event == TARGET_EVENT_HALTED) { + /* execute early halted first */ + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); + } + + LOG_DEBUG("target event %i (%s)", event, + Jim_Nvp_value2name_simple(nvp_target_event, event)->name); + + target_handle_event(target, event); + + while (callback) { + next_callback = callback->next; + callback->callback(target, event, callback->priv); + callback = next_callback; + } + + return ERROR_OK; } int target_call_reset_callbacks(struct target *target, enum target_reset_mode reset_mode) { - struct target_reset_callback *callback; - - LOG_DEBUG("target reset %i (%s)", reset_mode, - Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name); - - list_for_each_entry(callback, &target_reset_callback_list, list) - callback->callback(target, reset_mode, callback->priv); - - return ERROR_OK; + struct target_reset_callback *callback; + + LOG_DEBUG("target reset %i (%s)", reset_mode, + Jim_Nvp_value2name_simple(nvp_reset_modes, reset_mode)->name); + + list_for_each_entry(callback, &target_reset_callback_list, list) + callback->callback(target, reset_mode, callback->priv); + + return ERROR_OK; } int target_call_trace_callbacks(struct target *target, size_t len, uint8_t *data) { - struct target_trace_callback *callback; - - list_for_each_entry(callback, &target_trace_callback_list, list) - callback->callback(target, len, data, callback->priv); - - return ERROR_OK; + struct target_trace_callback *callback; + + list_for_each_entry(callback, &target_trace_callback_list, list) + callback->callback(target, len, data, callback->priv); + + return ERROR_OK; } static int target_timer_callback_periodic_restart( - struct target_timer_callback *cb, struct timeval *now) + struct target_timer_callback *cb, struct timeval *now) { - int time_ms = cb->time_ms; - cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000; - time_ms -= (time_ms % 1000); - cb->when.tv_sec = now->tv_sec + time_ms / 1000; - if (cb->when.tv_usec > 1000000) { - cb->when.tv_usec = cb->when.tv_usec - 1000000; - cb->when.tv_sec += 1; - } - return ERROR_OK; + int time_ms = cb->time_ms; + cb->when.tv_usec = now->tv_usec + (time_ms % 1000) * 1000; + time_ms -= (time_ms % 1000); + cb->when.tv_sec = now->tv_sec + time_ms / 1000; + if (cb->when.tv_usec > 1000000) { + cb->when.tv_usec = cb->when.tv_usec - 1000000; + cb->when.tv_sec += 1; + } + return ERROR_OK; } static int target_call_timer_callback(struct target_timer_callback *cb, - struct timeval *now) + struct timeval *now) { - cb->callback(cb->priv); - - if (cb->periodic) - return target_timer_callback_periodic_restart(cb, now); - - return target_unregister_timer_callback(cb->callback, cb->priv); + cb->callback(cb->priv); + + if (cb->periodic) + return target_timer_callback_periodic_restart(cb, now); + + return target_unregister_timer_callback(cb->callback, cb->priv); } static int target_call_timer_callbacks_check_time(int checktime) { - static bool callback_processing; - - /* Do not allow nesting */ - if (callback_processing) - return ERROR_OK; - - callback_processing = true; - - keep_alive(); - - struct timeval now; - gettimeofday(&now, NULL); - - /* Store an address of the place containing a pointer to the - * next item; initially, that's a standalone "root of the - * list" variable. */ - struct target_timer_callback **callback = &target_timer_callbacks; - while (*callback) { - if ((*callback)->removed) { - struct target_timer_callback *p = *callback; - *callback = (*callback)->next; - free(p); - continue; - } - - bool call_it = (*callback)->callback && - ((!checktime && (*callback)->periodic) || - now.tv_sec > (*callback)->when.tv_sec || - (now.tv_sec == (*callback)->when.tv_sec && - now.tv_usec >= (*callback)->when.tv_usec)); - - if (call_it) - target_call_timer_callback(*callback, &now); - - callback = &(*callback)->next; - } - - callback_processing = false; - return ERROR_OK; + static bool callback_processing; + + /* Do not allow nesting */ + if (callback_processing) + return ERROR_OK; + + callback_processing = true; + + keep_alive(); + + struct timeval now; + gettimeofday(&now, NULL); + + /* Store an address of the place containing a pointer to the + * next item; initially, that's a standalone "root of the + * list" variable. */ + struct target_timer_callback **callback = &target_timer_callbacks; + while (*callback) { + if ((*callback)->removed) { + struct target_timer_callback *p = *callback; + *callback = (*callback)->next; + free(p); + continue; + } + + bool call_it = (*callback)->callback && + ((!checktime && (*callback)->periodic) || + now.tv_sec > (*callback)->when.tv_sec || + (now.tv_sec == (*callback)->when.tv_sec && + now.tv_usec >= (*callback)->when.tv_usec)); + + if (call_it) + target_call_timer_callback(*callback, &now); + + callback = &(*callback)->next; + } + + callback_processing = false; + return ERROR_OK; } int target_call_timer_callbacks(void) { - return target_call_timer_callbacks_check_time(1); + return target_call_timer_callbacks_check_time(1); } /* invoke periodic callbacks immediately */ int target_call_timer_callbacks_now(void) { - return target_call_timer_callbacks_check_time(0); + return target_call_timer_callbacks_check_time(0); } /* Prints the working area layout for debug purposes */ static void print_wa_layout(struct target *target) { - struct working_area *c = target->working_areas; - - while (c) { - LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)", - c->backup ? 'b' : ' ', c->free ? ' ' : '*', - c->address, c->address + c->size - 1, c->size); - c = c->next; - } + struct working_area *c = target->working_areas; + + while (c) { + LOG_DEBUG("%c%c " TARGET_ADDR_FMT "-" TARGET_ADDR_FMT " (%" PRIu32 " bytes)", + c->backup ? 'b' : ' ', c->free ? ' ' : '*', + c->address, c->address + c->size - 1, c->size); + c = c->next; + } } /* Reduce area to size bytes, create a new free area from the remaining bytes, if any. */ static void target_split_working_area(struct working_area *area, uint32_t size) { - assert(area->free); /* Shouldn't split an allocated area */ - assert(size <= area->size); /* Caller should guarantee this */ - - /* Split only if not already the right size */ - if (size < area->size) { - struct working_area *new_wa = malloc(sizeof(*new_wa)); - - if (new_wa == NULL) - return; - - new_wa->next = area->next; - new_wa->size = area->size - size; - new_wa->address = area->address + size; - new_wa->backup = NULL; - new_wa->user = NULL; - new_wa->free = true; - - area->next = new_wa; - area->size = size; - - /* If backup memory was allocated to this area, it has the wrong size - * now so free it and it will be reallocated if/when needed */ - if (area->backup) { - free(area->backup); - area->backup = NULL; - } - } + assert(area->free); /* Shouldn't split an allocated area */ + assert(size <= area->size); /* Caller should guarantee this */ + + /* Split only if not already the right size */ + if (size < area->size) { + struct working_area *new_wa = malloc(sizeof(*new_wa)); + + if (new_wa == NULL) + return; + + new_wa->next = area->next; + new_wa->size = area->size - size; + new_wa->address = area->address + size; + new_wa->backup = NULL; + new_wa->user = NULL; + new_wa->free = true; + + area->next = new_wa; + area->size = size; + + /* If backup memory was allocated to this area, it has the wrong size + * now so free it and it will be reallocated if/when needed */ + if (area->backup) { + free(area->backup); + area->backup = NULL; + } + } } /* Merge all adjacent free areas into one */ static void target_merge_working_areas(struct target *target) { - struct working_area *c = target->working_areas; - - while (c && c->next) { - assert(c->next->address == c->address + c->size); /* This is an invariant */ - - /* Find two adjacent free areas */ - if (c->free && c->next->free) { - /* Merge the last into the first */ - c->size += c->next->size; - - /* Remove the last */ - struct working_area *to_be_freed = c->next; - c->next = c->next->next; - if (to_be_freed->backup) - free(to_be_freed->backup); - free(to_be_freed); - - /* If backup memory was allocated to the remaining area, it's has - * the wrong size now */ - if (c->backup) { - free(c->backup); - c->backup = NULL; - } - } else { - c = c->next; - } - } + struct working_area *c = target->working_areas; + + while (c && c->next) { + assert(c->next->address == c->address + c->size); /* This is an invariant */ + + /* Find two adjacent free areas */ + if (c->free && c->next->free) { + /* Merge the last into the first */ + c->size += c->next->size; + + /* Remove the last */ + struct working_area *to_be_freed = c->next; + c->next = c->next->next; + if (to_be_freed->backup) + free(to_be_freed->backup); + free(to_be_freed); + + /* If backup memory was allocated to the remaining area, it's has + * the wrong size now */ + if (c->backup) { + free(c->backup); + c->backup = NULL; + } + } else { + c = c->next; + } + } } int target_alloc_working_area_try(struct target *target, uint32_t size, struct working_area **area) { - /* Reevaluate working area address based on MMU state*/ - if (target->working_areas == NULL) { - int retval; - int enabled; - - retval = target->type->mmu(target, &enabled); - if (retval != ERROR_OK) - return retval; - - if (!enabled) { - if (target->working_area_phys_spec) { - LOG_DEBUG("MMU disabled, using physical " - "address for working memory 0x%08"PRIx32, - target->working_area_phys); - target->working_area = target->working_area_phys; - } else { - LOG_ERROR("No working memory available. " - "Specify -work-area-phys to target."); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - } else { - if (target->working_area_virt_spec) { - LOG_DEBUG("MMU enabled, using virtual " - "address for working memory 0x%08"PRIx32, - target->working_area_virt); - target->working_area = target->working_area_virt; - } else { - LOG_ERROR("No working memory available. " - "Specify -work-area-virt to target."); - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - } - } - - /* Set up initial working area on first call */ - struct working_area *new_wa = malloc(sizeof(*new_wa)); - if (new_wa) { - new_wa->next = NULL; - new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */ - new_wa->address = target->working_area; - new_wa->backup = NULL; - new_wa->user = NULL; - new_wa->free = true; - } - - target->working_areas = new_wa; - } - - /* only allocate multiples of 4 byte */ - if (size % 4) - size = (size + 3) & (~3UL); - - struct working_area *c = target->working_areas; - - /* Find the first large enough working area */ - while (c) { - if (c->free && c->size >= size) - break; - c = c->next; - } - - if (c == NULL) - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - - /* Split the working area into the requested size */ - target_split_working_area(c, size); - - LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address); - - if (target->backup_working_area) { - if (c->backup == NULL) { - c->backup = malloc(c->size); - if (c->backup == NULL) - return ERROR_FAIL; - } - - int retval = target_read_memory(target, c->address, 4, c->size / 4, c->backup); - if (retval != ERROR_OK) - return retval; - } - - /* mark as used, and return the new (reused) area */ - c->free = false; - *area = c; - - /* user pointer */ - c->user = area; - - print_wa_layout(target); - - return ERROR_OK; + /* Reevaluate working area address based on MMU state*/ + if (target->working_areas == NULL) { + int retval; + int enabled; + + retval = target->type->mmu(target, &enabled); + if (retval != ERROR_OK) + return retval; + + if (!enabled) { + if (target->working_area_phys_spec) { + LOG_DEBUG("MMU disabled, using physical " + "address for working memory " TARGET_ADDR_FMT, + target->working_area_phys); + target->working_area = target->working_area_phys; + } else { + LOG_ERROR("No working memory available. " + "Specify -work-area-phys to target."); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } else { + if (target->working_area_virt_spec) { + LOG_DEBUG("MMU enabled, using virtual " + "address for working memory " TARGET_ADDR_FMT, + target->working_area_virt); + target->working_area = target->working_area_virt; + } else { + LOG_ERROR("No working memory available. " + "Specify -work-area-virt to target."); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + } + + /* Set up initial working area on first call */ + struct working_area *new_wa = malloc(sizeof(*new_wa)); + if (new_wa) { + new_wa->next = NULL; + new_wa->size = target->working_area_size & ~3UL; /* 4-byte align */ + new_wa->address = target->working_area; + new_wa->backup = NULL; + new_wa->user = NULL; + new_wa->free = true; + } + + target->working_areas = new_wa; + } + + /* only allocate multiples of 4 byte */ + if (size % 4) + size = (size + 3) & (~3UL); + + struct working_area *c = target->working_areas; + + /* Find the first large enough working area */ + while (c) { + if (c->free && c->size >= size) + break; + c = c->next; + } + + if (c == NULL) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + /* Split the working area into the requested size */ + target_split_working_area(c, size); + + LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT, + size, c->address); + + if (target->backup_working_area) { + if (c->backup == NULL) { + c->backup = malloc(c->size); + if (c->backup == NULL) + return ERROR_FAIL; + } + + int retval = target_read_memory(target, c->address, 4, c->size / 4, c->backup); + if (retval != ERROR_OK) + return retval; + } + + /* mark as used, and return the new (reused) area */ + c->free = false; + *area = c; + + /* user pointer */ + c->user = area; + + print_wa_layout(target); + + return ERROR_OK; } int target_alloc_working_area(struct target *target, uint32_t size, struct working_area **area) { - int retval; - - retval = target_alloc_working_area_try(target, size, area); - if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) - LOG_WARNING("not enough working area available(requested %"PRIu32")", size); - return retval; - + int retval; + + retval = target_alloc_working_area_try(target, size, area); + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + LOG_WARNING("not enough working area available(requested %"PRIu32")", size); + return retval; + } static int target_restore_working_area(struct target *target, struct working_area *area) { - int retval = ERROR_OK; - - if (target->backup_working_area && area->backup != NULL) { - retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); - if (retval != ERROR_OK) - LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32, - area->size, area->address); - } - - return retval; + int retval = ERROR_OK; + + if (target->backup_working_area && area->backup != NULL) { + retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); + if (retval != ERROR_OK) + LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, + area->size, area->address); + } + + return retval; } /* Restore the area's backup memory, if any, and return the area to the allocation pool */ static int target_free_working_area_restore(struct target *target, struct working_area *area, int restore) { - int retval = ERROR_OK; - - if (area->free) - return retval; - - if (restore) { - retval = target_restore_working_area(target, area); - /* REVISIT: Perhaps the area should be freed even if restoring fails. */ - if (retval != ERROR_OK) - return retval; - } - - area->free = true; - - LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32, - area->size, area->address); - - /* mark user pointer invalid */ - /* TODO: Is this really safe? It points to some previous caller's memory. - * How could we know that the area pointer is still in that place and not - * some other vital data? What's the purpose of this, anyway? */ - *area->user = NULL; - area->user = NULL; - - target_merge_working_areas(target); - - print_wa_layout(target); - - return retval; + int retval = ERROR_OK; + + if (area->free) + return retval; + + if (restore) { + retval = target_restore_working_area(target, area); + /* REVISIT: Perhaps the area should be freed even if restoring fails. */ + if (retval != ERROR_OK) + return retval; + } + + area->free = true; + + LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, + area->size, area->address); + + /* mark user pointer invalid */ + /* TODO: Is this really safe? It points to some previous caller's memory. + * How could we know that the area pointer is still in that place and not + * some other vital data? What's the purpose of this, anyway? */ + *area->user = NULL; + area->user = NULL; + + target_merge_working_areas(target); + + print_wa_layout(target); + + return retval; } int target_free_working_area(struct target *target, struct working_area *area) { - return target_free_working_area_restore(target, area, 1); + return target_free_working_area_restore(target, area, 1); +} + +static void target_destroy(struct target *target) +{ + if (target->type->deinit_target) + target->type->deinit_target(target); + + free(target->type); + free(target->trace_info); + free(target->cmd_name); + free(target); } void target_quit(void) { - struct target_event_callback *pe = target_event_callbacks; - while (pe) { - struct target_event_callback *t = pe->next; - free(pe); - pe = t; - } - target_event_callbacks = NULL; - - struct target_timer_callback *pt = target_timer_callbacks; - while (pt) { - struct target_timer_callback *t = pt->next; - free(pt); - pt = t; - } - target_timer_callbacks = NULL; - - for (struct target *target = all_targets; - target; target = target->next) { - if (target->type->deinit_target) - target->type->deinit_target(target); - } + struct target_event_callback *pe = target_event_callbacks; + while (pe) { + struct target_event_callback *t = pe->next; + free(pe); + pe = t; + } + target_event_callbacks = NULL; + + struct target_timer_callback *pt = target_timer_callbacks; + while (pt) { + struct target_timer_callback *t = pt->next; + free(pt); + pt = t; + } + target_timer_callbacks = NULL; + + for (struct target *target = all_targets; target;) { + struct target *tmp; + + tmp = target->next; + target_destroy(target); + target = tmp; + } + + all_targets = NULL; } /* free resources and restore memory, if restoring memory fails, @@ -1876,548 +1954,633 @@ void target_quit(void) */ static void target_free_all_working_areas_restore(struct target *target, int restore) { - struct working_area *c = target->working_areas; - - LOG_DEBUG("freeing all working areas"); - - /* Loop through all areas, restoring the allocated ones and marking them as free */ - while (c) { - if (!c->free) { - if (restore) - target_restore_working_area(target, c); - c->free = true; - *c->user = NULL; /* Same as above */ - c->user = NULL; - } - c = c->next; - } - - /* Run a merge pass to combine all areas into one */ - target_merge_working_areas(target); - - print_wa_layout(target); + struct working_area *c = target->working_areas; + + LOG_DEBUG("freeing all working areas"); + + /* Loop through all areas, restoring the allocated ones and marking them as free */ + while (c) { + if (!c->free) { + if (restore) + target_restore_working_area(target, c); + c->free = true; + *c->user = NULL; /* Same as above */ + c->user = NULL; + } + c = c->next; + } + + /* Run a merge pass to combine all areas into one */ + target_merge_working_areas(target); + + print_wa_layout(target); } void target_free_all_working_areas(struct target *target) { - target_free_all_working_areas_restore(target, 1); + target_free_all_working_areas_restore(target, 1); } /* Find the largest number of bytes that can be allocated */ uint32_t target_get_working_area_avail(struct target *target) { - struct working_area *c = target->working_areas; - uint32_t max_size = 0; - - if (c == NULL) - return target->working_area_size; - - while (c) { - if (c->free && max_size < c->size) - max_size = c->size; - - c = c->next; - } - - return max_size; + struct working_area *c = target->working_areas; + uint32_t max_size = 0; + + if (c == NULL) + return target->working_area_size; + + while (c) { + if (c->free && max_size < c->size) + max_size = c->size; + + c = c->next; + } + + return max_size; } int target_arch_state(struct target *target) { - int retval; - if (target == NULL) { - LOG_USER("No target has been configured"); - return ERROR_OK; - } - - LOG_USER("%s: target state: %s", target_name(target), - target_state_name(target)); - - if (target->state != TARGET_HALTED) - return ERROR_OK; + int retval; + if (target == NULL) { +#if BUILD_RISCV == 1 + LOG_USER("No target has been configured"); +#else + LOG_WARNING("No target has been configured"); +#endif + + return ERROR_OK; + } - retval = target->type->arch_state(target); - return retval; + if (target->state != TARGET_HALTED) + return ERROR_OK; + + retval = target->type->arch_state(target); + return retval; } static int target_get_gdb_fileio_info_default(struct target *target, - struct gdb_fileio_info *fileio_info) + struct gdb_fileio_info *fileio_info) { - /* If target does not support semi-hosting function, target - has no need to provide .get_gdb_fileio_info callback. - It just return ERROR_FAIL and gdb_server will return "Txx" - as target halted every time. */ - return ERROR_FAIL; + /* If target does not support semi-hosting function, target + has no need to provide .get_gdb_fileio_info callback. + It just return ERROR_FAIL and gdb_server will return "Txx" + as target halted every time. */ + return ERROR_FAIL; } static int target_gdb_fileio_end_default(struct target *target, - int retcode, int fileio_errno, bool ctrl_c) + int retcode, int fileio_errno, bool ctrl_c) { - return ERROR_OK; + return ERROR_OK; } static int target_profiling_default(struct target *target, uint32_t *samples, - uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) -{ - struct timeval timeout, now; - - gettimeofday(&timeout, NULL); - timeval_add_time(&timeout, seconds, 0); - - LOG_INFO("Starting profiling. Halting and resuming the" - " target as often as we can..."); - - uint32_t sample_count = 0; - /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ - struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); - - int retval = ERROR_OK; - for (;;) { - target_poll(target); - if (target->state == TARGET_HALTED) { - uint32_t t = buf_get_u32(reg->value, 0, 32); - samples[sample_count++] = t; - /* current pc, addr = 0, do not handle breakpoints, not debugging */ - retval = target_resume(target, 1, 0, 0, 0); - target_poll(target); - alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */ - } else if (target->state == TARGET_RUNNING) { - /* We want to quickly sample the PC. */ - retval = target_halt(target); - } else { - LOG_INFO("Target not halted or running"); - retval = ERROR_OK; - break; - } - - if (retval != ERROR_OK) - break; - - gettimeofday(&now, NULL); - if ((sample_count >= max_num_samples) || - ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { - LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); - break; - } - } - - *num_samples = sample_count; - return retval; + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + struct timeval timeout, now; + + gettimeofday(&timeout, NULL); + timeval_add_time(&timeout, seconds, 0); + + LOG_INFO("Starting profiling. Halting and resuming the" + " target as often as we can..."); + + uint32_t sample_count = 0; + /* hopefully it is safe to cache! We want to stop/restart as quickly as possible. */ + struct reg *reg = register_get_by_name(target->reg_cache, "pc", 1); + + int retval = ERROR_OK; + for (;;) { + target_poll(target); + if (target->state == TARGET_HALTED) { + uint32_t t = buf_get_u32(reg->value, 0, 32); + samples[sample_count++] = t; + /* current pc, addr = 0, do not handle breakpoints, not debugging */ + retval = target_resume(target, 1, 0, 0, 0); + target_poll(target); + alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */ + } else if (target->state == TARGET_RUNNING) { + /* We want to quickly sample the PC. */ + retval = target_halt(target); + } else { + LOG_INFO("Target not halted or running"); + retval = ERROR_OK; + break; + } + + if (retval != ERROR_OK) + break; + + gettimeofday(&now, NULL); + if ((sample_count >= max_num_samples) || + ((now.tv_sec >= timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec))) { + LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count); + break; + } + } + + *num_samples = sample_count; + return retval; } /* Single aligned words are guaranteed to use 16 or 32 bit access * mode respectively, otherwise data is handled as quickly as * possible */ -int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) -{ - LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); - - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - if (size == 0) - return ERROR_OK; - - if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)", - (unsigned)address, - (unsigned)size); - return ERROR_FAIL; - } - - return target->type->write_buffer(target, address, size, buffer); -} - -static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) -{ - uint32_t size; - - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass - * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { - if (address & size) { - int retval = target_write_memory(target, address, size, 1, buffer); - if (retval != ERROR_OK) - return retval; - address += size; - count -= size; - buffer += size; - } - } - - /* Write the data with as large access size as possible. */ - for (; size > 0; size /= 2) { - uint32_t aligned = count - count % size; - if (aligned > 0) { - int retval = target_write_memory(target, address, size, aligned / size, buffer); - if (retval != ERROR_OK) - return retval; - address += aligned; - count -= aligned; - buffer += aligned; - } - } - - return ERROR_OK; +int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) +{ + LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + size, address); + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (size == 0) + return ERROR_OK; + + if ((address + size - 1) < address) { + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", + address, + size); + return ERROR_FAIL; + } + + return target->type->write_buffer(target, address, size, buffer); +} + +static int target_write_buffer_default(struct target *target, + target_addr_t address, uint32_t count, const uint8_t *buffer) +{ + uint32_t size; + + /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + * will have something to do with the size we leave to it. */ + for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + if (address & size) { + int retval = target_write_memory(target, address, size, 1, buffer); + if (retval != ERROR_OK) + return retval; + address += size; + count -= size; + buffer += size; + } + } + + /* Write the data with as large access size as possible. */ + for (; size > 0; size /= 2) { + uint32_t aligned = count - count % size; + if (aligned > 0) { + int retval = target_write_memory(target, address, size, aligned / size, buffer); + if (retval != ERROR_OK) + return retval; + address += aligned; + count -= aligned; + buffer += aligned; + } + } + + return ERROR_OK; } /* Single aligned words are guaranteed to use 16 or 32 bit access * mode respectively, otherwise data is handled as quickly as * possible */ -int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) -{ - LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); - - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - if (size == 0) - return ERROR_OK; - - if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08" PRIx32 ", 0x%08" PRIx32 ")", - address, - size); - return ERROR_FAIL; - } - - return target->type->read_buffer(target, address, size, buffer); -} - -static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) -{ - uint32_t size; - - /* Align up to maximum 4 bytes. The loop condition makes sure the next pass - * will have something to do with the size we leave to it. */ - for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { - if (address & size) { - int retval = target_read_memory(target, address, size, 1, buffer); - if (retval != ERROR_OK) - return retval; - address += size; - count -= size; - buffer += size; - } - } - - /* Read the data with as large access size as possible. */ - for (; size > 0; size /= 2) { - uint32_t aligned = count - count % size; - if (aligned > 0) { - int retval = target_read_memory(target, address, size, aligned / size, buffer); - if (retval != ERROR_OK) - return retval; - address += aligned; - count -= aligned; - buffer += aligned; - } - } - - return ERROR_OK; -} - -int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc) -{ - uint8_t *buffer; - int retval; - uint32_t i; - uint32_t checksum = 0; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - retval = target->type->checksum_memory(target, address, size, &checksum); - if (retval != ERROR_OK) { - buffer = malloc(size); - if (buffer == NULL) { - LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size); - return ERROR_COMMAND_SYNTAX_ERROR; - } - retval = target_read_buffer(target, address, size, buffer); - if (retval != ERROR_OK) { - free(buffer); - return retval; - } - - /* convert to target endianness */ - for (i = 0; i < (size/sizeof(uint32_t)); i++) { - uint32_t target_data; - target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]); - target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data); - } - - retval = image_calculate_checksum(buffer, size, &checksum); - free(buffer); - } - - *crc = checksum; - - return retval; -} - -int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank) -{ - int retval; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - if (target->type->blank_check_memory == 0) - return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - - retval = target->type->blank_check_memory(target, address, size, blank); - - return retval; -} - -int target_read_u64(struct target *target, uint64_t address, uint64_t *value) -{ - uint8_t value_buf[8]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - int retval = target_read_memory(target, address, 8, 1, value_buf); - - if (retval == ERROR_OK) { - *value = target_buffer_get_u64(target, value_buf); - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", - address, - *value); - } else { - *value = 0x0; - LOG_DEBUG("address: 0x%" PRIx64 " failed", - address); - } - - return retval; -} - -int target_read_u32(struct target *target, uint32_t address, uint32_t *value) -{ - uint8_t value_buf[4]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - int retval = target_read_memory(target, address, 4, 1, value_buf); - - if (retval == ERROR_OK) { - *value = target_buffer_get_u32(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", - address, - *value); - } else { - *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", - address); - } - - return retval; -} - -int target_read_u16(struct target *target, uint32_t address, uint16_t *value) -{ - uint8_t value_buf[2]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - int retval = target_read_memory(target, address, 2, 1, value_buf); - - if (retval == ERROR_OK) { - *value = target_buffer_get_u16(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x", - address, - *value); - } else { - *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", - address); - } - - return retval; -} - -int target_read_u8(struct target *target, uint32_t address, uint8_t *value) -{ - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - int retval = target_read_memory(target, address, 1, 1, value); - - if (retval == ERROR_OK) { - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", - address, - *value); - } else { - *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", - address); - } - - return retval; -} - -int target_write_u64(struct target *target, uint64_t address, uint64_t value) -{ - int retval; - uint8_t value_buf[8]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", - address, - value); - - target_buffer_set_u64(target, value_buf, value); - retval = target_write_memory(target, address, 8, 1, value_buf); - if (retval != ERROR_OK) - LOG_DEBUG("failed: %i", retval); - - return retval; -} - -int target_write_u32(struct target *target, uint32_t address, uint32_t value) -{ - int retval; - uint8_t value_buf[4]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", - address, - value); - - target_buffer_set_u32(target, value_buf, value); - retval = target_write_memory(target, address, 4, 1, value_buf); - if (retval != ERROR_OK) - LOG_DEBUG("failed: %i", retval); - - return retval; -} - -int target_write_u16(struct target *target, uint32_t address, uint16_t value) -{ - int retval; - uint8_t value_buf[2]; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x", - address, - value); - - target_buffer_set_u16(target, value_buf, value); - retval = target_write_memory(target, address, 2, 1, value_buf); - if (retval != ERROR_OK) - LOG_DEBUG("failed: %i", retval); - - return retval; -} - -int target_write_u8(struct target *target, uint32_t address, uint8_t value) -{ - int retval; - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", - address, value); - - retval = target_write_memory(target, address, 1, 1, &value); - if (retval != ERROR_OK) - LOG_DEBUG("failed: %i", retval); - - return retval; +int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) +{ + LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, + size, address); + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (size == 0) + return ERROR_OK; + + if ((address + size - 1) < address) { + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", + address, + size); + return ERROR_FAIL; + } + + return target->type->read_buffer(target, address, size, buffer); +} + +static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) +{ + uint32_t size; + + /* Align up to maximum 4 bytes. The loop condition makes sure the next pass + * will have something to do with the size we leave to it. */ + for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) { + if (address & size) { + int retval = target_read_memory(target, address, size, 1, buffer); + if (retval != ERROR_OK) + return retval; + address += size; + count -= size; + buffer += size; + } + } + + /* Read the data with as large access size as possible. */ + for (; size > 0; size /= 2) { + uint32_t aligned = count - count % size; + if (aligned > 0) { + int retval = target_read_memory(target, address, size, aligned / size, buffer); + if (retval != ERROR_OK) + return retval; + address += aligned; + count -= aligned; + buffer += aligned; + } + } + + return ERROR_OK; +} + +int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc) +{ + uint8_t *buffer; + int retval; + uint32_t i; + uint32_t checksum = 0; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + retval = target->type->checksum_memory(target, address, size, &checksum); + if (retval != ERROR_OK) { + buffer = malloc(size); + if (buffer == NULL) { + LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size); + return ERROR_COMMAND_SYNTAX_ERROR; + } + retval = target_read_buffer(target, address, size, buffer); + if (retval != ERROR_OK) { + free(buffer); + return retval; + } + + /* convert to target endianness */ + for (i = 0; i < (size/sizeof(uint32_t)); i++) { + uint32_t target_data; + target_data = target_buffer_get_u32(target, &buffer[i*sizeof(uint32_t)]); + target_buffer_set_u32(target, &buffer[i*sizeof(uint32_t)], target_data); + } + + retval = image_calculate_checksum(buffer, size, &checksum); + free(buffer); + } + + *crc = checksum; + + return retval; +} + +int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank, + uint8_t erased_value) +{ + int retval; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (target->type->blank_check_memory == 0) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + retval = target->type->blank_check_memory(target, address, size, blank, erased_value); + + return retval; +} + +int target_read_u64(struct target *target, target_addr_t address, uint64_t *value) +{ + uint8_t value_buf[8]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + int retval = target_read_memory(target, address, 8, 1, value_buf); + + if (retval == ERROR_OK) { + *value = target_buffer_get_u64(target, value_buf); + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", + address, + *value); + } else { + *value = 0x0; + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", + address); + } + + return retval; +} + +int target_read_u32(struct target *target, target_addr_t address, uint32_t *value) +{ + uint8_t value_buf[4]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + int retval = target_read_memory(target, address, 4, 1, value_buf); + + if (retval == ERROR_OK) { + *value = target_buffer_get_u32(target, value_buf); + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", + address, + *value); + } else { + *value = 0x0; + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", + address); + } + + return retval; +} + +int target_read_u16(struct target *target, target_addr_t address, uint16_t *value) +{ + uint8_t value_buf[2]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + int retval = target_read_memory(target, address, 2, 1, value_buf); + + if (retval == ERROR_OK) { + *value = target_buffer_get_u16(target, value_buf); + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16, + address, + *value); + } else { + *value = 0x0; + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", + address); + } + + return retval; +} + +int target_read_u8(struct target *target, target_addr_t address, uint8_t *value) +{ + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + int retval = target_read_memory(target, address, 1, 1, value); + + if (retval == ERROR_OK) { + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, + address, + *value); + } else { + *value = 0x0; + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", + address); + } + + return retval; +} + +int target_write_u64(struct target *target, target_addr_t address, uint64_t value) +{ + int retval; + uint8_t value_buf[8]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", + address, + value); + + target_buffer_set_u64(target, value_buf, value); + retval = target_write_memory(target, address, 8, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_u32(struct target *target, target_addr_t address, uint32_t value) +{ + int retval; + uint8_t value_buf[4]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", + address, + value); + + target_buffer_set_u32(target, value_buf, value); + retval = target_write_memory(target, address, 4, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_u16(struct target *target, target_addr_t address, uint16_t value) +{ + int retval; + uint8_t value_buf[2]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, + address, + value); + + target_buffer_set_u16(target, value_buf, value); + retval = target_write_memory(target, address, 2, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_u8(struct target *target, target_addr_t address, uint8_t value) +{ + int retval; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, + address, value); + + retval = target_write_memory(target, address, 1, 1, &value); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value) +{ + int retval; + uint8_t value_buf[8]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", + address, + value); + + target_buffer_set_u64(target, value_buf, value); + retval = target_write_phys_memory(target, address, 8, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value) +{ + int retval; + uint8_t value_buf[4]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", + address, + value); + + target_buffer_set_u32(target, value_buf, value); + retval = target_write_phys_memory(target, address, 4, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value) +{ + int retval; + uint8_t value_buf[2]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, + address, + value); + + target_buffer_set_u16(target, value_buf, value); + retval = target_write_phys_memory(target, address, 2, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value) +{ + int retval; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, + address, value); + + retval = target_write_phys_memory(target, address, 1, 1, &value); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; } static int find_target(struct command_context *cmd_ctx, const char *name) { - struct target *target = get_target(name); - if (target == NULL) { - LOG_ERROR("Target: %s is unknown, try one of:\n", name); - return ERROR_FAIL; - } - if (!target->tap->enabled) { - LOG_USER("Target: TAP %s is disabled, " - "can't be the current target\n", - target->tap->dotted_name); - return ERROR_FAIL; - } - - cmd_ctx->current_target = target->target_number; - return ERROR_OK; + struct target *target = get_target(name); + if (target == NULL) { + LOG_ERROR("Target: %s is unknown, try one of:\n", name); + return ERROR_FAIL; + } + if (!target->tap->enabled) { + LOG_USER("Target: TAP %s is disabled, " + "can't be the current target\n", + target->tap->dotted_name); + return ERROR_FAIL; + } + + cmd_ctx->current_target = target->target_number; + return ERROR_OK; } COMMAND_HANDLER(handle_targets_command) { - int retval = ERROR_OK; - if (CMD_ARGC == 1) { - retval = find_target(CMD_CTX, CMD_ARGV[0]); - if (retval == ERROR_OK) { - /* we're done! */ - return retval; - } - } - - struct target *target = all_targets; - command_print(CMD_CTX, " TargetName Type Endian TapName State "); - command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); - while (target) { - const char *state; - char marker = ' '; - - if (target->tap->enabled) - state = target_state_name(target); - else - state = "tap-disabled"; - - if (CMD_CTX->current_target == target->target_number) - marker = '*'; - - /* keep columns lined up to match the headers above */ - command_print(CMD_CTX, - "%2d%c %-18s %-10s %-6s %-18s %s", - target->target_number, - marker, - target_name(target), - target_type_name(target), - Jim_Nvp_value2name_simple(nvp_target_endian, - target->endianness)->name, - target->tap->dotted_name, - state); - target = target->next; - } - - return retval; + int retval = ERROR_OK; + if (CMD_ARGC == 1) { + retval = find_target(CMD_CTX, CMD_ARGV[0]); + if (retval == ERROR_OK) { + /* we're done! */ + return retval; + } + } + + struct target *target = all_targets; + command_print(CMD_CTX, " TargetName Type Endian TapName State "); + command_print(CMD_CTX, "-- ------------------ ---------- ------ ------------------ ------------"); + while (target) { + const char *state; + char marker = ' '; + + if (target->tap->enabled) + state = target_state_name(target); + else + state = "tap-disabled"; + + if (CMD_CTX->current_target == target->target_number) + marker = '*'; + + /* keep columns lined up to match the headers above */ + command_print(CMD_CTX, + "%2d%c %-18s %-10s %-6s %-18s %s", + target->target_number, + marker, + target_name(target), + target_type_name(target), + Jim_Nvp_value2name_simple(nvp_target_endian, + target->endianness)->name, + target->tap->dotted_name, + state); + target = target->next; + } + + return retval; } /* every 300ms we check for reset & powerdropout and issue a "reset halt" if so. */ @@ -2432,332 +2595,354 @@ static int runSrstDeasserted; static int sense_handler(void) { - static int prevSrstAsserted; - static int prevPowerdropout; - - int retval = jtag_power_dropout(&powerDropout); - if (retval != ERROR_OK) - return retval; - - int powerRestored; - powerRestored = prevPowerdropout && !powerDropout; - if (powerRestored) - runPowerRestore = 1; - - long long current = timeval_ms(); - static long long lastPower; - int waitMore = lastPower + 2000 > current; - if (powerDropout && !waitMore) { - runPowerDropout = 1; - lastPower = current; - } - - retval = jtag_srst_asserted(&srstAsserted); - if (retval != ERROR_OK) - return retval; - - int srstDeasserted; - srstDeasserted = prevSrstAsserted && !srstAsserted; - - static long long lastSrst; - waitMore = lastSrst + 2000 > current; - if (srstDeasserted && !waitMore) { - runSrstDeasserted = 1; - lastSrst = current; - } - - if (!prevSrstAsserted && srstAsserted) - runSrstAsserted = 1; - - prevSrstAsserted = srstAsserted; - prevPowerdropout = powerDropout; - - if (srstDeasserted || powerRestored) { - /* Other than logging the event we can't do anything here. - * Issuing a reset is a particularly bad idea as we might - * be inside a reset already. - */ - } - - return ERROR_OK; + static int prevSrstAsserted; + static int prevPowerdropout; + + int retval = jtag_power_dropout(&powerDropout); + if (retval != ERROR_OK) + return retval; + + int powerRestored; + powerRestored = prevPowerdropout && !powerDropout; + if (powerRestored) + runPowerRestore = 1; + + int64_t current = timeval_ms(); + static int64_t lastPower; + bool waitMore = lastPower + 2000 > current; + if (powerDropout && !waitMore) { + runPowerDropout = 1; + lastPower = current; + } + + retval = jtag_srst_asserted(&srstAsserted); + if (retval != ERROR_OK) + return retval; + + int srstDeasserted; + srstDeasserted = prevSrstAsserted && !srstAsserted; + + static int64_t lastSrst; + waitMore = lastSrst + 2000 > current; + if (srstDeasserted && !waitMore) { + runSrstDeasserted = 1; + lastSrst = current; + } + + if (!prevSrstAsserted && srstAsserted) + runSrstAsserted = 1; + + prevSrstAsserted = srstAsserted; + prevPowerdropout = powerDropout; + + if (srstDeasserted || powerRestored) { + /* Other than logging the event we can't do anything here. + * Issuing a reset is a particularly bad idea as we might + * be inside a reset already. + */ + } + + return ERROR_OK; } /* process target state changes */ static int handle_target(void *priv) { - Jim_Interp *interp = (Jim_Interp *)priv; - int retval = ERROR_OK; - - if (!is_jtag_poll_safe()) { - /* polling is disabled currently */ - return ERROR_OK; - } - - /* we do not want to recurse here... */ - static int recursive; - if (!recursive) { - recursive = 1; - sense_handler(); - /* danger! running these procedures can trigger srst assertions and power dropouts. - * We need to avoid an infinite loop/recursion here and we do that by - * clearing the flags after running these events. - */ - int did_something = 0; - if (runSrstAsserted) { - LOG_INFO("srst asserted detected, running srst_asserted proc."); - Jim_Eval(interp, "srst_asserted"); - did_something = 1; - } - if (runSrstDeasserted) { - Jim_Eval(interp, "srst_deasserted"); - did_something = 1; - } - if (runPowerDropout) { - LOG_INFO("Power dropout detected, running power_dropout proc."); - Jim_Eval(interp, "power_dropout"); - did_something = 1; - } - if (runPowerRestore) { - Jim_Eval(interp, "power_restore"); - did_something = 1; - } - - if (did_something) { - /* clear detect flags */ - sense_handler(); - } - - /* clear action flags */ - - runSrstAsserted = 0; - runSrstDeasserted = 0; - runPowerRestore = 0; - runPowerDropout = 0; - - recursive = 0; - } - - /* Poll targets for state changes unless that's globally disabled. - * Skip targets that are currently disabled. - */ - for (struct target *target = all_targets; - is_jtag_poll_safe() && target; - target = target->next) { - - if (!target_was_examined(target)) - continue; - - if (!target->tap->enabled) - continue; - - if (target->backoff.times > target->backoff.count) { - /* do not poll this time as we failed previously */ - target->backoff.count++; - continue; - } - target->backoff.count = 0; - - /* only poll target if we've got power and srst isn't asserted */ - if (!powerDropout && !srstAsserted) { - /* polling may fail silently until the target has been examined */ - retval = target_poll(target); - if (retval != ERROR_OK) { - /* 100ms polling interval. Increase interval between polling up to 5000ms */ - if (target->backoff.times * polling_interval < 5000) { - target->backoff.times *= 2; - target->backoff.times++; - } - - /* Tell GDB to halt the debugger. This allows the user to - * run monitor commands to handle the situation. - */ - target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); - } - if (target->backoff.times > 0) { - LOG_USER("Polling target %s failed, trying to reexamine", target_name(target)); - target_reset_examined(target); - retval = target_examine_one(target); - /* Target examination could have failed due to unstable connection, - * but we set the examined flag anyway to repoll it later */ - if (retval != ERROR_OK) { - target->examined = true; - LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", - target->backoff.times * polling_interval); - return retval; - } - } - - /* Since we succeeded, we reset backoff count */ - target->backoff.times = 0; - } - } - - return retval; + Jim_Interp *interp = (Jim_Interp *)priv; + int retval = ERROR_OK; + + if (!is_jtag_poll_safe()) { + /* polling is disabled currently */ + return ERROR_OK; + } + + /* we do not want to recurse here... */ + static int recursive; + if (!recursive) { + recursive = 1; + sense_handler(); + /* danger! running these procedures can trigger srst assertions and power dropouts. + * We need to avoid an infinite loop/recursion here and we do that by + * clearing the flags after running these events. + */ + int did_something = 0; + if (runSrstAsserted) { + LOG_INFO("srst asserted detected, running srst_asserted proc."); + Jim_Eval(interp, "srst_asserted"); + did_something = 1; + } + if (runSrstDeasserted) { + Jim_Eval(interp, "srst_deasserted"); + did_something = 1; + } + if (runPowerDropout) { + LOG_INFO("Power dropout detected, running power_dropout proc."); + Jim_Eval(interp, "power_dropout"); + did_something = 1; + } + if (runPowerRestore) { + Jim_Eval(interp, "power_restore"); + did_something = 1; + } + + if (did_something) { + /* clear detect flags */ + sense_handler(); + } + + /* clear action flags */ + + runSrstAsserted = 0; + runSrstDeasserted = 0; + runPowerRestore = 0; + runPowerDropout = 0; + + recursive = 0; + } + + /* Poll targets for state changes unless that's globally disabled. + * Skip targets that are currently disabled. + */ + for (struct target *target = all_targets; + is_jtag_poll_safe() && target; + target = target->next) { + + if (!target_was_examined(target)) + continue; + + if (!target->tap->enabled) + continue; + + if (target->backoff.times > target->backoff.count) { + /* do not poll this time as we failed previously */ + target->backoff.count++; + continue; + } + target->backoff.count = 0; + + /* only poll target if we've got power and srst isn't asserted */ + if (!powerDropout && !srstAsserted) { + /* polling may fail silently until the target has been examined */ + retval = target_poll(target); + if (retval != ERROR_OK) { + /* 100ms polling interval. Increase interval between polling up to 5000ms */ + if (target->backoff.times * polling_interval < 5000) { + target->backoff.times *= 2; + target->backoff.times++; + } + + /* Tell GDB to halt the debugger. This allows the user to + * run monitor commands to handle the situation. + */ + target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT); + } + if (target->backoff.times > 0) { + LOG_USER("Polling target %s failed, trying to reexamine", target_name(target)); + target_reset_examined(target); + retval = target_examine_one(target); + /* Target examination could have failed due to unstable connection, + * but we set the examined flag anyway to repoll it later */ + if (retval != ERROR_OK) { + target->examined = true; + LOG_USER("Examination failed, GDB will be halted. Polling again in %dms", + target->backoff.times * polling_interval); + return retval; + } + } + + /* Since we succeeded, we reset backoff count */ + target->backoff.times = 0; + } + } + + return retval; } COMMAND_HANDLER(handle_reg_command) { - struct target *target; - struct reg *reg = NULL; - unsigned count = 0; - char *value; - - LOG_DEBUG("-"); - - target = get_current_target(CMD_CTX); - - /* list all available registers for the current target */ - if (CMD_ARGC == 0) { - struct reg_cache *cache = target->reg_cache; - - count = 0; - while (cache) { - unsigned i; - - command_print(CMD_CTX, "===== %s", cache->name); - - for (i = 0, reg = cache->reg_list; - i < cache->num_regs; - i++, reg++, count++) { - /* only print cached values if they are valid */ - if (reg->valid) { - value = buf_to_str(reg->value, - reg->size, 16); - command_print(CMD_CTX, - "(%i) %s (/%" PRIu32 "): 0x%s%s", - count, reg->name, - reg->size, value, - reg->dirty - ? " (dirty)" - : ""); - free(value); - } else { - command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")", - count, reg->name, - reg->size) ; - } - } - cache = cache->next; - } - - return ERROR_OK; - } - - /* access a single register by its ordinal number */ - if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { - unsigned num; - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); - - struct reg_cache *cache = target->reg_cache; - count = 0; - while (cache) { - unsigned i; - for (i = 0; i < cache->num_regs; i++) { - if (count++ == num) { - reg = &cache->reg_list[i]; - break; - } - } - if (reg) - break; - cache = cache->next; - } - - if (!reg) { - command_print(CMD_CTX, "%i is out of bounds, the current target " - "has only %i registers (0 - %i)", num, count, count - 1); - return ERROR_OK; - } - } else { - /* access a single register by its name */ - reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); - - if (!reg) { - command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); - return ERROR_OK; - } - } - - assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ - - /* display a register */ - if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') - && (CMD_ARGV[1][0] <= '9')))) { - if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) - reg->valid = 0; - - if (reg->valid == 0) - reg->type->get(reg); - value = buf_to_str(reg->value, reg->size, 16); - command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); - free(value); - return ERROR_OK; - } - - /* set register value */ - if (CMD_ARGC == 2) { - uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); - if (buf == NULL) - return ERROR_FAIL; - str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); - - reg->type->set(reg, buf); - - value = buf_to_str(reg->value, reg->size, 16); - command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); - free(value); - - free(buf); - - return ERROR_OK; - } - - return ERROR_COMMAND_SYNTAX_ERROR; + struct target *target; + struct reg *reg = NULL; + unsigned count = 0; + char *value; +#if BUILD_RISCV == 1 + int retval; +#endif + + LOG_DEBUG("-"); + + target = get_current_target(CMD_CTX); + + /* list all available registers for the current target */ + if (CMD_ARGC == 0) { + struct reg_cache *cache = target->reg_cache; + + count = 0; + while (cache) { + unsigned i; + + command_print(CMD_CTX, "===== %s", cache->name); + + for (i = 0, reg = cache->reg_list; + i < cache->num_regs; + i++, reg++, count++) { + /* only print cached values if they are valid */ + if (reg->valid) { + value = buf_to_str(reg->value, + reg->size, 16); + command_print(CMD_CTX, + "(%i) %s (/%" PRIu32 "): 0x%s%s", + count, reg->name, + reg->size, value, + reg->dirty + ? " (dirty)" + : ""); + free(value); + } else { + command_print(CMD_CTX, "(%i) %s (/%" PRIu32 ")", + count, reg->name, + reg->size) ; + } + } + cache = cache->next; + } + + return ERROR_OK; + } + + /* access a single register by its ordinal number */ + if ((CMD_ARGV[0][0] >= '0') && (CMD_ARGV[0][0] <= '9')) { + unsigned num; + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num); + + struct reg_cache *cache = target->reg_cache; + count = 0; + while (cache) { + unsigned i; + for (i = 0; i < cache->num_regs; i++) { + if (count++ == num) { + reg = &cache->reg_list[i]; + break; + } + } + if (reg) + break; + cache = cache->next; + } + + if (!reg) { + command_print(CMD_CTX, "%i is out of bounds, the current target " + "has only %i registers (0 - %i)", num, count, count - 1); + return ERROR_OK; + } + } else { + /* access a single register by its name */ + reg = register_get_by_name(target->reg_cache, CMD_ARGV[0], 1); + + if (!reg) { + command_print(CMD_CTX, "register %s not found in current target", CMD_ARGV[0]); + return ERROR_OK; + } + } + + assert(reg != NULL); /* give clang a hint that we *know* reg is != NULL here */ + + /* display a register */ + if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0') + && (CMD_ARGV[1][0] <= '9')))) { + if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0)) + reg->valid = 0; + +#if BUILD_RISCV == 1 + if (reg->valid == 0) { + retval = reg->type->get(reg); + if (retval != ERROR_OK) { + LOG_DEBUG("Couldn't get register %s.", reg->name); + return retval; + } + } +#else + if (reg->valid == 0) + reg->type->get(reg); +#endif + value = buf_to_str(reg->value, reg->size, 16); + command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + free(value); + return ERROR_OK; + } + + /* set register value */ + if (CMD_ARGC == 2) { + uint8_t *buf = malloc(DIV_ROUND_UP(reg->size, 8)); + if (buf == NULL) + return ERROR_FAIL; + str_to_buf(CMD_ARGV[1], strlen(CMD_ARGV[1]), buf, reg->size, 0); + +#if BUILD_RISCV == 1 + retval = reg->type->set(reg, buf); + if (retval != ERROR_OK) { + LOG_DEBUG("Couldn't set register %s.", reg->name); + free (buf); + return retval; + } +#else + reg->type->set(reg, buf); +#endif + + value = buf_to_str(reg->value, reg->size, 16); + command_print(CMD_CTX, "%s (/%i): 0x%s", reg->name, (int)(reg->size), value); + free(value); + + free(buf); + + return ERROR_OK; + } + + return ERROR_COMMAND_SYNTAX_ERROR; } COMMAND_HANDLER(handle_poll_command) { - int retval = ERROR_OK; - struct target *target = get_current_target(CMD_CTX); - - if (CMD_ARGC == 0) { - command_print(CMD_CTX, "background polling: %s", - jtag_poll_get_enabled() ? "on" : "off"); - command_print(CMD_CTX, "TAP: %s (%s)", - target->tap->dotted_name, - target->tap->enabled ? "enabled" : "disabled"); - if (!target->tap->enabled) - return ERROR_OK; - retval = target_poll(target); - if (retval != ERROR_OK) - return retval; - retval = target_arch_state(target); - if (retval != ERROR_OK) - return retval; - } else if (CMD_ARGC == 1) { - bool enable; - COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); - jtag_poll_set_enabled(enable); - } else - return ERROR_COMMAND_SYNTAX_ERROR; - - return retval; + int retval = ERROR_OK; + struct target *target = get_current_target(CMD_CTX); + + if (CMD_ARGC == 0) { + command_print(CMD_CTX, "background polling: %s", + jtag_poll_get_enabled() ? "on" : "off"); + command_print(CMD_CTX, "TAP: %s (%s)", + target->tap->dotted_name, + target->tap->enabled ? "enabled" : "disabled"); + if (!target->tap->enabled) + return ERROR_OK; + retval = target_poll(target); + if (retval != ERROR_OK) + return retval; + retval = target_arch_state(target); + if (retval != ERROR_OK) + return retval; + } else if (CMD_ARGC == 1) { + bool enable; + COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); + jtag_poll_set_enabled(enable); + } else + return ERROR_COMMAND_SYNTAX_ERROR; + + return retval; } COMMAND_HANDLER(handle_wait_halt_command) { - if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - unsigned ms = DEFAULT_HALT_TIMEOUT; - if (1 == CMD_ARGC) { - int retval = parse_uint(CMD_ARGV[0], &ms); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; - } - - struct target *target = get_current_target(CMD_CTX); - return target_wait_state(target, TARGET_HALTED, ms); + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + unsigned ms = DEFAULT_HALT_TIMEOUT; + if (1 == CMD_ARGC) { + int retval = parse_uint(CMD_ARGV[0], &ms); + if (ERROR_OK != retval) + return ERROR_COMMAND_SYNTAX_ERROR; + } + + struct target *target = get_current_target(CMD_CTX); + return target_wait_state(target, TARGET_HALTED, ms); } /* wait for target state to change. The trick here is to have a low @@ -2768,880 +2953,910 @@ COMMAND_HANDLER(handle_wait_halt_command) */ int target_wait_state(struct target *target, enum target_state state, int ms) { - int retval; - long long then = 0, cur; - int once = 1; - - for (;;) { - retval = target_poll(target); - if (retval != ERROR_OK) - return retval; - if (target->state == state) - break; - cur = timeval_ms(); - if (once) { - once = 0; - then = timeval_ms(); - LOG_DEBUG("waiting for target %s...", - Jim_Nvp_value2name_simple(nvp_target_state, state)->name); - } - - if (cur-then > 500) - keep_alive(); - - if ((cur-then) > ms) { - LOG_ERROR("timed out while waiting for target %s", - Jim_Nvp_value2name_simple(nvp_target_state, state)->name); - return ERROR_FAIL; - } - } - - return ERROR_OK; + int retval; + int64_t then = 0, cur; + bool once = true; + + for (;;) { + retval = target_poll(target); + if (retval != ERROR_OK) + return retval; + if (target->state == state) + break; + cur = timeval_ms(); + if (once) { + once = false; + then = timeval_ms(); + LOG_DEBUG("waiting for target %s...", + Jim_Nvp_value2name_simple(nvp_target_state, state)->name); + } + + if (cur-then > 500) + keep_alive(); + + if ((cur-then) > ms) { + LOG_ERROR("timed out while waiting for target %s", + Jim_Nvp_value2name_simple(nvp_target_state, state)->name); + return ERROR_FAIL; + } + } + + return ERROR_OK; } COMMAND_HANDLER(handle_halt_command) { - LOG_DEBUG("-"); - - struct target *target = get_current_target(CMD_CTX); - int retval = target_halt(target); - if (ERROR_OK != retval) - return retval; - - if (CMD_ARGC == 1) { - unsigned wait_local; - retval = parse_uint(CMD_ARGV[0], &wait_local); - if (ERROR_OK != retval) - return ERROR_COMMAND_SYNTAX_ERROR; - if (!wait_local) - return ERROR_OK; - } - - return CALL_COMMAND_HANDLER(handle_wait_halt_command); + LOG_DEBUG("-"); + + struct target *target = get_current_target(CMD_CTX); + int retval = target_halt(target); + if (ERROR_OK != retval) + return retval; + + if (CMD_ARGC == 1) { + unsigned wait_local; + retval = parse_uint(CMD_ARGV[0], &wait_local); + if (ERROR_OK != retval) + return ERROR_COMMAND_SYNTAX_ERROR; + if (!wait_local) + return ERROR_OK; + } + + return CALL_COMMAND_HANDLER(handle_wait_halt_command); } COMMAND_HANDLER(handle_soft_reset_halt_command) { - struct target *target = get_current_target(CMD_CTX); - - LOG_USER("requesting target halt and executing a soft reset"); - - target_soft_reset_halt(target); - - return ERROR_OK; + struct target *target = get_current_target(CMD_CTX); + + LOG_USER("requesting target halt and executing a soft reset"); + + target_soft_reset_halt(target); + + return ERROR_OK; } COMMAND_HANDLER(handle_reset_command) { - if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - enum target_reset_mode reset_mode = RESET_RUN; - if (CMD_ARGC == 1) { - const Jim_Nvp *n; - n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]); - if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) - return ERROR_COMMAND_SYNTAX_ERROR; - reset_mode = n->value; - } - - /* reset *all* targets */ - return target_process_reset(CMD_CTX, reset_mode); + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + enum target_reset_mode reset_mode = RESET_RUN; + if (CMD_ARGC == 1) { + const Jim_Nvp *n; + n = Jim_Nvp_name2value_simple(nvp_reset_modes, CMD_ARGV[0]); + if ((n->name == NULL) || (n->value == RESET_UNKNOWN)) + return ERROR_COMMAND_SYNTAX_ERROR; + reset_mode = n->value; + } + + /* reset *all* targets */ + return target_process_reset(CMD_CTX, reset_mode); } COMMAND_HANDLER(handle_resume_command) { - int current = 1; - if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - struct target *target = get_current_target(CMD_CTX); - - /* with no CMD_ARGV, resume from current pc, addr = 0, - * with one arguments, addr = CMD_ARGV[0], - * handle breakpoints, not debugging */ - uint32_t addr = 0; - if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - current = 0; - } - - return target_resume(target, current, addr, 1, 0); + int current = 1; + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *target = get_current_target(CMD_CTX); + + /* with no CMD_ARGV, resume from current pc, addr = 0, + * with one arguments, addr = CMD_ARGV[0], + * handle breakpoints, not debugging */ + target_addr_t addr = 0; + if (CMD_ARGC == 1) { + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + current = 0; + } + + return target_resume(target, current, addr, 1, 0); } COMMAND_HANDLER(handle_step_command) { - if (CMD_ARGC > 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - LOG_DEBUG("-"); - - /* with no CMD_ARGV, step from current pc, addr = 0, - * with one argument addr = CMD_ARGV[0], - * handle breakpoints, debugging */ - uint32_t addr = 0; - int current_pc = 1; - if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - current_pc = 0; - } - - struct target *target = get_current_target(CMD_CTX); - - return target->type->step(target, current_pc, addr, 1); + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + LOG_DEBUG("-"); + + /* with no CMD_ARGV, step from current pc, addr = 0, + * with one argument addr = CMD_ARGV[0], + * handle breakpoints, debugging */ + target_addr_t addr = 0; + int current_pc = 1; + if (CMD_ARGC == 1) { + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + current_pc = 0; + } + + struct target *target = get_current_target(CMD_CTX); + + return target->type->step(target, current_pc, addr, 1); } static void handle_md_output(struct command_context *cmd_ctx, - struct target *target, uint32_t address, unsigned size, - unsigned count, const uint8_t *buffer) -{ - const unsigned line_bytecnt = 32; - unsigned line_modulo = line_bytecnt / size; - - char output[line_bytecnt * 4 + 1]; - unsigned output_len = 0; - - const char *value_fmt; - switch (size) { - case 4: - value_fmt = "%8.8x "; - break; - case 2: - value_fmt = "%4.4x "; - break; - case 1: - value_fmt = "%2.2x "; - break; - default: - /* "can't happen", caller checked */ - LOG_ERROR("invalid memory read size: %u", size); - return; - } - - for (unsigned i = 0; i < count; i++) { - if (i % line_modulo == 0) { - output_len += snprintf(output + output_len, - sizeof(output) - output_len, - "0x%8.8x: ", - (unsigned)(address + (i*size))); - } - - uint32_t value = 0; - const uint8_t *value_ptr = buffer + i * size; - switch (size) { - case 4: - value = target_buffer_get_u32(target, value_ptr); - break; - case 2: - value = target_buffer_get_u16(target, value_ptr); - break; - case 1: - value = *value_ptr; - } - output_len += snprintf(output + output_len, - sizeof(output) - output_len, - value_fmt, value); - - if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { - command_print(cmd_ctx, "%s", output); - output_len = 0; - } - } + struct target *target, target_addr_t address, unsigned size, + unsigned count, const uint8_t *buffer) +{ + const unsigned line_bytecnt = 32; + unsigned line_modulo = line_bytecnt / size; + + char output[line_bytecnt * 4 + 1]; + unsigned output_len = 0; + + const char *value_fmt; + switch (size) { + case 8: + value_fmt = "%16.16llx "; + break; + case 4: + value_fmt = "%8.8x "; + break; + case 2: + value_fmt = "%4.4x "; + break; + case 1: + value_fmt = "%2.2x "; + break; + default: + /* "can't happen", caller checked */ + LOG_ERROR("invalid memory read size: %u", size); + return; + } + + for (unsigned i = 0; i < count; i++) { + if (i % line_modulo == 0) { + output_len += snprintf(output + output_len, + sizeof(output) - output_len, + TARGET_ADDR_FMT ": ", + (address + (i * size))); + } + + uint64_t value = 0; + const uint8_t *value_ptr = buffer + i * size; + switch (size) { + case 8: + value = target_buffer_get_u64(target, value_ptr); + break; + case 4: + value = target_buffer_get_u32(target, value_ptr); + break; + case 2: + value = target_buffer_get_u16(target, value_ptr); + break; + case 1: + value = *value_ptr; + } + output_len += snprintf(output + output_len, + sizeof(output) - output_len, + value_fmt, value); + + if ((i % line_modulo == line_modulo - 1) || (i == count - 1)) { + command_print(cmd_ctx, "%s", output); + output_len = 0; + } + } } COMMAND_HANDLER(handle_md_command) { - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - unsigned size = 0; - switch (CMD_NAME[2]) { - case 'w': - size = 4; - break; - case 'h': - size = 2; - break; - case 'b': - size = 1; - break; - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - bool physical = strcmp(CMD_ARGV[0], "phys") == 0; - int (*fn)(struct target *target, - uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); - if (physical) { - CMD_ARGC--; - CMD_ARGV++; - fn = target_read_phys_memory; - } else - fn = target_read_memory; - if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) - return ERROR_COMMAND_SYNTAX_ERROR; - - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); - - unsigned count = 1; - if (CMD_ARGC == 2) - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); - - uint8_t *buffer = calloc(count, size); - - struct target *target = get_current_target(CMD_CTX); - int retval = fn(target, address, size, count, buffer); - if (ERROR_OK == retval) - handle_md_output(CMD_CTX, target, address, size, count, buffer); - - free(buffer); - - return retval; + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + unsigned size = 0; + switch (CMD_NAME[2]) { + case 'd': + size = 8; + break; + case 'w': + size = 4; + break; + case 'h': + size = 2; + break; + case 'b': + size = 1; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + bool physical = strcmp(CMD_ARGV[0], "phys") == 0; + int (*fn)(struct target *target, + target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); + if (physical) { + CMD_ARGC--; + CMD_ARGV++; + fn = target_read_phys_memory; + } else + fn = target_read_memory; + if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) + return ERROR_COMMAND_SYNTAX_ERROR; + + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); + + unsigned count = 1; + if (CMD_ARGC == 2) + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], count); + + uint8_t *buffer = calloc(count, size); + + struct target *target = get_current_target(CMD_CTX); + int retval = fn(target, address, size, count, buffer); + if (ERROR_OK == retval) + handle_md_output(CMD_CTX, target, address, size, count, buffer); + + free(buffer); + + return retval; } typedef int (*target_write_fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); +target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); static int target_fill_mem(struct target *target, - uint32_t address, - target_write_fn fn, - unsigned data_size, - /* value */ - uint32_t b, - /* count */ - unsigned c) -{ - /* We have to write in reasonably large chunks to be able - * to fill large memory areas with any sane speed */ - const unsigned chunk_size = 16384; - uint8_t *target_buf = malloc(chunk_size * data_size); - if (target_buf == NULL) { - LOG_ERROR("Out of memory"); - return ERROR_FAIL; - } - - for (unsigned i = 0; i < chunk_size; i++) { - switch (data_size) { - case 4: - target_buffer_set_u32(target, target_buf + i * data_size, b); - break; - case 2: - target_buffer_set_u16(target, target_buf + i * data_size, b); - break; - case 1: - target_buffer_set_u8(target, target_buf + i * data_size, b); - break; - default: - exit(-1); - } - } - - int retval = ERROR_OK; - - for (unsigned x = 0; x < c; x += chunk_size) { - unsigned current; - current = c - x; - if (current > chunk_size) - current = chunk_size; - retval = fn(target, address + x * data_size, data_size, current, target_buf); - if (retval != ERROR_OK) - break; - /* avoid GDB timeouts */ - keep_alive(); - } - free(target_buf); - - return retval; + target_addr_t address, + target_write_fn fn, + unsigned data_size, + /* value */ + uint64_t b, + /* count */ + unsigned c) +{ + /* We have to write in reasonably large chunks to be able + * to fill large memory areas with any sane speed */ + const unsigned chunk_size = 16384; + uint8_t *target_buf = malloc(chunk_size * data_size); + if (target_buf == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + for (unsigned i = 0; i < chunk_size; i++) { + switch (data_size) { + case 8: + target_buffer_set_u64(target, target_buf + i * data_size, b); + break; + case 4: + target_buffer_set_u32(target, target_buf + i * data_size, b); + break; + case 2: + target_buffer_set_u16(target, target_buf + i * data_size, b); + break; + case 1: + target_buffer_set_u8(target, target_buf + i * data_size, b); + break; + default: + exit(-1); + } + } + + int retval = ERROR_OK; + + for (unsigned x = 0; x < c; x += chunk_size) { + unsigned current; + current = c - x; + if (current > chunk_size) + current = chunk_size; + retval = fn(target, address + x * data_size, data_size, current, target_buf); + if (retval != ERROR_OK) + break; + /* avoid GDB timeouts */ + keep_alive(); + } + free(target_buf); + + return retval; } COMMAND_HANDLER(handle_mw_command) { - if (CMD_ARGC < 2) - return ERROR_COMMAND_SYNTAX_ERROR; - bool physical = strcmp(CMD_ARGV[0], "phys") == 0; - target_write_fn fn; - if (physical) { - CMD_ARGC--; - CMD_ARGV++; - fn = target_write_phys_memory; - } else - fn = target_write_memory; - if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) - return ERROR_COMMAND_SYNTAX_ERROR; - - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); - - uint32_t value; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); - - unsigned count = 1; - if (CMD_ARGC == 3) - COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); - - struct target *target = get_current_target(CMD_CTX); - unsigned wordsize; - switch (CMD_NAME[2]) { - case 'w': - wordsize = 4; - break; - case 'h': - wordsize = 2; - break; - case 'b': - wordsize = 1; - break; - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return target_fill_mem(target, address, fn, wordsize, value, count); + if (CMD_ARGC < 2) + return ERROR_COMMAND_SYNTAX_ERROR; + bool physical = strcmp(CMD_ARGV[0], "phys") == 0; + target_write_fn fn; + if (physical) { + CMD_ARGC--; + CMD_ARGV++; + fn = target_write_phys_memory; + } else + fn = target_write_memory; + if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) + return ERROR_COMMAND_SYNTAX_ERROR; + + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); + + target_addr_t value; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value); + + unsigned count = 1; + if (CMD_ARGC == 3) + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count); + + struct target *target = get_current_target(CMD_CTX); + unsigned wordsize; + switch (CMD_NAME[2]) { + case 'd': + wordsize = 8; + break; + case 'w': + wordsize = 4; + break; + case 'h': + wordsize = 2; + break; + case 'b': + wordsize = 1; + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return target_fill_mem(target, address, fn, wordsize, value, count); } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, - uint32_t *min_address, uint32_t *max_address) -{ - if (CMD_ARGC < 1 || CMD_ARGC > 5) - return ERROR_COMMAND_SYNTAX_ERROR; - - /* a base address isn't always necessary, - * default to 0x0 (i.e. don't relocate) */ - if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); - image->base_address = addr; - image->base_address_set = 1; - } else - image->base_address_set = 0; - - image->start_address_set = 0; - - if (CMD_ARGC >= 4) - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address); - if (CMD_ARGC == 5) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address); - /* use size (given) to find max (required) */ - *max_address += *min_address; - } - - if (*min_address > *max_address) - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; + target_addr_t *min_address, target_addr_t *max_address) +{ + if (CMD_ARGC < 1 || CMD_ARGC > 5) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* a base address isn't always necessary, + * default to 0x0 (i.e. don't relocate) */ + if (CMD_ARGC >= 2) { + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); + image->base_address = addr; + image->base_address_set = 1; + } else + image->base_address_set = 0; + + image->start_address_set = 0; + + if (CMD_ARGC >= 4) + COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address); + if (CMD_ARGC == 5) { + COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address); + /* use size (given) to find max (required) */ + *max_address += *min_address; + } + + if (*min_address > *max_address) + return ERROR_COMMAND_SYNTAX_ERROR; + + return ERROR_OK; } COMMAND_HANDLER(handle_load_image_command) { - uint8_t *buffer; - size_t buf_cnt; - uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; - int i; - struct image image; - - int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, - &image, &min_address, &max_address); - if (ERROR_OK != retval) - return retval; - - struct target *target = get_current_target(CMD_CTX); - - struct duration bench; - duration_start(&bench); - - if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) - return ERROR_OK; - - image_size = 0x0; - retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { - buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, - "error allocating buffer for section (%d bytes)", - (int)(image.sections[i].size)); - break; - } - - retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); - if (retval != ERROR_OK) { - free(buffer); - break; - } - - uint32_t offset = 0; - uint32_t length = buf_cnt; - - /* DANGER!!! beware of unsigned comparision here!!! */ - - if ((image.sections[i].base_address + buf_cnt >= min_address) && - (image.sections[i].base_address < max_address)) { - - if (image.sections[i].base_address < min_address) { - /* clip addresses below */ - offset += min_address-image.sections[i].base_address; - length -= offset; - } - - if (image.sections[i].base_address + buf_cnt > max_address) - length -= (image.sections[i].base_address + buf_cnt)-max_address; - - retval = target_write_buffer(target, - image.sections[i].base_address + offset, length, buffer + offset); - if (retval != ERROR_OK) { - free(buffer); - break; - } - image_size += length; - command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "", - (unsigned int)length, - image.sections[i].base_address + offset); - } - - free(buffer); - } - - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " - "in %fs (%0.3f KiB/s)", image_size, - duration_elapsed(&bench), duration_kbps(&bench, image_size)); - } - - image_close(&image); - - return retval; - + uint8_t *buffer; + size_t buf_cnt; + uint32_t image_size; + target_addr_t min_address = 0; + target_addr_t max_address = -1; + int i; + struct image image; + + int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, + &image, &min_address, &max_address); + if (ERROR_OK != retval) + return retval; + + struct target *target = get_current_target(CMD_CTX); + + struct duration bench; + duration_start(&bench); + + if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) + return ERROR_FAIL; + + image_size = 0x0; + retval = ERROR_OK; + for (i = 0; i < image.num_sections; i++) { + buffer = malloc(image.sections[i].size); + if (buffer == NULL) { + command_print(CMD_CTX, + "error allocating buffer for section (%d bytes)", + (int)(image.sections[i].size)); + retval = ERROR_FAIL; + break; + } + + retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); + if (retval != ERROR_OK) { + free(buffer); + break; + } + + uint32_t offset = 0; + uint32_t length = buf_cnt; + + /* DANGER!!! beware of unsigned comparision here!!! */ + + if ((image.sections[i].base_address + buf_cnt >= min_address) && + (image.sections[i].base_address < max_address)) { + + if (image.sections[i].base_address < min_address) { + /* clip addresses below */ + offset += min_address-image.sections[i].base_address; + length -= offset; + } + + if (image.sections[i].base_address + buf_cnt > max_address) + length -= (image.sections[i].base_address + buf_cnt)-max_address; + + retval = target_write_buffer(target, + image.sections[i].base_address + offset, length, buffer + offset); + if (retval != ERROR_OK) { + free(buffer); + break; + } + image_size += length; + command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "", + (unsigned int)length, + image.sections[i].base_address + offset); + } + + free(buffer); + } + + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD_CTX, "downloaded %" PRIu32 " bytes " + "in %fs (%0.3f KiB/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); + } + + image_close(&image); + + return retval; + } COMMAND_HANDLER(handle_dump_image_command) { - struct fileio fileio; - uint8_t *buffer; - int retval, retvaltemp; - uint32_t address, size; - struct duration bench; - struct target *target = get_current_target(CMD_CTX); - - if (CMD_ARGC != 3) - return ERROR_COMMAND_SYNTAX_ERROR; - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); - - uint32_t buf_size = (size > 4096) ? 4096 : size; - buffer = malloc(buf_size); - if (!buffer) - return ERROR_FAIL; - - retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); - if (retval != ERROR_OK) { - free(buffer); - return retval; - } - - duration_start(&bench); - - while (size > 0) { - size_t size_written; - uint32_t this_run_size = (size > buf_size) ? buf_size : size; - retval = target_read_buffer(target, address, this_run_size, buffer); - if (retval != ERROR_OK) - break; - - retval = fileio_write(&fileio, this_run_size, buffer, &size_written); - if (retval != ERROR_OK) - break; - - size -= this_run_size; - address += this_run_size; - } - - free(buffer); - - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - size_t filesize; - retval = fileio_size(&fileio, &filesize); - if (retval != ERROR_OK) - return retval; - command_print(CMD_CTX, - "dumped %zu bytes in %fs (%0.3f KiB/s)", filesize, - duration_elapsed(&bench), duration_kbps(&bench, filesize)); - } - - retvaltemp = fileio_close(&fileio); - if (retvaltemp != ERROR_OK) - return retvaltemp; - - return retval; -} - -static COMMAND_HELPER(handle_verify_image_command_internal, int verify) -{ - uint8_t *buffer; - size_t buf_cnt; - uint32_t image_size; - int i; - int retval; - uint32_t checksum = 0; - uint32_t mem_checksum = 0; - - struct image image; - - struct target *target = get_current_target(CMD_CTX); - - if (CMD_ARGC < 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (!target) { - LOG_ERROR("no target selected"); - return ERROR_FAIL; - } - - struct duration bench; - duration_start(&bench); - - if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); - image.base_address = addr; - image.base_address_set = 1; - } else { - image.base_address_set = 0; - image.base_address = 0x0; - } - - image.start_address_set = 0; - - retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); - if (retval != ERROR_OK) - return retval; - - image_size = 0x0; - int diffs = 0; - retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { - buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, - "error allocating buffer for section (%d bytes)", - (int)(image.sections[i].size)); - break; - } - retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); - if (retval != ERROR_OK) { - free(buffer); - break; - } - - if (verify) { - /* calculate checksum of image */ - retval = image_calculate_checksum(buffer, buf_cnt, &checksum); - if (retval != ERROR_OK) { - free(buffer); - break; - } - - retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); - if (retval != ERROR_OK) { - free(buffer); - break; - } - - if (checksum != mem_checksum) { - /* failed crc checksum, fall back to a binary compare */ - uint8_t *data; - - if (diffs == 0) - LOG_ERROR("checksum mismatch - attempting binary compare"); - - data = malloc(buf_cnt); - - /* Can we use 32bit word accesses? */ - int size = 1; - int count = buf_cnt; - if ((count % 4) == 0) { - size *= 4; - count /= 4; - } - retval = target_read_memory(target, image.sections[i].base_address, size, count, data); - if (retval == ERROR_OK) { - uint32_t t; - for (t = 0; t < buf_cnt; t++) { - if (data[t] != buffer[t]) { - command_print(CMD_CTX, - "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", - diffs, - (unsigned)(t + image.sections[i].base_address), - data[t], - buffer[t]); - if (diffs++ >= 127) { - command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); - free(data); - free(buffer); - goto done; - } - } - keep_alive(); - } - } - free(data); - } - } else { - command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx", - image.sections[i].base_address, - buf_cnt); - } - - free(buffer); - image_size += buf_cnt; - } - if (diffs > 0) - command_print(CMD_CTX, "No more differences found."); -done: - if (diffs > 0) - retval = ERROR_FAIL; - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "verified %" PRIu32 " bytes " - "in %fs (%0.3f KiB/s)", image_size, - duration_elapsed(&bench), duration_kbps(&bench, image_size)); - } + struct fileio *fileio; + uint8_t *buffer; + int retval, retvaltemp; + target_addr_t address, size; + struct duration bench; + struct target *target = get_current_target(CMD_CTX); + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[2], size); + + uint32_t buf_size = (size > 4096) ? 4096 : size; + buffer = malloc(buf_size); + if (!buffer) + return ERROR_FAIL; + + retval = fileio_open(&fileio, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY); + if (retval != ERROR_OK) { + free(buffer); + return retval; + } + + duration_start(&bench); + + while (size > 0) { + size_t size_written; + uint32_t this_run_size = (size > buf_size) ? buf_size : size; + retval = target_read_buffer(target, address, this_run_size, buffer); + if (retval != ERROR_OK) + break; + + retval = fileio_write(fileio, this_run_size, buffer, &size_written); + if (retval != ERROR_OK) + break; + + size -= this_run_size; + address += this_run_size; + } + + free(buffer); + + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + size_t filesize; + retval = fileio_size(fileio, &filesize); + if (retval != ERROR_OK) + return retval; + command_print(CMD_CTX, + "dumped %zu bytes in %fs (%0.3f KiB/s)", filesize, + duration_elapsed(&bench), duration_kbps(&bench, filesize)); + } + + retvaltemp = fileio_close(fileio); + if (retvaltemp != ERROR_OK) + return retvaltemp; + + return retval; +} + +enum verify_mode { + IMAGE_TEST = 0, + IMAGE_VERIFY = 1, + IMAGE_CHECKSUM_ONLY = 2 +}; - image_close(&image); +static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode verify) +{ + uint8_t *buffer; + size_t buf_cnt; + uint32_t image_size; + int i; + int retval; + uint32_t checksum = 0; + uint32_t mem_checksum = 0; + + struct image image; + + struct target *target = get_current_target(CMD_CTX); + + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!target) { + LOG_ERROR("no target selected"); + return ERROR_FAIL; + } + + struct duration bench; + duration_start(&bench); + + if (CMD_ARGC >= 2) { + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); + image.base_address = addr; + image.base_address_set = 1; + } else { + image.base_address_set = 0; + image.base_address = 0x0; + } + + image.start_address_set = 0; + + retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); + if (retval != ERROR_OK) + return retval; + + image_size = 0x0; + int diffs = 0; + retval = ERROR_OK; + for (i = 0; i < image.num_sections; i++) { + buffer = malloc(image.sections[i].size); + if (buffer == NULL) { + command_print(CMD_CTX, + "error allocating buffer for section (%d bytes)", + (int)(image.sections[i].size)); + break; + } + retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); + if (retval != ERROR_OK) { + free(buffer); + break; + } + + if (verify >= IMAGE_VERIFY) { + /* calculate checksum of image */ + retval = image_calculate_checksum(buffer, buf_cnt, &checksum); + if (retval != ERROR_OK) { + free(buffer); + break; + } + + retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum); + if (retval != ERROR_OK) { + free(buffer); + break; + } + if ((checksum != mem_checksum) && (verify == IMAGE_CHECKSUM_ONLY)) { + LOG_ERROR("checksum mismatch"); + free(buffer); + retval = ERROR_FAIL; + goto done; + } + if (checksum != mem_checksum) { + /* failed crc checksum, fall back to a binary compare */ + uint8_t *data; + + if (diffs == 0) + LOG_ERROR("checksum mismatch - attempting binary compare"); + + data = malloc(buf_cnt); + + /* Can we use 32bit word accesses? */ + int size = 1; + int count = buf_cnt; + if ((count % 4) == 0) { + size *= 4; + count /= 4; + } + retval = target_read_memory(target, image.sections[i].base_address, size, count, data); + if (retval == ERROR_OK) { + uint32_t t; + for (t = 0; t < buf_cnt; t++) { + if (data[t] != buffer[t]) { + command_print(CMD_CTX, + "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", + diffs, + (unsigned)(t + image.sections[i].base_address), + data[t], + buffer[t]); + if (diffs++ >= 127) { + command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); + free(data); + free(buffer); + goto done; + } + } + keep_alive(); + } + } + free(data); + } + } else { + command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx", + image.sections[i].base_address, + buf_cnt); + } + + free(buffer); + image_size += buf_cnt; + } + if (diffs > 0) + command_print(CMD_CTX, "No more differences found."); +done: + if (diffs > 0) + retval = ERROR_FAIL; + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD_CTX, "verified %" PRIu32 " bytes " + "in %fs (%0.3f KiB/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); + } + + image_close(&image); + + return retval; +} - return retval; +COMMAND_HANDLER(handle_verify_image_checksum_command) +{ + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_CHECKSUM_ONLY); } COMMAND_HANDLER(handle_verify_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_VERIFY); } COMMAND_HANDLER(handle_test_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST); } static int handle_bp_command_list(struct command_context *cmd_ctx) { - struct target *target = get_current_target(cmd_ctx); - struct breakpoint *breakpoint = target->breakpoints; - while (breakpoint) { - if (breakpoint->type == BKPT_SOFT) { - char *buf = buf_to_str(breakpoint->orig_instr, - breakpoint->length, 16); - command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", - breakpoint->address, - breakpoint->length, - breakpoint->set, buf); - free(buf); - } else { - if ((breakpoint->address == 0) && (breakpoint->asid != 0)) - command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", - breakpoint->asid, - breakpoint->length, breakpoint->set); - else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", - breakpoint->address, - breakpoint->length, breakpoint->set); - command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, - breakpoint->asid); - } else - command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", - breakpoint->address, - breakpoint->length, breakpoint->set); - } - - breakpoint = breakpoint->next; - } - return ERROR_OK; + struct target *target = get_current_target(cmd_ctx); + struct breakpoint *breakpoint = target->breakpoints; + while (breakpoint) { + if (breakpoint->type == BKPT_SOFT) { + char *buf = buf_to_str(breakpoint->orig_instr, + breakpoint->length, 16); + command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", + breakpoint->address, + breakpoint->length, + breakpoint->set, buf); + free(buf); + } else { + if ((breakpoint->address == 0) && (breakpoint->asid != 0)) + command_print(cmd_ctx, "Context breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i", + breakpoint->asid, + breakpoint->length, breakpoint->set); + else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { + command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); + command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, + breakpoint->asid); + } else + command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", + breakpoint->address, + breakpoint->length, breakpoint->set); + } + + breakpoint = breakpoint->next; + } + return ERROR_OK; } static int handle_bp_command_set(struct command_context *cmd_ctx, - uint32_t addr, uint32_t asid, uint32_t length, int hw) -{ - struct target *target = get_current_target(cmd_ctx); - int retval; - - if (asid == 0) { - retval = breakpoint_add(target, addr, length, hw); - if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); - else { - LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); - return retval; - } - } else if (addr == 0) { - if (target->type->add_context_breakpoint == NULL) { - LOG_WARNING("Context breakpoint not available"); - return ERROR_OK; - } - retval = context_breakpoint_add(target, asid, length, hw); - if (ERROR_OK == retval) - command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); - return retval; - } - } else { - if (target->type->add_hybrid_breakpoint == NULL) { - LOG_WARNING("Hybrid breakpoint not available"); - return ERROR_OK; - } - retval = hybrid_breakpoint_add(target, addr, asid, length, hw); - if (ERROR_OK == retval) - command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); - else { - LOG_ERROR("Failure setting breakpoint, the same address is already used"); - return retval; - } - } - return ERROR_OK; + target_addr_t addr, uint32_t asid, uint32_t length, int hw) +{ + struct target *target = get_current_target(cmd_ctx); + int retval; + + if (asid == 0) { + retval = breakpoint_add(target, addr, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); + else { + LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); + return retval; + } + } else if (addr == 0) { + if (target->type->add_context_breakpoint == NULL) { + LOG_WARNING("Context breakpoint not available"); + return ERROR_OK; + } + retval = context_breakpoint_add(target, asid, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "Context breakpoint set at 0x%8.8" PRIx32 "", asid); + else { + LOG_ERROR("Failure setting breakpoint, the same address(CONTEXTID) is already used"); + return retval; + } + } else { + if (target->type->add_hybrid_breakpoint == NULL) { + LOG_WARNING("Hybrid breakpoint not available"); + return ERROR_OK; + } + retval = hybrid_breakpoint_add(target, addr, asid, length, hw); + if (ERROR_OK == retval) + command_print(cmd_ctx, "Hybrid breakpoint set at 0x%8.8" PRIx32 "", asid); + else { + LOG_ERROR("Failure setting breakpoint, the same address is already used"); + return retval; + } + } + return ERROR_OK; } COMMAND_HANDLER(handle_bp_command) { - uint32_t addr; - uint32_t asid; - uint32_t length; - int hw = BKPT_SOFT; - - switch (CMD_ARGC) { - case 0: - return handle_bp_command_list(CMD_CTX); - - case 2: - asid = 0; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); - - case 3: - if (strcmp(CMD_ARGV[2], "hw") == 0) { - hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - - asid = 0; - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); - } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { - hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - addr = 0; - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); - } - - case 4: - hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); - return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } + target_addr_t addr; + uint32_t asid; + uint32_t length; + int hw = BKPT_SOFT; + + switch (CMD_ARGC) { + case 0: + return handle_bp_command_list(CMD_CTX); + + case 2: + asid = 0; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + + case 3: + if (strcmp(CMD_ARGV[2], "hw") == 0) { + hw = BKPT_HARD; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + asid = 0; + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { + hw = BKPT_HARD; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], asid); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + addr = 0; + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + } + + case 4: + hw = BKPT_HARD; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); + return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); + + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } } COMMAND_HANDLER(handle_rbp_command) { - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - - struct target *target = get_current_target(CMD_CTX); - breakpoint_remove(target, addr); - - return ERROR_OK; + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); + + struct target *target = get_current_target(CMD_CTX); + breakpoint_remove(target, addr); + + return ERROR_OK; } COMMAND_HANDLER(handle_wp_command) { - struct target *target = get_current_target(CMD_CTX); - - if (CMD_ARGC == 0) { - struct watchpoint *watchpoint = target->watchpoints; - - while (watchpoint) { - command_print(CMD_CTX, "address: 0x%8.8" PRIx32 - ", len: 0x%8.8" PRIx32 - ", r/w/a: %i, value: 0x%8.8" PRIx32 - ", mask: 0x%8.8" PRIx32, - watchpoint->address, - watchpoint->length, - (int)watchpoint->rw, - watchpoint->value, - watchpoint->mask); - watchpoint = watchpoint->next; - } - return ERROR_OK; - } - - enum watchpoint_rw type = WPT_ACCESS; - uint32_t addr = 0; - uint32_t length = 0; - uint32_t data_value = 0x0; - uint32_t data_mask = 0xffffffff; - - switch (CMD_ARGC) { - case 5: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask); - /* fall through */ - case 4: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value); - /* fall through */ - case 3: - switch (CMD_ARGV[2][0]) { - case 'r': - type = WPT_READ; - break; - case 'w': - type = WPT_WRITE; - break; - case 'a': - type = WPT_ACCESS; - break; - default: - LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); - return ERROR_COMMAND_SYNTAX_ERROR; - } - /* fall through */ - case 2: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - int retval = watchpoint_add(target, addr, length, type, - data_value, data_mask); - if (ERROR_OK != retval) - LOG_ERROR("Failure setting watchpoints"); - - return retval; + struct target *target = get_current_target(CMD_CTX); + + if (CMD_ARGC == 0) { + struct watchpoint *watchpoint = target->watchpoints; + + while (watchpoint) { + command_print(CMD_CTX, "address: " TARGET_ADDR_FMT + ", len: 0x%8.8" PRIx32 + ", r/w/a: %i, value: 0x%8.8" PRIx32 + ", mask: 0x%8.8" PRIx32, + watchpoint->address, + watchpoint->length, + (int)watchpoint->rw, + watchpoint->value, + watchpoint->mask); + watchpoint = watchpoint->next; + } + return ERROR_OK; + } + + enum watchpoint_rw type = WPT_ACCESS; + uint32_t addr = 0; + uint32_t length = 0; + uint32_t data_value = 0x0; + uint32_t data_mask = 0xffffffff; + + switch (CMD_ARGC) { + case 5: + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], data_mask); + /* fall through */ + case 4: + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], data_value); + /* fall through */ + case 3: + switch (CMD_ARGV[2][0]) { + case 'r': + type = WPT_READ; + break; + case 'w': + type = WPT_WRITE; + break; + case 'a': + type = WPT_ACCESS; + break; + default: + LOG_ERROR("invalid watchpoint mode ('%c')", CMD_ARGV[2][0]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + /* fall through */ + case 2: + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + break; + + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } + + int retval = watchpoint_add(target, addr, length, type, + data_value, data_mask); + if (ERROR_OK != retval) + LOG_ERROR("Failure setting watchpoints"); + + return retval; } COMMAND_HANDLER(handle_rwp_command) { - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - - struct target *target = get_current_target(CMD_CTX); - watchpoint_remove(target, addr); - - return ERROR_OK; + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + uint32_t addr; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + + struct target *target = get_current_target(CMD_CTX); + watchpoint_remove(target, addr); + + return ERROR_OK; } /** @@ -3652,588 +3867,614 @@ COMMAND_HANDLER(handle_rwp_command) */ COMMAND_HANDLER(handle_virt2phys_command) { - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - uint32_t va; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va); - uint32_t pa; - - struct target *target = get_current_target(CMD_CTX); - int retval = target->type->virt2phys(target, va, &pa); - if (retval == ERROR_OK) - command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa); - - return retval; + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + target_addr_t va; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], va); + target_addr_t pa; + + struct target *target = get_current_target(CMD_CTX); + int retval = target->type->virt2phys(target, va, &pa); + if (retval == ERROR_OK) + command_print(CMD_CTX, "Physical address " TARGET_ADDR_FMT "", pa); + + return retval; } static void writeData(FILE *f, const void *data, size_t len) { - size_t written = fwrite(data, 1, len, f); - if (written != len) - LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno)); + size_t written = fwrite(data, 1, len, f); + if (written != len) + LOG_ERROR("failed to write %zu bytes: %s", len, strerror(errno)); } static void writeLong(FILE *f, int l, struct target *target) { - uint8_t val[4]; - - target_buffer_set_u32(target, val, l); - writeData(f, val, 4); + uint8_t val[4]; + + target_buffer_set_u32(target, val, l); + writeData(f, val, 4); } static void writeString(FILE *f, char *s) { - writeData(f, s, strlen(s)); + writeData(f, s, strlen(s)); } typedef unsigned char UNIT[2]; /* unit of profiling */ /* Dump a gmon.out histogram file. */ static void write_gmon(uint32_t *samples, uint32_t sampleNum, const char *filename, bool with_range, - uint32_t start_address, uint32_t end_address, struct target *target) -{ - uint32_t i; - FILE *f = fopen(filename, "w"); - if (f == NULL) - return; - writeString(f, "gmon"); - writeLong(f, 0x00000001, target); /* Version */ - writeLong(f, 0, target); /* padding */ - writeLong(f, 0, target); /* padding */ - writeLong(f, 0, target); /* padding */ - - uint8_t zero = 0; /* GMON_TAG_TIME_HIST */ - writeData(f, &zero, 1); - - /* figure out bucket size */ - uint32_t min; - uint32_t max; - if (with_range) { - min = start_address; - max = end_address; - } else { - min = samples[0]; - max = samples[0]; - for (i = 0; i < sampleNum; i++) { - if (min > samples[i]) - min = samples[i]; - if (max < samples[i]) - max = samples[i]; - } - - /* max should be (largest sample + 1) - * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ - max++; - } - - int addressSpace = max - min; - assert(addressSpace >= 2); - - /* FIXME: What is the reasonable number of buckets? - * The profiling result will be more accurate if there are enough buckets. */ - static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */ - uint32_t numBuckets = addressSpace / sizeof(UNIT); - if (numBuckets > maxBuckets) - numBuckets = maxBuckets; - int *buckets = malloc(sizeof(int) * numBuckets); - if (buckets == NULL) { - fclose(f); - return; - } - memset(buckets, 0, sizeof(int) * numBuckets); - for (i = 0; i < sampleNum; i++) { - uint32_t address = samples[i]; - - if ((address < min) || (max <= address)) - continue; - - long long a = address - min; - long long b = numBuckets; - long long c = addressSpace; - int index_t = (a * b) / c; /* danger!!!! int32 overflows */ - buckets[index_t]++; - } - - /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ - writeLong(f, min, target); /* low_pc */ - writeLong(f, max, target); /* high_pc */ - writeLong(f, numBuckets, target); /* # of buckets */ - writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */ - writeString(f, "seconds"); - for (i = 0; i < (15-strlen("seconds")); i++) - writeData(f, &zero, 1); - writeString(f, "s"); - - /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ - - char *data = malloc(2 * numBuckets); - if (data != NULL) { - for (i = 0; i < numBuckets; i++) { - int val; - val = buckets[i]; - if (val > 65535) - val = 65535; - data[i * 2] = val&0xff; - data[i * 2 + 1] = (val >> 8) & 0xff; - } - free(buckets); - writeData(f, data, numBuckets * 2); - free(data); - } else - free(buckets); - - fclose(f); + uint32_t start_address, uint32_t end_address, struct target *target) +{ + uint32_t i; + FILE *f = fopen(filename, "w"); + if (f == NULL) + return; + writeString(f, "gmon"); + writeLong(f, 0x00000001, target); /* Version */ + writeLong(f, 0, target); /* padding */ + writeLong(f, 0, target); /* padding */ + writeLong(f, 0, target); /* padding */ + + uint8_t zero = 0; /* GMON_TAG_TIME_HIST */ + writeData(f, &zero, 1); + + /* figure out bucket size */ + uint32_t min; + uint32_t max; + if (with_range) { + min = start_address; + max = end_address; + } else { + min = samples[0]; + max = samples[0]; + for (i = 0; i < sampleNum; i++) { + if (min > samples[i]) + min = samples[i]; + if (max < samples[i]) + max = samples[i]; + } + + /* max should be (largest sample + 1) + * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + max++; + } + + int addressSpace = max - min; + assert(addressSpace >= 2); + + /* FIXME: What is the reasonable number of buckets? + * The profiling result will be more accurate if there are enough buckets. */ + static const uint32_t maxBuckets = 128 * 1024; /* maximum buckets. */ + uint32_t numBuckets = addressSpace / sizeof(UNIT); + if (numBuckets > maxBuckets) + numBuckets = maxBuckets; + int *buckets = malloc(sizeof(int) * numBuckets); + if (buckets == NULL) { + fclose(f); + return; + } + memset(buckets, 0, sizeof(int) * numBuckets); + for (i = 0; i < sampleNum; i++) { + uint32_t address = samples[i]; + + if ((address < min) || (max <= address)) + continue; + + long long a = address - min; + long long b = numBuckets; + long long c = addressSpace; + int index_t = (a * b) / c; /* danger!!!! int32 overflows */ + buckets[index_t]++; + } + + /* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */ + writeLong(f, min, target); /* low_pc */ + writeLong(f, max, target); /* high_pc */ + writeLong(f, numBuckets, target); /* # of buckets */ + writeLong(f, 100, target); /* KLUDGE! We lie, ca. 100Hz best case. */ + writeString(f, "seconds"); + for (i = 0; i < (15-strlen("seconds")); i++) + writeData(f, &zero, 1); + writeString(f, "s"); + + /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ + + char *data = malloc(2 * numBuckets); + if (data != NULL) { + for (i = 0; i < numBuckets; i++) { + int val; + val = buckets[i]; + if (val > 65535) + val = 65535; + data[i * 2] = val&0xff; + data[i * 2 + 1] = (val >> 8) & 0xff; + } + free(buckets); + writeData(f, data, numBuckets * 2); + free(data); + } else + free(buckets); + + fclose(f); } /* profiling samples the CPU PC as quickly as OpenOCD is able, * which will be used as a random sampling of PC */ COMMAND_HANDLER(handle_profile_command) { - struct target *target = get_current_target(CMD_CTX); - - if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) - return ERROR_COMMAND_SYNTAX_ERROR; - - const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; - uint32_t offset; - uint32_t num_of_samples; - int retval = ERROR_OK; - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset); - - uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM); - if (samples == NULL) { - LOG_ERROR("No memory to store samples."); - return ERROR_FAIL; - } - - /** - * Some cores let us sample the PC without the - * annoying halt/resume step; for example, ARMv7 PCSR. - * Provide a way to use that more efficient mechanism. - */ - retval = target_profiling(target, samples, MAX_PROFILE_SAMPLE_NUM, - &num_of_samples, offset); - if (retval != ERROR_OK) { - free(samples); - return retval; - } - - assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM); - - retval = target_poll(target); - if (retval != ERROR_OK) { - free(samples); - return retval; - } - if (target->state == TARGET_RUNNING) { - retval = target_halt(target); - if (retval != ERROR_OK) { - free(samples); - return retval; - } - } - - retval = target_poll(target); - if (retval != ERROR_OK) { - free(samples); - return retval; - } - - uint32_t start_address = 0; - uint32_t end_address = 0; - bool with_range = false; - if (CMD_ARGC == 4) { - with_range = true; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address); - } - - write_gmon(samples, num_of_samples, CMD_ARGV[1], - with_range, start_address, end_address, target); - command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); - - free(samples); - return retval; + struct target *target = get_current_target(CMD_CTX); + + if ((CMD_ARGC != 2) && (CMD_ARGC != 4)) + return ERROR_COMMAND_SYNTAX_ERROR; + + const uint32_t MAX_PROFILE_SAMPLE_NUM = 10000; + uint32_t offset; + uint32_t num_of_samples; + int retval = ERROR_OK; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset); + + uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM); + if (samples == NULL) { + LOG_ERROR("No memory to store samples."); + return ERROR_FAIL; + } + + /** + * Some cores let us sample the PC without the + * annoying halt/resume step; for example, ARMv7 PCSR. + * Provide a way to use that more efficient mechanism. + */ + retval = target_profiling(target, samples, MAX_PROFILE_SAMPLE_NUM, + &num_of_samples, offset); + if (retval != ERROR_OK) { + free(samples); + return retval; + } + + assert(num_of_samples <= MAX_PROFILE_SAMPLE_NUM); + + retval = target_poll(target); + if (retval != ERROR_OK) { + free(samples); + return retval; + } + if (target->state == TARGET_RUNNING) { + retval = target_halt(target); + if (retval != ERROR_OK) { + free(samples); + return retval; + } + } + + retval = target_poll(target); + if (retval != ERROR_OK) { + free(samples); + return retval; + } + + uint32_t start_address = 0; + uint32_t end_address = 0; + bool with_range = false; + if (CMD_ARGC == 4) { + with_range = true; + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], start_address); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], end_address); + } + + write_gmon(samples, num_of_samples, CMD_ARGV[1], + with_range, start_address, end_address, target); + command_print(CMD_CTX, "Wrote %s", CMD_ARGV[1]); + + free(samples); + return retval; } static int new_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t val) { - char *namebuf; - Jim_Obj *nameObjPtr, *valObjPtr; - int result; - - namebuf = alloc_printf("%s(%d)", varname, idx); - if (!namebuf) - return JIM_ERR; - - nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); - valObjPtr = Jim_NewIntObj(interp, val); - if (!nameObjPtr || !valObjPtr) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(nameObjPtr); - Jim_IncrRefCount(valObjPtr); - result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); - Jim_DecrRefCount(interp, nameObjPtr); - Jim_DecrRefCount(interp, valObjPtr); - free(namebuf); - /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ - return result; + char *namebuf; + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + + namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; + + nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); + valObjPtr = Jim_NewIntObj(interp, val); + if (!nameObjPtr || !valObjPtr) { + free(namebuf); + return JIM_ERR; + } + + Jim_IncrRefCount(nameObjPtr); + Jim_IncrRefCount(valObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + Jim_DecrRefCount(interp, valObjPtr); + free(namebuf); + /* printf("%s(%d) <= 0%08x\n", varname, idx, val); */ + return result; } static int jim_mem2array(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct command_context *context; - struct target *target; - - context = current_command_context(interp); - assert(context != NULL); - - target = get_current_target(context); - if (target == NULL) { - LOG_ERROR("mem2array: no current target"); - return JIM_ERR; - } - - return target_mem2array(interp, target, argc - 1, argv + 1); + struct command_context *context; + struct target *target; + + context = current_command_context(interp); + assert(context != NULL); + + target = get_current_target(context); + if (target == NULL) { + LOG_ERROR("mem2array: no current target"); + return JIM_ERR; + } + + return target_mem2array(interp, target, argc - 1, argv + 1); } static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, Jim_Obj *const *argv) { - long l; - uint32_t width; - int len; - uint32_t addr; - uint32_t count; - uint32_t v; - const char *varname; - int n, e, retval; - uint32_t i; - - /* argv[1] = name of array to receive the data - * argv[2] = desired width - * argv[3] = memory address - * argv[4] = count of times to read - */ - if (argc != 4) { - Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems"); - return JIM_ERR; - } - varname = Jim_GetString(argv[0], &len); - /* given "foo" get space for worse case "foo(%d)" .. add 20 */ - - e = Jim_GetLong(interp, argv[1], &l); - width = l; - if (e != JIM_OK) - return e; - - e = Jim_GetLong(interp, argv[2], &l); - addr = l; - if (e != JIM_OK) - return e; - e = Jim_GetLong(interp, argv[3], &l); - len = l; - if (e != JIM_OK) - return e; - switch (width) { - case 8: - width = 1; - break; - case 16: - width = 2; - break; - case 32: - width = 4; - break; - default: - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL); - return JIM_ERR; - } - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); - return JIM_ERR; - } - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - /* absurd transfer size? */ - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0))) { - /* all is well */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", - addr, - width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* index counter */ - n = 0; - - size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (buffer == NULL) - return JIM_ERR; - - /* assume ok */ - e = JIM_OK; - while (len) { - /* Slurp... in buffer size chunks */ - - count = len; /* in objects.. */ - if (count > (buffersize / width)) - count = (buffersize / width); - - retval = target_read_memory(target, addr, width, count, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); - e = JIM_ERR; - break; - } else { - v = 0; /* shut up gcc */ - for (i = 0; i < count ; i++, n++) { - switch (width) { - case 4: - v = target_buffer_get_u32(target, &buffer[i*width]); - break; - case 2: - v = target_buffer_get_u16(target, &buffer[i*width]); - break; - case 1: - v = buffer[i] & 0x0ff; - break; - } - new_int_array_element(interp, varname, n, v); - } - len -= count; - addr += count * width; - } - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; + long l; + uint32_t width; + int len; + uint32_t addr; + uint32_t count; + uint32_t v; + const char *varname; + const char *phys; + bool is_phys; + int n, e, retval; + uint32_t i; + + /* argv[1] = name of array to receive the data + * argv[2] = desired width + * argv[3] = memory address + * argv[4] = count of times to read + */ + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]"); + return JIM_ERR; + } + varname = Jim_GetString(argv[0], &len); + /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + + e = Jim_GetLong(interp, argv[1], &l); + width = l; + if (e != JIM_OK) + return e; + + e = Jim_GetLong(interp, argv[2], &l); + addr = l; + if (e != JIM_OK) + return e; + e = Jim_GetLong(interp, argv[3], &l); + len = l; + if (e != JIM_OK) + return e; + is_phys = false; + if (argc > 4) { + phys = Jim_GetString(argv[4], &n); + if (!strncmp(phys, "phys", n)) + is_phys = true; + else + return JIM_ERR; + } + switch (width) { + case 8: + width = 1; + break; + case 16: + width = 2; + break; + case 32: + width = 4; + break; + default: + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Invalid width param, must be 8/16/32", NULL); + return JIM_ERR; + } + if (len == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: zero width read?", NULL); + return JIM_ERR; + } + if ((addr + (len * width)) < addr) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: addr + len - wraps to zero?", NULL); + return JIM_ERR; + } + /* absurd transfer size? */ + if (len > 65536) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: absurd > 64K item request", NULL); + return JIM_ERR; + } + + if ((width == 1) || + ((width == 2) && ((addr & 1) == 0)) || + ((width == 4) && ((addr & 3) == 0))) { + /* all is well */ + } else { + char buf[100]; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + addr, + width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); + return JIM_ERR; + } + + /* Transfer loop */ + + /* index counter */ + n = 0; + + size_t buffersize = 4096; + uint8_t *buffer = malloc(buffersize); + if (buffer == NULL) + return JIM_ERR; + + /* assume ok */ + e = JIM_OK; + while (len) { + /* Slurp... in buffer size chunks */ + + count = len; /* in objects.. */ + if (count > (buffersize / width)) + count = (buffersize / width); + + if (is_phys) + retval = target_read_phys_memory(target, addr, width, count, buffer); + else + retval = target_read_memory(target, addr, width, count, buffer); + if (retval != ERROR_OK) { + /* BOO !*/ + LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); + e = JIM_ERR; + break; + } else { + v = 0; /* shut up gcc */ + for (i = 0; i < count ; i++, n++) { + switch (width) { + case 4: + v = target_buffer_get_u32(target, &buffer[i*width]); + break; + case 2: + v = target_buffer_get_u16(target, &buffer[i*width]); + break; + case 1: + v = buffer[i] & 0x0ff; + break; + } + new_int_array_element(interp, varname, n, v); + } + len -= count; + addr += count * width; + } + } + + free(buffer); + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + + return e; } static int get_int_array_element(Jim_Interp *interp, const char *varname, int idx, uint32_t *val) { - char *namebuf; - Jim_Obj *nameObjPtr, *valObjPtr; - int result; - long l; - - namebuf = alloc_printf("%s(%d)", varname, idx); - if (!namebuf) - return JIM_ERR; - - nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); - if (!nameObjPtr) { - free(namebuf); - return JIM_ERR; - } - - Jim_IncrRefCount(nameObjPtr); - valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); - Jim_DecrRefCount(interp, nameObjPtr); - free(namebuf); - if (valObjPtr == NULL) - return JIM_ERR; - - result = Jim_GetLong(interp, valObjPtr, &l); - /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ - *val = l; - return result; + char *namebuf; + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + long l; + + namebuf = alloc_printf("%s(%d)", varname, idx); + if (!namebuf) + return JIM_ERR; + + nameObjPtr = Jim_NewStringObj(interp, namebuf, -1); + if (!nameObjPtr) { + free(namebuf); + return JIM_ERR; + } + + Jim_IncrRefCount(nameObjPtr); + valObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG); + Jim_DecrRefCount(interp, nameObjPtr); + free(namebuf); + if (valObjPtr == NULL) + return JIM_ERR; + + result = Jim_GetLong(interp, valObjPtr, &l); + /* printf("%s(%d) => 0%08x\n", varname, idx, val); */ + *val = l; + return result; } static int jim_array2mem(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - struct command_context *context; - struct target *target; - - context = current_command_context(interp); - assert(context != NULL); - - target = get_current_target(context); - if (target == NULL) { - LOG_ERROR("array2mem: no current target"); - return JIM_ERR; - } - - return target_array2mem(interp, target, argc-1, argv + 1); + struct command_context *context; + struct target *target; + + context = current_command_context(interp); + assert(context != NULL); + + target = get_current_target(context); + if (target == NULL) { + LOG_ERROR("array2mem: no current target"); + return JIM_ERR; + } + + return target_array2mem(interp, target, argc-1, argv + 1); } static int target_array2mem(Jim_Interp *interp, struct target *target, - int argc, Jim_Obj *const *argv) -{ - long l; - uint32_t width; - int len; - uint32_t addr; - uint32_t count; - uint32_t v; - const char *varname; - int n, e, retval; - uint32_t i; - - /* argv[1] = name of array to get the data - * argv[2] = desired width - * argv[3] = memory address - * argv[4] = count to write - */ - if (argc != 4) { - Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems"); - return JIM_ERR; - } - varname = Jim_GetString(argv[0], &len); - /* given "foo" get space for worse case "foo(%d)" .. add 20 */ - - e = Jim_GetLong(interp, argv[1], &l); - width = l; - if (e != JIM_OK) - return e; - - e = Jim_GetLong(interp, argv[2], &l); - addr = l; - if (e != JIM_OK) - return e; - e = Jim_GetLong(interp, argv[3], &l); - len = l; - if (e != JIM_OK) - return e; - switch (width) { - case 8: - width = 1; - break; - case 16: - width = 2; - break; - case 32: - width = 4; - break; - default: - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "Invalid width param, must be 8/16/32", NULL); - return JIM_ERR; - } - if (len == 0) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: zero width read?", NULL); - return JIM_ERR; - } - if ((addr + (len * width)) < addr) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: addr + len - wraps to zero?", NULL); - return JIM_ERR; - } - /* absurd transfer size? */ - if (len > 65536) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), - "array2mem: absurd > 64K item request", NULL); - return JIM_ERR; - } - - if ((width == 1) || - ((width == 2) && ((addr & 1) == 0)) || - ((width == 4) && ((addr & 3) == 0))) { - /* all is well */ - } else { - char buf[100]; - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", - (unsigned int)addr, - (int)width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); - return JIM_ERR; - } - - /* Transfer loop */ - - /* index counter */ - n = 0; - /* assume ok */ - e = JIM_OK; - - size_t buffersize = 4096; - uint8_t *buffer = malloc(buffersize); - if (buffer == NULL) - return JIM_ERR; - - while (len) { - /* Slurp... in buffer size chunks */ - - count = len; /* in objects.. */ - if (count > (buffersize / width)) - count = (buffersize / width); - - v = 0; /* shut up gcc */ - for (i = 0; i < count; i++, n++) { - get_int_array_element(interp, varname, n, &v); - switch (width) { - case 4: - target_buffer_set_u32(target, &buffer[i * width], v); - break; - case 2: - target_buffer_set_u16(target, &buffer[i * width], v); - break; - case 1: - buffer[i] = v & 0x0ff; - break; - } - } - len -= count; - - retval = target_write_memory(target, addr, width, count, buffer); - if (retval != ERROR_OK) { - /* BOO !*/ - LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); - e = JIM_ERR; - break; - } - addr += count * width; - } - - free(buffer); - - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - - return e; + int argc, Jim_Obj *const *argv) +{ + long l; + uint32_t width; + int len; + uint32_t addr; + uint32_t count; + uint32_t v; + const char *varname; + const char *phys; + bool is_phys; + int n, e, retval; + uint32_t i; + + /* argv[1] = name of array to get the data + * argv[2] = desired width + * argv[3] = memory address + * argv[4] = count to write + */ + if (argc < 4 || argc > 5) { + Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); + return JIM_ERR; + } + varname = Jim_GetString(argv[0], &len); + /* given "foo" get space for worse case "foo(%d)" .. add 20 */ + + e = Jim_GetLong(interp, argv[1], &l); + width = l; + if (e != JIM_OK) + return e; + + e = Jim_GetLong(interp, argv[2], &l); + addr = l; + if (e != JIM_OK) + return e; + e = Jim_GetLong(interp, argv[3], &l); + len = l; + if (e != JIM_OK) + return e; + is_phys = false; + if (argc > 4) { + phys = Jim_GetString(argv[4], &n); + if (!strncmp(phys, "phys", n)) + is_phys = true; + else + return JIM_ERR; + } + switch (width) { + case 8: + width = 1; + break; + case 16: + width = 2; + break; + case 32: + width = 4; + break; + default: + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "Invalid width param, must be 8/16/32", NULL); + return JIM_ERR; + } + if (len == 0) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "array2mem: zero width read?", NULL); + return JIM_ERR; + } + if ((addr + (len * width)) < addr) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "array2mem: addr + len - wraps to zero?", NULL); + return JIM_ERR; + } + /* absurd transfer size? */ + if (len > 65536) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), + "array2mem: absurd > 64K item request", NULL); + return JIM_ERR; + } + + if ((width == 1) || + ((width == 2) && ((addr & 1) == 0)) || + ((width == 4) && ((addr & 3) == 0))) { + /* all is well */ + } else { + char buf[100]; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + addr, + width); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); + return JIM_ERR; + } + + /* Transfer loop */ + + /* index counter */ + n = 0; + /* assume ok */ + e = JIM_OK; + + size_t buffersize = 4096; + uint8_t *buffer = malloc(buffersize); + if (buffer == NULL) + return JIM_ERR; + + while (len) { + /* Slurp... in buffer size chunks */ + + count = len; /* in objects.. */ + if (count > (buffersize / width)) + count = (buffersize / width); + + v = 0; /* shut up gcc */ + for (i = 0; i < count; i++, n++) { + get_int_array_element(interp, varname, n, &v); + switch (width) { + case 4: + target_buffer_set_u32(target, &buffer[i * width], v); + break; + case 2: + target_buffer_set_u16(target, &buffer[i * width], v); + break; + case 1: + buffer[i] = v & 0x0ff; + break; + } + } + len -= count; + + if (is_phys) + retval = target_write_phys_memory(target, addr, width, count, buffer); + else + retval = target_write_memory(target, addr, width, count, buffer); + if (retval != ERROR_OK) { + /* BOO !*/ + LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); + e = JIM_ERR; + break; + } + addr += count * width; + } + + free(buffer); + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + + return e; } /* FIX? should we propagate errors here rather than printing them @@ -4241,23 +4482,23 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, */ void target_handle_event(struct target *target, enum target_event e) { - struct target_event_action *teap; - - for (teap = target->event_action; teap != NULL; teap = teap->next) { - if (teap->event == e) { - LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", - target->target_number, - target_name(target), - target_type_name(target), - e, - Jim_Nvp_value2name_simple(nvp_target_event, e)->name, - Jim_GetString(teap->body, NULL)); - if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { - Jim_MakeErrorMessage(teap->interp); - command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); - } - } - } + struct target_event_action *teap; + + for (teap = target->event_action; teap != NULL; teap = teap->next) { + if (teap->event == e) { + LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s", + target->target_number, + target_name(target), + target_type_name(target), + e, + Jim_Nvp_value2name_simple(nvp_target_event, e)->name, + Jim_GetString(teap->body, NULL)); + if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) { + Jim_MakeErrorMessage(teap->interp); + command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL)); + } + } + } } /** @@ -4265,1919 +4506,2016 @@ void target_handle_event(struct target *target, enum target_event e) */ bool target_has_event_action(struct target *target, enum target_event event) { - struct target_event_action *teap; - - for (teap = target->event_action; teap != NULL; teap = teap->next) { - if (teap->event == event) - return true; - } - return false; + struct target_event_action *teap; + + for (teap = target->event_action; teap != NULL; teap = teap->next) { + if (teap->event == event) + return true; + } + return false; } enum target_cfg_param { - TCFG_TYPE, - TCFG_EVENT, - TCFG_WORK_AREA_VIRT, - TCFG_WORK_AREA_PHYS, - TCFG_WORK_AREA_SIZE, - TCFG_WORK_AREA_BACKUP, - TCFG_ENDIAN, - TCFG_COREID, - TCFG_CHAIN_POSITION, - TCFG_DBGBASE, - TCFG_RTOS, + TCFG_TYPE, + TCFG_EVENT, + TCFG_WORK_AREA_VIRT, + TCFG_WORK_AREA_PHYS, + TCFG_WORK_AREA_SIZE, + TCFG_WORK_AREA_BACKUP, + TCFG_ENDIAN, + TCFG_COREID, + TCFG_CHAIN_POSITION, + TCFG_DBGBASE, + TCFG_CTIBASE, + TCFG_RTOS, + TCFG_DEFER_EXAMINE, }; static Jim_Nvp nvp_config_opts[] = { - { .name = "-type", .value = TCFG_TYPE }, - { .name = "-event", .value = TCFG_EVENT }, - { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, - { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS }, - { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE }, - { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP }, - { .name = "-endian" , .value = TCFG_ENDIAN }, - { .name = "-coreid", .value = TCFG_COREID }, - { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, - { .name = "-dbgbase", .value = TCFG_DBGBASE }, - { .name = "-rtos", .value = TCFG_RTOS }, - { .name = NULL, .value = -1 } + { .name = "-type", .value = TCFG_TYPE }, + { .name = "-event", .value = TCFG_EVENT }, + { .name = "-work-area-virt", .value = TCFG_WORK_AREA_VIRT }, + { .name = "-work-area-phys", .value = TCFG_WORK_AREA_PHYS }, + { .name = "-work-area-size", .value = TCFG_WORK_AREA_SIZE }, + { .name = "-work-area-backup", .value = TCFG_WORK_AREA_BACKUP }, + { .name = "-endian" , .value = TCFG_ENDIAN }, + { .name = "-coreid", .value = TCFG_COREID }, + { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, + { .name = "-dbgbase", .value = TCFG_DBGBASE }, + { .name = "-ctibase", .value = TCFG_CTIBASE }, + { .name = "-rtos", .value = TCFG_RTOS }, + { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, + { .name = NULL, .value = -1 } }; static int target_configure(Jim_GetOptInfo *goi, struct target *target) { - Jim_Nvp *n; - Jim_Obj *o; - jim_wide w; - int e; - - /* parse config or cget options ... */ - while (goi->argc > 0) { - Jim_SetEmptyResult(goi->interp); - /* Jim_GetOpt_Debug(goi); */ - - if (target->type->target_jim_configure) { - /* target defines a configure function */ - /* target gets first dibs on parameters */ - e = (*(target->type->target_jim_configure))(target, goi); - if (e == JIM_OK) { - /* more? */ - continue; - } - if (e == JIM_ERR) { - /* An error */ - return e; - } - /* otherwise we 'continue' below */ - } - e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); - return e; - } - switch (n->value) { - case TCFG_TYPE: - /* not setable */ - if (goi->isconfigure) { - Jim_SetResultFormatted(goi->interp, - "not settable: %s", n->name); - return JIM_ERR; - } else { -no_params: - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, - goi->argc, goi->argv, - "NO PARAMS"); - return JIM_ERR; - } - } - Jim_SetResultString(goi->interp, - target_type_name(target), -1); - /* loop for more */ - break; - case TCFG_EVENT: - if (goi->argc == 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); - return JIM_ERR; - } - - e = Jim_GetOpt_Nvp(goi, nvp_target_event, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_target_event, 1); - return e; - } - - if (goi->isconfigure) { - if (goi->argc != 1) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); - return JIM_ERR; - } - } else { - if (goi->argc != 0) { - Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); - return JIM_ERR; - } - } - - { - struct target_event_action *teap; - - teap = target->event_action; - /* replace existing? */ - while (teap) { - if (teap->event == (enum target_event)n->value) - break; - teap = teap->next; - } - - if (goi->isconfigure) { - bool replace = true; - if (teap == NULL) { - /* create new */ - teap = calloc(1, sizeof(*teap)); - replace = false; - } - teap->event = n->value; - teap->interp = goi->interp; - Jim_GetOpt_Obj(goi, &o); - if (teap->body) - Jim_DecrRefCount(teap->interp, teap->body); - teap->body = Jim_DuplicateObj(goi->interp, o); - /* - * FIXME: - * Tcl/TK - "tk events" have a nice feature. - * See the "BIND" command. - * We should support that here. - * You can specify %X and %Y in the event code. - * The idea is: %T - target name. - * The idea is: %N - target number - * The idea is: %E - event name. - */ - Jim_IncrRefCount(teap->body); - - if (!replace) { - /* add to head of event list */ - teap->next = target->event_action; - target->event_action = teap; - } - Jim_SetEmptyResult(goi->interp); - } else { - /* get */ - if (teap == NULL) - Jim_SetEmptyResult(goi->interp); - else - Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); - } - } - /* loop for more */ - break; - - case TCFG_WORK_AREA_VIRT: - if (goi->isconfigure) { - target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_virt = w; - target->working_area_virt_spec = true; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); - /* loop for more */ - break; - - case TCFG_WORK_AREA_PHYS: - if (goi->isconfigure) { - target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_phys = w; - target->working_area_phys_spec = true; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); - /* loop for more */ - break; - - case TCFG_WORK_AREA_SIZE: - if (goi->isconfigure) { - target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - target->working_area_size = w; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); - /* loop for more */ - break; - - case TCFG_WORK_AREA_BACKUP: - if (goi->isconfigure) { - target_free_all_working_areas(target); - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - /* make this exactly 1 or 0 */ - target->backup_working_area = (!!w); - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); - /* loop for more e*/ - break; - - - case TCFG_ENDIAN: - if (goi->isconfigure) { - e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(goi, nvp_target_endian, 1); - return e; - } - target->endianness = n->value; - } else { - if (goi->argc != 0) - goto no_params; - } - n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); - if (n->name == NULL) { - target->endianness = TARGET_LITTLE_ENDIAN; - n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); - } - Jim_SetResultString(goi->interp, n->name, -1); - /* loop for more */ - break; - - case TCFG_COREID: - if (goi->isconfigure) { - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - target->coreid = (int32_t)w; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); - /* loop for more */ - break; - - case TCFG_CHAIN_POSITION: - if (goi->isconfigure) { - Jim_Obj *o_t; - struct jtag_tap *tap; - target_free_all_working_areas(target); - e = Jim_GetOpt_Obj(goi, &o_t); - if (e != JIM_OK) - return e; - tap = jtag_tap_by_jim_obj(goi->interp, o_t); - if (tap == NULL) - return JIM_ERR; - /* make this exactly 1 or 0 */ - target->tap = tap; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); - /* loop for more e*/ - break; - case TCFG_DBGBASE: - if (goi->isconfigure) { - e = Jim_GetOpt_Wide(goi, &w); - if (e != JIM_OK) - return e; - target->dbgbase = (uint32_t)w; - target->dbgbase_set = true; - } else { - if (goi->argc != 0) - goto no_params; - } - Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); - /* loop for more */ - break; - - case TCFG_RTOS: - /* RTOS */ - { - int result = rtos_create(goi, target); - if (result != JIM_OK) - return result; - } - /* loop for more */ - break; - } - } /* while (goi->argc) */ - - - /* done - we return */ - return JIM_OK; + Jim_Nvp *n; + Jim_Obj *o; + jim_wide w; + int e; + + /* parse config or cget options ... */ + while (goi->argc > 0) { + Jim_SetEmptyResult(goi->interp); + /* Jim_GetOpt_Debug(goi); */ + + if (target->type->target_jim_configure) { + /* target defines a configure function */ + /* target gets first dibs on parameters */ + e = (*(target->type->target_jim_configure))(target, goi); + if (e == JIM_OK) { + /* more? */ + continue; + } + if (e == JIM_ERR) { + /* An error */ + return e; + } + /* otherwise we 'continue' below */ + } + e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0); + return e; + } + switch (n->value) { + case TCFG_TYPE: + /* not setable */ + if (goi->isconfigure) { + Jim_SetResultFormatted(goi->interp, + "not settable: %s", n->name); + return JIM_ERR; + } else { + no_params: + if (goi->argc != 0) { + Jim_WrongNumArgs(goi->interp, + goi->argc, goi->argv, + "NO PARAMS"); + return JIM_ERR; + } + } + Jim_SetResultString(goi->interp, + target_type_name(target), -1); + /* loop for more */ + break; + case TCFG_EVENT: + if (goi->argc == 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ..."); + return JIM_ERR; + } + + e = Jim_GetOpt_Nvp(goi, nvp_target_event, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_target_event, 1); + return e; + } + + if (goi->isconfigure) { + if (goi->argc != 1) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name? ?EVENT-BODY?"); + return JIM_ERR; + } + } else { + if (goi->argc != 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-event ?event-name?"); + return JIM_ERR; + } + } + + { + struct target_event_action *teap; + + teap = target->event_action; + /* replace existing? */ + while (teap) { + if (teap->event == (enum target_event)n->value) + break; + teap = teap->next; + } + + if (goi->isconfigure) { + bool replace = true; + if (teap == NULL) { + /* create new */ + teap = calloc(1, sizeof(*teap)); + replace = false; + } + teap->event = n->value; + teap->interp = goi->interp; + Jim_GetOpt_Obj(goi, &o); + if (teap->body) + Jim_DecrRefCount(teap->interp, teap->body); + teap->body = Jim_DuplicateObj(goi->interp, o); + /* + * FIXME: + * Tcl/TK - "tk events" have a nice feature. + * See the "BIND" command. + * We should support that here. + * You can specify %X and %Y in the event code. + * The idea is: %T - target name. + * The idea is: %N - target number + * The idea is: %E - event name. + */ + Jim_IncrRefCount(teap->body); + + if (!replace) { + /* add to head of event list */ + teap->next = target->event_action; + target->event_action = teap; + } + Jim_SetEmptyResult(goi->interp); + } else { + /* get */ + if (teap == NULL) + Jim_SetEmptyResult(goi->interp); + else + Jim_SetResult(goi->interp, Jim_DuplicateObj(goi->interp, teap->body)); + } + } + /* loop for more */ + break; + + case TCFG_WORK_AREA_VIRT: + if (goi->isconfigure) { + target_free_all_working_areas(target); + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->working_area_virt = w; + target->working_area_virt_spec = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_virt)); + /* loop for more */ + break; + + case TCFG_WORK_AREA_PHYS: + if (goi->isconfigure) { + target_free_all_working_areas(target); + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->working_area_phys = w; + target->working_area_phys_spec = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_phys)); + /* loop for more */ + break; + + case TCFG_WORK_AREA_SIZE: + if (goi->isconfigure) { + target_free_all_working_areas(target); + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->working_area_size = w; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); + /* loop for more */ + break; + + case TCFG_WORK_AREA_BACKUP: + if (goi->isconfigure) { + target_free_all_working_areas(target); + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + /* make this exactly 1 or 0 */ + target->backup_working_area = (!!w); + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->backup_working_area)); + /* loop for more e*/ + break; + + + case TCFG_ENDIAN: + if (goi->isconfigure) { + e = Jim_GetOpt_Nvp(goi, nvp_target_endian, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(goi, nvp_target_endian, 1); + return e; + } + target->endianness = n->value; + } else { + if (goi->argc != 0) + goto no_params; + } + n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); + if (n->name == NULL) { + target->endianness = TARGET_LITTLE_ENDIAN; + n = Jim_Nvp_value2name_simple(nvp_target_endian, target->endianness); + } + Jim_SetResultString(goi->interp, n->name, -1); + /* loop for more */ + break; + + case TCFG_COREID: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->coreid = (int32_t)w; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->working_area_size)); + /* loop for more */ + break; + + case TCFG_CHAIN_POSITION: + if (goi->isconfigure) { + Jim_Obj *o_t; + struct jtag_tap *tap; + target_free_all_working_areas(target); + e = Jim_GetOpt_Obj(goi, &o_t); + if (e != JIM_OK) + return e; + tap = jtag_tap_by_jim_obj(goi->interp, o_t); + if (tap == NULL) + return JIM_ERR; + /* make this exactly 1 or 0 */ + target->tap = tap; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResultString(goi->interp, target->tap->dotted_name, -1); + /* loop for more e*/ + break; + case TCFG_DBGBASE: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->dbgbase = (uint32_t)w; + target->dbgbase_set = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); + /* loop for more */ + break; + case TCFG_CTIBASE: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->ctibase = (uint32_t)w; + target->ctibase_set = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase)); + /* loop for more */ + break; + case TCFG_RTOS: + /* RTOS */ + { + int result = rtos_create(goi, target); + if (result != JIM_OK) + return result; + } + /* loop for more */ + break; + + case TCFG_DEFER_EXAMINE: + /* DEFER_EXAMINE */ + target->defer_examine = true; + /* loop for more */ + break; + + } + } /* while (goi->argc) */ + + + /* done - we return */ + return JIM_OK; } static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *argv) { - Jim_GetOptInfo goi; - - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); - int need_args = 1 + goi.isconfigure; - if (goi.argc < need_args) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - goi.isconfigure - ? "missing: -option VALUE ..." - : "missing: -option ..."); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(goi.interp); - return target_configure(&goi, target); -} - -static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - const char *cmd_name = Jim_GetString(argv[0], NULL); - - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - - if (goi.argc < 2 || goi.argc > 4) { - Jim_SetResultFormatted(goi.interp, - "usage: %s [phys]
[]", cmd_name); - return JIM_ERR; - } - - target_write_fn fn; - fn = target_write_memory; - - int e; - if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { - /* consume it */ - struct Jim_Obj *obj; - e = Jim_GetOpt_Obj(&goi, &obj); - if (e != JIM_OK) - return e; - - fn = target_write_phys_memory; - } - - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) - return e; - - jim_wide b; - e = Jim_GetOpt_Wide(&goi, &b); - if (e != JIM_OK) - return e; - - jim_wide c = 1; - if (goi.argc == 1) { - e = Jim_GetOpt_Wide(&goi, &c); - if (e != JIM_OK) - return e; - } - - /* all args must be consumed */ - if (goi.argc != 0) - return JIM_ERR; - - struct target *target = Jim_CmdPrivData(goi.interp); - unsigned data_size; - if (strcasecmp(cmd_name, "mww") == 0) - data_size = 4; - else if (strcasecmp(cmd_name, "mwh") == 0) - data_size = 2; - else if (strcasecmp(cmd_name, "mwb") == 0) - data_size = 1; - else { - LOG_ERROR("command '%s' unknown: ", cmd_name); - return JIM_ERR; - } - - return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; -} - -/** -* @brief Reads an array of words/halfwords/bytes from target memory starting at specified address. -* -* Usage: mdw [phys]
[] - for 32 bit reads -* mdh [phys]
[] - for 16 bit reads -* mdb [phys]
[] - for 8 bit reads -* -* Count defaults to 1. -* -* Calls target_read_memory or target_read_phys_memory depending on -* the presence of the "phys" argument -* Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted -* to int representation in base16. -* Also outputs read data in a human readable form using command_print -* -* @param phys if present target_read_phys_memory will be used instead of target_read_memory -* @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix -* @param count optional count parameter to read an array of values. If not specified, defaults to 1. -* @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers -* on success, with [] number of elements. -* -* In case of little endian target: -* Example1: "mdw 0x00000000" returns "10123456" -* Exmaple2: "mdh 0x00000000 1" returns "3456" -* Example3: "mdb 0x00000000" returns "56" -* Example4: "mdh 0x00000000 2" returns "3456 1012" -* Example5: "mdb 0x00000000 3" returns "56 34 12" -**/ -static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - const char *cmd_name = Jim_GetString(argv[0], NULL); - - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - - if ((goi.argc < 1) || (goi.argc > 3)) { - Jim_SetResultFormatted(goi.interp, - "usage: %s [phys]
[]", cmd_name); - return JIM_ERR; - } - - int (*fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); - fn = target_read_memory; - - int e; - if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { - /* consume it */ - struct Jim_Obj *obj; - e = Jim_GetOpt_Obj(&goi, &obj); - if (e != JIM_OK) - return e; - - fn = target_read_phys_memory; - } - - /* Read address parameter */ - jim_wide addr; - e = Jim_GetOpt_Wide(&goi, &addr); - if (e != JIM_OK) - return JIM_ERR; - - /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */ - jim_wide count; - if (goi.argc == 1) { - e = Jim_GetOpt_Wide(&goi, &count); - if (e != JIM_OK) - return JIM_ERR; - } else - count = 1; - - /* all args must be consumed */ - if (goi.argc != 0) - return JIM_ERR; - - jim_wide dwidth = 1; /* shut up gcc */ - if (strcasecmp(cmd_name, "mdw") == 0) - dwidth = 4; - else if (strcasecmp(cmd_name, "mdh") == 0) - dwidth = 2; - else if (strcasecmp(cmd_name, "mdb") == 0) - dwidth = 1; - else { - LOG_ERROR("command '%s' unknown: ", cmd_name); - return JIM_ERR; - } - - /* convert count to "bytes" */ - int bytes = count * dwidth; - - struct target *target = Jim_CmdPrivData(goi.interp); - uint8_t target_buf[32]; - jim_wide x, y, z; - while (bytes > 0) { - y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */ - - /* Try to read out next block */ - e = fn(target, addr, dwidth, y / dwidth, target_buf); - - if (e != ERROR_OK) { - Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); - return JIM_ERR; - } - - command_print_sameline(NULL, "0x%08x ", (int)(addr)); - switch (dwidth) { - case 4: - for (x = 0; x < 16 && x < y; x += 4) { - z = target_buffer_get_u32(target, &(target_buf[x])); - command_print_sameline(NULL, "%08x ", (int)(z)); - } - for (; (x < 16) ; x += 4) - command_print_sameline(NULL, " "); - break; - case 2: - for (x = 0; x < 16 && x < y; x += 2) { - z = target_buffer_get_u16(target, &(target_buf[x])); - command_print_sameline(NULL, "%04x ", (int)(z)); - } - for (; (x < 16) ; x += 2) - command_print_sameline(NULL, " "); - break; - case 1: - default: - for (x = 0 ; (x < 16) && (x < y) ; x += 1) { - z = target_buffer_get_u8(target, &(target_buf[x])); - command_print_sameline(NULL, "%02x ", (int)(z)); - } - for (; (x < 16) ; x += 1) - command_print_sameline(NULL, " "); - break; - } - /* ascii-ify the bytes */ - for (x = 0 ; x < y ; x++) { - if ((target_buf[x] >= 0x20) && - (target_buf[x] <= 0x7e)) { - /* good */ - } else { - /* smack it */ - target_buf[x] = '.'; - } - } - /* space pad */ - while (x < 16) { - target_buf[x] = ' '; - x++; - } - /* terminate */ - target_buf[16] = 0; - /* print - with a newline */ - command_print_sameline(NULL, "%s\n", target_buf); - /* NEXT... */ - bytes -= 16; - addr += 16; - } - return JIM_OK; -} - -static int jim_target_mem2array(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct target *target = Jim_CmdPrivData(interp); - return target_mem2array(interp, target, argc - 1, argv + 1); -} - -static int jim_target_array2mem(Jim_Interp *interp, - int argc, Jim_Obj *const *argv) -{ - struct target *target = Jim_CmdPrivData(interp); - return target_array2mem(interp, target, argc - 1, argv + 1); -} - -static int jim_target_tap_disabled(Jim_Interp *interp) -{ - Jim_SetResultFormatted(interp, "[TAP is disabled]"); - return JIM_ERR; -} - -static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(interp); - if (!target->tap->enabled) - return jim_target_tap_disabled(interp); - - int e = target->type->examine(target); - if (e != ERROR_OK) - return JIM_ERR; - return JIM_OK; -} - -static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(interp); - - if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) - return JIM_ERR; - - return JIM_OK; -} - -static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(interp); - if (!target->tap->enabled) - return jim_target_tap_disabled(interp); - - int e; - if (!(target_was_examined(target))) - e = ERROR_TARGET_NOT_EXAMINED; - else - e = target->type->poll(target); - if (e != ERROR_OK) - return JIM_ERR; - return JIM_OK; -} - -static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - - if (goi.argc != 2) { - Jim_WrongNumArgs(interp, 0, argv, - "([tT]|[fF]|assert|deassert) BOOL"); - return JIM_ERR; - } - - Jim_Nvp *n; - int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); - return e; - } - /* the halt or not param */ - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) - return e; - - struct target *target = Jim_CmdPrivData(goi.interp); - if (!target->tap->enabled) - return jim_target_tap_disabled(interp); - if (!(target_was_examined(target))) { - LOG_ERROR("Target not examined yet"); - return ERROR_TARGET_NOT_EXAMINED; - } - if (!target->type->assert_reset || !target->type->deassert_reset) { - Jim_SetResultFormatted(interp, - "No target-specific reset for %s", - target_name(target)); - return JIM_ERR; - } - /* determine if we should halt or not. */ - target->reset_halt = !!a; - /* When this happens - all workareas are invalid. */ - target_free_all_working_areas_restore(target, 0); - - /* do the assert */ - if (n->value == NVP_ASSERT) - e = target->type->assert_reset(target); - else - e = target->type->deassert_reset(target); - return (e == ERROR_OK) ? JIM_OK : JIM_ERR; -} - -static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(interp); - if (!target->tap->enabled) - return jim_target_tap_disabled(interp); - int e = target->type->halt(target); - return (e == ERROR_OK) ? JIM_OK : JIM_ERR; -} - -static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - - /* params: statename timeoutmsecs */ - if (goi.argc != 2) { - const char *cmd_name = Jim_GetString(argv[0], NULL); - Jim_SetResultFormatted(goi.interp, - "%s ", cmd_name); - return JIM_ERR; - } - - Jim_Nvp *n; - int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_target_state, 1); - return e; - } - jim_wide a; - e = Jim_GetOpt_Wide(&goi, &a); - if (e != JIM_OK) - return e; - struct target *target = Jim_CmdPrivData(interp); - if (!target->tap->enabled) - return jim_target_tap_disabled(interp); - - e = target_wait_state(target, n->value, a); - if (e != ERROR_OK) { - Jim_Obj *eObj = Jim_NewIntObj(interp, e); - Jim_SetResultFormatted(goi.interp, - "target: %s wait %s fails (%#s) %s", - target_name(target), n->name, - eObj, target_strerror_safe(e)); - Jim_FreeNewObj(interp, eObj); - return JIM_ERR; - } - return JIM_OK; -} -/* List for human, Events defined for this target. - * scripts/programs should use 'name cget -event NAME' - */ -static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); - - struct target *target = Jim_CmdPrivData(interp); - struct target_event_action *teap = target->event_action; - command_print(cmd_ctx, "Event actions for target (%d) %s\n", - target->target_number, - target_name(target)); - command_print(cmd_ctx, "%-25s | Body", "Event"); - command_print(cmd_ctx, "------------------------- | " - "----------------------------------------"); - while (teap) { - Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event); - command_print(cmd_ctx, "%-25s | %s", - opt->name, Jim_GetString(teap->body, NULL)); - teap = teap->next; - } - command_print(cmd_ctx, "***END***"); - return JIM_OK; -} -static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); - return JIM_ERR; - } - struct target *target = Jim_CmdPrivData(interp); - Jim_SetResultString(interp, target_state_name(target), -1); - return JIM_OK; -} -static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc != 1) { - const char *cmd_name = Jim_GetString(argv[0], NULL); - Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); - return JIM_ERR; - } - Jim_Nvp *n; - int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n); - if (e != JIM_OK) { - Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); - return e; - } - struct target *target = Jim_CmdPrivData(interp); - target_handle_event(target, n->value); - return JIM_OK; -} - -static const struct command_registration target_instance_command_handlers[] = { - { - .name = "configure", - .mode = COMMAND_CONFIG, - .jim_handler = jim_target_configure, - .help = "configure a new target for use", - .usage = "[target_attribute ...]", - }, - { - .name = "cget", - .mode = COMMAND_ANY, - .jim_handler = jim_target_configure, - .help = "returns the specified target attribute", - .usage = "target_attribute", - }, - { - .name = "mww", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, - .help = "Write 32-bit word(s) to target memory", - .usage = "address data [count]", - }, - { - .name = "mwh", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, - .help = "Write 16-bit half-word(s) to target memory", - .usage = "address data [count]", - }, - { - .name = "mwb", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mw, - .help = "Write byte(s) to target memory", - .usage = "address data [count]", - }, - { - .name = "mdw", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, - .help = "Display target memory as 32-bit words", - .usage = "address [count]", - }, - { - .name = "mdh", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, - .help = "Display target memory as 16-bit half-words", - .usage = "address [count]", - }, - { - .name = "mdb", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_md, - .help = "Display target memory as 8-bit bytes", - .usage = "address [count]", - }, - { - .name = "array2mem", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_array2mem, - .help = "Writes Tcl array of 8/16/32 bit numbers " - "to target memory", - .usage = "arrayname bitwidth address count", - }, - { - .name = "mem2array", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_mem2array, - .help = "Loads Tcl array of 8/16/32 bit numbers " - "from target memory", - .usage = "arrayname bitwidth address count", - }, - { - .name = "eventlist", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_event_list, - .help = "displays a table of events defined for this target", - }, - { - .name = "curstate", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_current_state, - .help = "displays the current state of this target", - }, - { - .name = "arp_examine", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_examine, - .help = "used internally for reset processing", - }, - { - .name = "arp_halt_gdb", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_halt_gdb, - .help = "used internally for reset processing to halt GDB", - }, - { - .name = "arp_poll", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_poll, - .help = "used internally for reset processing", - }, - { - .name = "arp_reset", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_reset, - .help = "used internally for reset processing", - }, - { - .name = "arp_halt", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_halt, - .help = "used internally for reset processing", - }, - { - .name = "arp_waitstate", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_wait_state, - .help = "used internally for reset processing", - }, - { - .name = "invoke-event", - .mode = COMMAND_EXEC, - .jim_handler = jim_target_invoke_event, - .help = "invoke handler for specified event", - .usage = "event_name", - }, - COMMAND_REGISTRATION_DONE -}; - -static int target_create(Jim_GetOptInfo *goi) -{ - Jim_Obj *new_cmd; - Jim_Cmd *cmd; - const char *cp; - char *cp2; - int e; - int x; - struct target *target; - struct command_context *cmd_ctx; - - cmd_ctx = current_command_context(goi->interp); - assert(cmd_ctx != NULL); - - if (goi->argc < 3) { - Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); - return JIM_ERR; - } - - /* COMMAND */ - Jim_GetOpt_Obj(goi, &new_cmd); - /* does this command exist? */ - cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); - if (cmd) { - cp = Jim_GetString(new_cmd, NULL); - Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); - return JIM_ERR; - } - - /* TYPE */ - e = Jim_GetOpt_String(goi, &cp2, NULL); - if (e != JIM_OK) - return e; - cp = cp2; - struct transport *tr = get_current_transport(); - if (tr->override_target) { - e = tr->override_target(&cp); - if (e != ERROR_OK) { - LOG_ERROR("The selected transport doesn't support this target"); - return JIM_ERR; - } - LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD"); - } - /* now does target type exist */ - for (x = 0 ; target_types[x] ; x++) { - if (0 == strcmp(cp, target_types[x]->name)) { - /* found */ - break; - } - - /* check for deprecated name */ - if (target_types[x]->deprecated_name) { - if (0 == strcmp(cp, target_types[x]->deprecated_name)) { - /* found */ - LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name); - break; - } - } - } - if (target_types[x] == NULL) { - Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); - for (x = 0 ; target_types[x] ; x++) { - if (target_types[x + 1]) { - Jim_AppendStrings(goi->interp, - Jim_GetResult(goi->interp), - target_types[x]->name, - ", ", NULL); - } else { - Jim_AppendStrings(goi->interp, - Jim_GetResult(goi->interp), - " or ", - target_types[x]->name, NULL); - } - } - return JIM_ERR; - } - - /* Create it */ - target = calloc(1, sizeof(struct target)); - /* set target number */ - target->target_number = new_target_number(); - cmd_ctx->current_target = target->target_number; - - /* allocate memory for each unique target type */ - target->type = calloc(1, sizeof(struct target_type)); - - memcpy(target->type, target_types[x], sizeof(struct target_type)); - - /* will be set by "-endian" */ - target->endianness = TARGET_ENDIAN_UNKNOWN; - - /* default to first core, override with -coreid */ - target->coreid = 0; - - target->working_area = 0x0; - target->working_area_size = 0x0; - target->working_areas = NULL; - target->backup_working_area = 0; - - target->state = TARGET_UNKNOWN; - target->debug_reason = DBG_REASON_UNDEFINED; - target->reg_cache = NULL; - target->breakpoints = NULL; - target->watchpoints = NULL; - target->next = NULL; - target->arch_info = NULL; - - target->display = 1; - - target->halt_issued = false; - - /* initialize trace information */ - target->trace_info = malloc(sizeof(struct trace)); - target->trace_info->num_trace_points = 0; - target->trace_info->trace_points_size = 0; - target->trace_info->trace_points = NULL; - target->trace_info->trace_history_size = 0; - target->trace_info->trace_history = NULL; - target->trace_info->trace_history_pos = 0; - target->trace_info->trace_history_overflowed = 0; - - target->dbgmsg = NULL; - target->dbg_msg_enabled = 0; - - target->endianness = TARGET_ENDIAN_UNKNOWN; - - target->rtos = NULL; - target->rtos_auto_detect = false; - - /* Do the rest as "configure" options */ - goi->isconfigure = 1; - e = target_configure(goi, target); - - if (target->tap == NULL) { - Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1); - e = JIM_ERR; - } - - if (e != JIM_OK) { - free(target->type); - free(target); - return e; - } - - if (target->endianness == TARGET_ENDIAN_UNKNOWN) { - /* default endian to little if not specified */ - target->endianness = TARGET_LITTLE_ENDIAN; - } - - cp = Jim_GetString(new_cmd, NULL); - target->cmd_name = strdup(cp); - - /* create the target specific commands */ - if (target->type->commands) { - e = register_commands(cmd_ctx, NULL, target->type->commands); - if (ERROR_OK != e) - LOG_ERROR("unable to register '%s' commands", cp); - } - if (target->type->target_create) - (*(target->type->target_create))(target, goi->interp); - - /* append to end of list */ - { - struct target **tpp; - tpp = &(all_targets); - while (*tpp) - tpp = &((*tpp)->next); - *tpp = target; - } - - /* now - create the new target name command */ - const struct command_registration target_subcommands[] = { - { - .chain = target_instance_command_handlers, - }, - { - .chain = target->type->commands, - }, - COMMAND_REGISTRATION_DONE - }; - const struct command_registration target_commands[] = { - { - .name = cp, - .mode = COMMAND_ANY, - .help = "target command group", - .usage = "", - .chain = target_subcommands, - }, - COMMAND_REGISTRATION_DONE - }; - e = register_commands(cmd_ctx, NULL, target_commands); - if (ERROR_OK != e) - return JIM_ERR; - - struct command *c = command_find_in_context(cmd_ctx, cp); - assert(c); - command_set_handler_data(c, target); - - return (ERROR_OK == e) ? JIM_OK : JIM_ERR; -} - -static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); - return JIM_ERR; - } - struct command_context *cmd_ctx = current_command_context(interp); - assert(cmd_ctx != NULL); - - Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1); - return JIM_OK; -} - -static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); - return JIM_ERR; - } - Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); - for (unsigned x = 0; NULL != target_types[x]; x++) { - Jim_ListAppendElement(interp, Jim_GetResult(interp), - Jim_NewStringObj(interp, target_types[x]->name, -1)); - } - return JIM_OK; -} - -static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); - return JIM_ERR; - } - Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); - struct target *target = all_targets; - while (target) { - Jim_ListAppendElement(interp, Jim_GetResult(interp), - Jim_NewStringObj(interp, target_name(target), -1)); - target = target->next; - } - return JIM_OK; -} - -static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - int i; - const char *targetname; - int retval, len; - struct target *target = (struct target *) NULL; - struct target_list *head, *curr, *new; - curr = (struct target_list *) NULL; - head = (struct target_list *) NULL; - - retval = 0; - LOG_DEBUG("%d", argc); - /* argv[1] = target to associate in smp - * argv[2] = target to assoicate in smp - * argv[3] ... - */ - - for (i = 1; i < argc; i++) { - - targetname = Jim_GetString(argv[i], &len); - target = get_target(targetname); - LOG_DEBUG("%s ", targetname); - if (target) { - new = malloc(sizeof(struct target_list)); - new->target = target; - new->next = (struct target_list *)NULL; - if (head == (struct target_list *)NULL) { - head = new; - curr = head; - } else { - curr->next = new; - curr = new; - } - } - } - /* now parse the list of cpu and put the target in smp mode*/ - curr = head; - - while (curr != (struct target_list *)NULL) { - target = curr->target; - target->smp = 1; - target->head = head; - curr = curr->next; - } - - if (target && target->rtos) - retval = rtos_smp_init(head->target); - - return retval; -} - - -static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) -{ - Jim_GetOptInfo goi; - Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); - if (goi.argc < 3) { - Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - " [ ...]"); - return JIM_ERR; - } - return target_create(&goi); -} - -static const struct command_registration target_subcommand_handlers[] = { - { - .name = "init", - .mode = COMMAND_CONFIG, - .handler = handle_target_init_command, - .help = "initialize targets", - }, - { - .name = "create", - /* REVISIT this should be COMMAND_CONFIG ... */ - .mode = COMMAND_ANY, - .jim_handler = jim_target_create, - .usage = "name type '-chain-position' name [options ...]", - .help = "Creates and selects a new target", - }, - { - .name = "current", - .mode = COMMAND_ANY, - .jim_handler = jim_target_current, - .help = "Returns the currently selected target", - }, - { - .name = "types", - .mode = COMMAND_ANY, - .jim_handler = jim_target_types, - .help = "Returns the available target types as " - "a list of strings", - }, - { - .name = "names", - .mode = COMMAND_ANY, - .jim_handler = jim_target_names, - .help = "Returns the names of all targets as a list of strings", - }, - { - .name = "smp", - .mode = COMMAND_ANY, - .jim_handler = jim_target_smp, - .usage = "targetname1 targetname2 ...", - .help = "gather several target in a smp list" - }, - - COMMAND_REGISTRATION_DONE -}; - -struct FastLoad { - uint32_t address; - uint8_t *data; - int length; - -}; - -static int fastload_num; -static struct FastLoad *fastload; - -static void free_fastload(void) -{ - if (fastload != NULL) { - int i; - for (i = 0; i < fastload_num; i++) { - if (fastload[i].data) - free(fastload[i].data); - } - free(fastload); - fastload = NULL; - } -} - -COMMAND_HANDLER(handle_fast_load_image_command) -{ - uint8_t *buffer; - size_t buf_cnt; - uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; - int i; - - struct image image; - - int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, - &image, &min_address, &max_address); - if (ERROR_OK != retval) - return retval; - - struct duration bench; - duration_start(&bench); - - retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL); - if (retval != ERROR_OK) - return retval; - - image_size = 0x0; - retval = ERROR_OK; - fastload_num = image.num_sections; - fastload = malloc(sizeof(struct FastLoad)*image.num_sections); - if (fastload == NULL) { - command_print(CMD_CTX, "out of memory"); - image_close(&image); - return ERROR_FAIL; - } - memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); - for (i = 0; i < image.num_sections; i++) { - buffer = malloc(image.sections[i].size); - if (buffer == NULL) { - command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", - (int)(image.sections[i].size)); - retval = ERROR_FAIL; - break; - } - - retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); - if (retval != ERROR_OK) { - free(buffer); - break; - } - - uint32_t offset = 0; - uint32_t length = buf_cnt; - - /* DANGER!!! beware of unsigned comparision here!!! */ - - if ((image.sections[i].base_address + buf_cnt >= min_address) && - (image.sections[i].base_address < max_address)) { - if (image.sections[i].base_address < min_address) { - /* clip addresses below */ - offset += min_address-image.sections[i].base_address; - length -= offset; - } - - if (image.sections[i].base_address + buf_cnt > max_address) - length -= (image.sections[i].base_address + buf_cnt)-max_address; - - fastload[i].address = image.sections[i].base_address + offset; - fastload[i].data = malloc(length); - if (fastload[i].data == NULL) { - free(buffer); - command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)", - length); - retval = ERROR_FAIL; - break; - } - memcpy(fastload[i].data, buffer + offset, length); - fastload[i].length = length; - - image_size += length; - command_print(CMD_CTX, "%u bytes written at address 0x%8.8x", - (unsigned int)length, - ((unsigned int)(image.sections[i].base_address + offset))); - } - - free(buffer); - } - - if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " - "in %fs (%0.3f KiB/s)", image_size, - duration_elapsed(&bench), duration_kbps(&bench, image_size)); - - command_print(CMD_CTX, - "WARNING: image has not been loaded to target!" - "You can issue a 'fast_load' to finish loading."); - } - - image_close(&image); - - if (retval != ERROR_OK) - free_fastload(); - - return retval; -} - -COMMAND_HANDLER(handle_fast_load_command) -{ - if (CMD_ARGC > 0) - return ERROR_COMMAND_SYNTAX_ERROR; - if (fastload == NULL) { - LOG_ERROR("No image in memory"); - return ERROR_FAIL; - } - int i; - int ms = timeval_ms(); - int size = 0; - int retval = ERROR_OK; - for (i = 0; i < fastload_num; i++) { - struct target *target = get_current_target(CMD_CTX); - command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x", - (unsigned int)(fastload[i].address), - (unsigned int)(fastload[i].length)); - retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data); - if (retval != ERROR_OK) - break; - size += fastload[i].length; - } - if (retval == ERROR_OK) { - int after = timeval_ms(); - command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); - } - return retval; -} - -static const struct command_registration target_command_handlers[] = { - { - .name = "targets", - .handler = handle_targets_command, - .mode = COMMAND_ANY, - .help = "change current default target (one parameter) " - "or prints table of all targets (no parameters)", - .usage = "[target]", - }, - { - .name = "target", - .mode = COMMAND_CONFIG, - .help = "configure target", - - .chain = target_subcommand_handlers, - }, - COMMAND_REGISTRATION_DONE -}; - -int target_register_commands(struct command_context *cmd_ctx) -{ - return register_commands(cmd_ctx, NULL, target_command_handlers); -} - -static bool target_reset_nag = true; - -bool get_target_reset_nag(void) -{ - return target_reset_nag; -} - -COMMAND_HANDLER(handle_target_reset_nag) -{ - return CALL_COMMAND_HANDLER(handle_command_parse_bool, - &target_reset_nag, "Nag after each reset about options to improve " - "performance"); -} - -COMMAND_HANDLER(handle_ps_command) -{ - struct target *target = get_current_target(CMD_CTX); - char *display; - if (target->state != TARGET_HALTED) { - LOG_INFO("target not halted !!"); - return ERROR_OK; - } - - if ((target->rtos) && (target->rtos->type) - && (target->rtos->type->ps_command)) { - display = target->rtos->type->ps_command(target); - command_print(CMD_CTX, "%s", display); - free(display); - return ERROR_OK; - } else { - LOG_INFO("failed"); - return ERROR_TARGET_FAILURE; - } -} - -static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size) -{ - if (text != NULL) - command_print_sameline(cmd_ctx, "%s", text); - for (int i = 0; i < size; i++) - command_print_sameline(cmd_ctx, " %02x", buf[i]); - command_print(cmd_ctx, " "); -} - -COMMAND_HANDLER(handle_test_mem_access_command) -{ - struct target *target = get_current_target(CMD_CTX); - uint32_t test_size; - int retval = ERROR_OK; - - if (target->state != TARGET_HALTED) { - LOG_INFO("target not halted !!"); - return ERROR_FAIL; - } - - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size); - - /* Test reads */ - size_t num_bytes = test_size + 4; - - struct working_area *wa = NULL; - retval = target_alloc_working_area(target, num_bytes, &wa); - if (retval != ERROR_OK) { - LOG_ERROR("Not enough working area"); - return ERROR_FAIL; - } - - uint8_t *test_pattern = malloc(num_bytes); - - for (size_t i = 0; i < num_bytes; i++) - test_pattern[i] = rand(); - - retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); - if (retval != ERROR_OK) { - LOG_ERROR("Test pattern write failed"); - goto out; - } - - for (int host_offset = 0; host_offset <= 1; host_offset++) { - for (int size = 1; size <= 4; size *= 2) { - for (int offset = 0; offset < 4; offset++) { - uint32_t count = test_size / size; - size_t host_bufsiz = (count + 2) * size + host_offset; - uint8_t *read_ref = malloc(host_bufsiz); - uint8_t *read_buf = malloc(host_bufsiz); - - for (size_t i = 0; i < host_bufsiz; i++) { - read_ref[i] = rand(); - read_buf[i] = read_ref[i]; - } - command_print_sameline(CMD_CTX, - "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count, - size, offset, host_offset ? "un" : ""); - - struct duration bench; - duration_start(&bench); - - retval = target_read_memory(target, wa->address + offset, size, count, - read_buf + size + host_offset); - - duration_measure(&bench); - - if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { - command_print(CMD_CTX, "Unsupported alignment"); - goto next; - } else if (retval != ERROR_OK) { - command_print(CMD_CTX, "Memory read failed"); - goto next; - } - - /* replay on host */ - memcpy(read_ref + size + host_offset, test_pattern + offset, count * size); - - /* check result */ - int result = memcmp(read_ref, read_buf, host_bufsiz); - if (result == 0) { - command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", - duration_elapsed(&bench), - duration_kbps(&bench, count * size)); - } else { - command_print(CMD_CTX, "Compare failed"); - binprint(CMD_CTX, "ref:", read_ref, host_bufsiz); - binprint(CMD_CTX, "buf:", read_buf, host_bufsiz); - } -next: - free(read_ref); - free(read_buf); - } - } - } - -out: - free(test_pattern); - - if (wa != NULL) - target_free_working_area(target, wa); - - /* Test writes */ - num_bytes = test_size + 4 + 4 + 4; - - retval = target_alloc_working_area(target, num_bytes, &wa); - if (retval != ERROR_OK) { - LOG_ERROR("Not enough working area"); - return ERROR_FAIL; - } - - test_pattern = malloc(num_bytes); - - for (size_t i = 0; i < num_bytes; i++) - test_pattern[i] = rand(); - - for (int host_offset = 0; host_offset <= 1; host_offset++) { - for (int size = 1; size <= 4; size *= 2) { - for (int offset = 0; offset < 4; offset++) { - uint32_t count = test_size / size; - size_t host_bufsiz = count * size + host_offset; - uint8_t *read_ref = malloc(num_bytes); - uint8_t *read_buf = malloc(num_bytes); - uint8_t *write_buf = malloc(host_bufsiz); - - for (size_t i = 0; i < host_bufsiz; i++) - write_buf[i] = rand(); - command_print_sameline(CMD_CTX, - "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count, - size, offset, host_offset ? "un" : ""); - - retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); - if (retval != ERROR_OK) { - command_print(CMD_CTX, "Test pattern write failed"); - goto nextw; - } - - /* replay on host */ - memcpy(read_ref, test_pattern, num_bytes); - memcpy(read_ref + size + offset, write_buf + host_offset, count * size); - - struct duration bench; - duration_start(&bench); - - retval = target_write_memory(target, wa->address + size + offset, size, count, - write_buf + host_offset); - - duration_measure(&bench); - - if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { - command_print(CMD_CTX, "Unsupported alignment"); - goto nextw; - } else if (retval != ERROR_OK) { - command_print(CMD_CTX, "Memory write failed"); - goto nextw; - } - - /* read back */ - retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf); - if (retval != ERROR_OK) { - command_print(CMD_CTX, "Test pattern write failed"); - goto nextw; - } - - /* check result */ - int result = memcmp(read_ref, read_buf, num_bytes); - if (result == 0) { - command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", - duration_elapsed(&bench), - duration_kbps(&bench, count * size)); - } else { - command_print(CMD_CTX, "Compare failed"); - binprint(CMD_CTX, "ref:", read_ref, num_bytes); - binprint(CMD_CTX, "buf:", read_buf, num_bytes); - } -nextw: - free(read_ref); - free(read_buf); - } - } - } - - free(test_pattern); - - if (wa != NULL) - target_free_working_area(target, wa); - return retval; -} - -static const struct command_registration target_exec_command_handlers[] = { - { - .name = "fast_load_image", - .handler = handle_fast_load_image_command, - .mode = COMMAND_ANY, - .help = "Load image into server memory for later use by " - "fast_load; primarily for profiling", - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address [max_length]]", - }, - { - .name = "fast_load", - .handler = handle_fast_load_command, - .mode = COMMAND_EXEC, - .help = "loads active fast load image to current target " - "- mainly for profiling purposes", - .usage = "", - }, - { - .name = "profile", - .handler = handle_profile_command, - .mode = COMMAND_EXEC, - .usage = "seconds filename [start end]", - .help = "profiling samples the CPU PC", - }, - /** @todo don't register virt2phys() unless target supports it */ - { - .name = "virt2phys", - .handler = handle_virt2phys_command, - .mode = COMMAND_ANY, - .help = "translate a virtual address into a physical address", - .usage = "virtual_address", - }, - { - .name = "reg", - .handler = handle_reg_command, - .mode = COMMAND_EXEC, - .help = "display (reread from target with \"force\") or set a register; " - "with no arguments, displays all registers and their values", - .usage = "[(register_number|register_name) [(value|'force')]]", - }, - { - .name = "poll", - .handler = handle_poll_command, - .mode = COMMAND_EXEC, - .help = "poll target state; or reconfigure background polling", - .usage = "['on'|'off']", - }, - { - .name = "wait_halt", - .handler = handle_wait_halt_command, - .mode = COMMAND_EXEC, - .help = "wait up to the specified number of milliseconds " - "(default 5000) for a previously requested halt", - .usage = "[milliseconds]", - }, - { - .name = "halt", - .handler = handle_halt_command, - .mode = COMMAND_EXEC, - .help = "request target to halt, then wait up to the specified" - "number of milliseconds (default 5000) for it to complete", - .usage = "[milliseconds]", - }, - { - .name = "resume", - .handler = handle_resume_command, - .mode = COMMAND_EXEC, - .help = "resume target execution from current PC or address", - .usage = "[address]", - }, - { - .name = "reset", - .handler = handle_reset_command, - .mode = COMMAND_EXEC, - .usage = "[run|halt|init]", - .help = "Reset all targets into the specified mode." - "Default reset mode is run, if not given.", - }, - { - .name = "soft_reset_halt", - .handler = handle_soft_reset_halt_command, - .mode = COMMAND_EXEC, - .usage = "", - .help = "halt the target and do a soft reset", - }, - { - .name = "step", - .handler = handle_step_command, - .mode = COMMAND_EXEC, - .help = "step one instruction from current PC or address", - .usage = "[address]", - }, - { - .name = "mdw", - .handler = handle_md_command, - .mode = COMMAND_EXEC, - .help = "display memory words", - .usage = "['phys'] address [count]", - }, - { - .name = "mdh", - .handler = handle_md_command, - .mode = COMMAND_EXEC, - .help = "display memory half-words", - .usage = "['phys'] address [count]", - }, - { - .name = "mdb", - .handler = handle_md_command, - .mode = COMMAND_EXEC, - .help = "display memory bytes", - .usage = "['phys'] address [count]", - }, - { - .name = "mww", - .handler = handle_mw_command, - .mode = COMMAND_EXEC, - .help = "write memory word", - .usage = "['phys'] address value [count]", - }, - { - .name = "mwh", - .handler = handle_mw_command, - .mode = COMMAND_EXEC, - .help = "write memory half-word", - .usage = "['phys'] address value [count]", - }, - { - .name = "mwb", - .handler = handle_mw_command, - .mode = COMMAND_EXEC, - .help = "write memory byte", - .usage = "['phys'] address value [count]", - }, - { - .name = "bp", - .handler = handle_bp_command, - .mode = COMMAND_EXEC, - .help = "list or set hardware or software breakpoint", - .usage = "
[] ['hw'|'hw_ctx']", - }, - { - .name = "rbp", - .handler = handle_rbp_command, - .mode = COMMAND_EXEC, - .help = "remove breakpoint", - .usage = "address", - }, - { - .name = "wp", - .handler = handle_wp_command, - .mode = COMMAND_EXEC, - .help = "list (no params) or create watchpoints", - .usage = "[address length [('r'|'w'|'a') value [mask]]]", - }, - { - .name = "rwp", - .handler = handle_rwp_command, - .mode = COMMAND_EXEC, - .help = "remove watchpoint", - .usage = "address", - }, - { - .name = "load_image", - .handler = handle_load_image_command, - .mode = COMMAND_EXEC, - .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " - "[min_address] [max_length]", - }, - { - .name = "dump_image", - .handler = handle_dump_image_command, - .mode = COMMAND_EXEC, - .usage = "filename address size", - }, - { - .name = "verify_image", - .handler = handle_verify_image_command, - .mode = COMMAND_EXEC, - .usage = "filename [offset [type]]", - }, - { - .name = "test_image", - .handler = handle_test_image_command, - .mode = COMMAND_EXEC, - .usage = "filename [offset [type]]", - }, - { - .name = "mem2array", - .mode = COMMAND_EXEC, - .jim_handler = jim_mem2array, - .help = "read 8/16/32 bit memory and return as a TCL array " - "for script processing", - .usage = "arrayname bitwidth address count", - }, - { - .name = "array2mem", - .mode = COMMAND_EXEC, - .jim_handler = jim_array2mem, - .help = "convert a TCL array to memory locations " - "and write the 8/16/32 bit values", - .usage = "arrayname bitwidth address count", - }, - { - .name = "reset_nag", - .handler = handle_target_reset_nag, - .mode = COMMAND_ANY, - .help = "Nag after each reset about options that could have been " - "enabled to improve performance. ", - .usage = "['enable'|'disable']", - }, - { - .name = "ps", - .handler = handle_ps_command, - .mode = COMMAND_EXEC, - .help = "list all tasks ", - .usage = " ", - }, - { - .name = "test_mem_access", - .handler = handle_test_mem_access_command, - .mode = COMMAND_EXEC, - .help = "Test the target's memory access functions", - .usage = "size", - }, - - COMMAND_REGISTRATION_DONE -}; -static int target_register_user_commands(struct command_context *cmd_ctx) -{ - int retval = ERROR_OK; - retval = target_request_register_commands(cmd_ctx); - if (retval != ERROR_OK) - return retval; - - retval = trace_register_commands(cmd_ctx); - if (retval != ERROR_OK) - return retval; - - - return register_commands(cmd_ctx, NULL, target_exec_command_handlers); -} + Jim_GetOptInfo goi; + + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); +#if BUILD_RISCV == 1 + int need_args = 1 + goi.isconfigure; + if (goi.argc < need_args) { + Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + goi.isconfigure + ? "missing: -option VALUE ..." + : "missing: -option ..."); + return JIM_ERR; + } +#else + if (goi.argc < 1) { + Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + "missing: -option ..."); + return JIM_ERR; + } +#endif + struct target *target = Jim_CmdPrivData(goi.interp); + return target_configure(&goi, target); + } + + static int jim_target_mw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + const char *cmd_name = Jim_GetString(argv[0], NULL); + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + if (goi.argc < 2 || goi.argc > 4) { + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); + return JIM_ERR; + } + + target_write_fn fn; + fn = target_write_memory; + + int e; + if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { + /* consume it */ + struct Jim_Obj *obj; + e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + + fn = target_write_phys_memory; + } + + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) + return e; + + jim_wide b; + e = Jim_GetOpt_Wide(&goi, &b); + if (e != JIM_OK) + return e; + + jim_wide c = 1; + if (goi.argc == 1) { + e = Jim_GetOpt_Wide(&goi, &c); + if (e != JIM_OK) + return e; + } + + /* all args must be consumed */ + if (goi.argc != 0) + return JIM_ERR; + + struct target *target = Jim_CmdPrivData(goi.interp); + unsigned data_size; + if (strcasecmp(cmd_name, "mww") == 0) + data_size = 4; + else if (strcasecmp(cmd_name, "mwh") == 0) + data_size = 2; + else if (strcasecmp(cmd_name, "mwb") == 0) + data_size = 1; + else { + LOG_ERROR("command '%s' unknown: ", cmd_name); + return JIM_ERR; + } + + return (target_fill_mem(target, a, fn, data_size, b, c) == ERROR_OK) ? JIM_OK : JIM_ERR; + } + + /** + * @brief Reads an array of words/halfwords/bytes from target memory starting at specified address. + * + * Usage: mdw [phys]
[] - for 32 bit reads + * mdh [phys]
[] - for 16 bit reads + * mdb [phys]
[] - for 8 bit reads + * + * Count defaults to 1. + * + * Calls target_read_memory or target_read_phys_memory depending on + * the presence of the "phys" argument + * Reads the target memory in blocks of max. 32 bytes, and returns an array of ints formatted + * to int representation in base16. + * Also outputs read data in a human readable form using command_print + * + * @param phys if present target_read_phys_memory will be used instead of target_read_memory + * @param address address where to start the read. May be specified in decimal or hex using the standard "0x" prefix + * @param count optional count parameter to read an array of values. If not specified, defaults to 1. + * @returns: JIM_ERR on error or JIM_OK on success and sets the result string to an array of ascii formatted numbers + * on success, with [] number of elements. + * + * In case of little endian target: + * Example1: "mdw 0x00000000" returns "10123456" + * Exmaple2: "mdh 0x00000000 1" returns "3456" + * Example3: "mdb 0x00000000" returns "56" + * Example4: "mdh 0x00000000 2" returns "3456 1012" + * Example5: "mdb 0x00000000 3" returns "56 34 12" + **/ + static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + const char *cmd_name = Jim_GetString(argv[0], NULL); + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + if ((goi.argc < 1) || (goi.argc > 3)) { + Jim_SetResultFormatted(goi.interp, + "usage: %s [phys]
[]", cmd_name); + return JIM_ERR; + } + + int (*fn)(struct target *target, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); + fn = target_read_memory; + + int e; + if (strcmp(Jim_GetString(argv[1], NULL), "phys") == 0) { + /* consume it */ + struct Jim_Obj *obj; + e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + + fn = target_read_phys_memory; + } + + /* Read address parameter */ + jim_wide addr; + e = Jim_GetOpt_Wide(&goi, &addr); + if (e != JIM_OK) + return JIM_ERR; + + /* If next parameter exists, read it out as the count parameter, if not, set it to 1 (default) */ + jim_wide count; + if (goi.argc == 1) { + e = Jim_GetOpt_Wide(&goi, &count); + if (e != JIM_OK) + return JIM_ERR; + } else + count = 1; + + /* all args must be consumed */ + if (goi.argc != 0) + return JIM_ERR; + + jim_wide dwidth = 1; /* shut up gcc */ + if (strcasecmp(cmd_name, "mdw") == 0) + dwidth = 4; + else if (strcasecmp(cmd_name, "mdh") == 0) + dwidth = 2; + else if (strcasecmp(cmd_name, "mdb") == 0) + dwidth = 1; + else { + LOG_ERROR("command '%s' unknown: ", cmd_name); + return JIM_ERR; + } + + /* convert count to "bytes" */ + int bytes = count * dwidth; + + struct target *target = Jim_CmdPrivData(goi.interp); + uint8_t target_buf[32]; + jim_wide x, y, z; + while (bytes > 0) { + y = (bytes < 16) ? bytes : 16; /* y = min(bytes, 16); */ + + /* Try to read out next block */ + e = fn(target, addr, dwidth, y / dwidth, target_buf); + + if (e != ERROR_OK) { + Jim_SetResultFormatted(interp, "error reading target @ 0x%08lx", (long)addr); + return JIM_ERR; + } + + command_print_sameline(NULL, "0x%08x ", (int)(addr)); + switch (dwidth) { + case 4: + for (x = 0; x < 16 && x < y; x += 4) { + z = target_buffer_get_u32(target, &(target_buf[x])); + command_print_sameline(NULL, "%08x ", (int)(z)); + } + for (; (x < 16) ; x += 4) + command_print_sameline(NULL, " "); + break; + case 2: + for (x = 0; x < 16 && x < y; x += 2) { + z = target_buffer_get_u16(target, &(target_buf[x])); + command_print_sameline(NULL, "%04x ", (int)(z)); + } + for (; (x < 16) ; x += 2) + command_print_sameline(NULL, " "); + break; + case 1: + default: + for (x = 0 ; (x < 16) && (x < y) ; x += 1) { + z = target_buffer_get_u8(target, &(target_buf[x])); + command_print_sameline(NULL, "%02x ", (int)(z)); + } + for (; (x < 16) ; x += 1) + command_print_sameline(NULL, " "); + break; + } + /* ascii-ify the bytes */ + for (x = 0 ; x < y ; x++) { + if ((target_buf[x] >= 0x20) && + (target_buf[x] <= 0x7e)) { + /* good */ + } else { + /* smack it */ + target_buf[x] = '.'; + } + } + /* space pad */ + while (x < 16) { + target_buf[x] = ' '; + x++; + } + /* terminate */ + target_buf[16] = 0; + /* print - with a newline */ + command_print_sameline(NULL, "%s\n", target_buf); + /* NEXT... */ + bytes -= 16; + addr += 16; + } + return JIM_OK; + } + + static int jim_target_mem2array(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) + { + struct target *target = Jim_CmdPrivData(interp); + return target_mem2array(interp, target, argc - 1, argv + 1); + } + + static int jim_target_array2mem(Jim_Interp *interp, + int argc, Jim_Obj *const *argv) + { + struct target *target = Jim_CmdPrivData(interp); + return target_array2mem(interp, target, argc - 1, argv + 1); + } + + static int jim_target_tap_disabled(Jim_Interp *interp) + { + Jim_SetResultFormatted(interp, "[TAP is disabled]"); + return JIM_ERR; + } + + static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + bool allow_defer = false; + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc > 1) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "usage: %s ['allow-defer']", cmd_name); + return JIM_ERR; + } + if (goi.argc > 0 && + strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) { + /* consume it */ + struct Jim_Obj *obj; + int e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + allow_defer = true; + } + + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + if (allow_defer && target->defer_examine) { + LOG_INFO("Deferring arp_examine of %s", target_name(target)); + LOG_INFO("Use arp_examine command to examine it manually!"); + return JIM_OK; + } + + int e = target->type->examine(target); + if (e != ERROR_OK) + return JIM_ERR; + return JIM_OK; + } + + static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) + { + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target_was_examined(target)); + return JIM_OK; + } + + static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) + { + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target->defer_examine); + return JIM_OK; + } + + static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + + if (target_call_event_callbacks(target, TARGET_EVENT_GDB_HALT) != ERROR_OK) + return JIM_ERR; + + return JIM_OK; + } + + static int jim_target_poll(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + int e; + if (!(target_was_examined(target))) + e = ERROR_TARGET_NOT_EXAMINED; + else + e = target->type->poll(target); + if (e != ERROR_OK) + return JIM_ERR; + return JIM_OK; + } + + static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + if (goi.argc != 2) { + Jim_WrongNumArgs(interp, 0, argv, + "([tT]|[fF]|assert|deassert) BOOL"); + return JIM_ERR; + } + + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_assert, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(&goi, nvp_assert, 1); + return e; + } + /* the halt or not param */ + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) + return e; + + struct target *target = Jim_CmdPrivData(goi.interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + if (!target->type->assert_reset || !target->type->deassert_reset) { + Jim_SetResultFormatted(interp, + "No target-specific reset for %s", + target_name(target)); + return JIM_ERR; + } + + if (target->defer_examine) + target_reset_examined(target); + + /* determine if we should halt or not. */ + target->reset_halt = !!a; + /* When this happens - all workareas are invalid. */ + target_free_all_working_areas_restore(target, 0); + + /* do the assert */ + if (n->value == NVP_ASSERT) + e = target->type->assert_reset(target); + else + e = target->type->deassert_reset(target); + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; + } + + static int jim_target_halt(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + int e = target->type->halt(target); + return (e == ERROR_OK) ? JIM_OK : JIM_ERR; + } + + static int jim_target_wait_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + + /* params: statename timeoutmsecs */ + if (goi.argc != 2) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "%s ", cmd_name); + return JIM_ERR; + } + + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_target_state, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(&goi, nvp_target_state, 1); + return e; + } + jim_wide a; + e = Jim_GetOpt_Wide(&goi, &a); + if (e != JIM_OK) + return e; + struct target *target = Jim_CmdPrivData(interp); + if (!target->tap->enabled) + return jim_target_tap_disabled(interp); + + e = target_wait_state(target, n->value, a); + if (e != ERROR_OK) { + Jim_Obj *eObj = Jim_NewIntObj(interp, e); + Jim_SetResultFormatted(goi.interp, + "target: %s wait %s fails (%#s) %s", + target_name(target), n->name, + eObj, target_strerror_safe(e)); + Jim_FreeNewObj(interp, eObj); + return JIM_ERR; + } + return JIM_OK; + } + /* List for human, Events defined for this target. + * scripts/programs should use 'name cget -event NAME' + */ + static int jim_target_event_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + + struct target *target = Jim_CmdPrivData(interp); + struct target_event_action *teap = target->event_action; + command_print(cmd_ctx, "Event actions for target (%d) %s\n", + target->target_number, + target_name(target)); + command_print(cmd_ctx, "%-25s | Body", "Event"); + command_print(cmd_ctx, "------------------------- | " + "----------------------------------------"); + while (teap) { + Jim_Nvp *opt = Jim_Nvp_value2name_simple(nvp_target_event, teap->event); + command_print(cmd_ctx, "%-25s | %s", + opt->name, Jim_GetString(teap->body, NULL)); + teap = teap->next; + } + command_print(cmd_ctx, "***END***"); + return JIM_OK; + } + static int jim_target_current_state(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + return JIM_ERR; + } + struct target *target = Jim_CmdPrivData(interp); + Jim_SetResultString(interp, target_state_name(target), -1); + return JIM_OK; + } + static int jim_target_invoke_event(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc != 1) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, "%s ", cmd_name); + return JIM_ERR; + } + Jim_Nvp *n; + int e = Jim_GetOpt_Nvp(&goi, nvp_target_event, &n); + if (e != JIM_OK) { + Jim_GetOpt_NvpUnknown(&goi, nvp_target_event, 1); + return e; + } + struct target *target = Jim_CmdPrivData(interp); + target_handle_event(target, n->value); + return JIM_OK; + } + + static const struct command_registration target_instance_command_handlers[] = { + { + .name = "configure", + .mode = COMMAND_CONFIG, + .jim_handler = jim_target_configure, + .help = "configure a new target for use", + .usage = "[target_attribute ...]", + }, + { + .name = "cget", + .mode = COMMAND_ANY, + .jim_handler = jim_target_configure, + .help = "returns the specified target attribute", + .usage = "target_attribute", + }, + { + .name = "mww", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write 32-bit word(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mwh", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write 16-bit half-word(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mwb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mw, + .help = "Write byte(s) to target memory", + .usage = "address data [count]", + }, + { + .name = "mdw", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 32-bit words", + .usage = "address [count]", + }, + { + .name = "mdh", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 16-bit half-words", + .usage = "address [count]", + }, + { + .name = "mdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_md, + .help = "Display target memory as 8-bit bytes", + .usage = "address [count]", + }, + { + .name = "array2mem", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_array2mem, + .help = "Writes Tcl array of 8/16/32 bit numbers " + "to target memory", + .usage = "arrayname bitwidth address count", + }, + { + .name = "mem2array", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_mem2array, + .help = "Loads Tcl array of 8/16/32 bit numbers " + "from target memory", + .usage = "arrayname bitwidth address count", + }, + { + .name = "eventlist", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_event_list, + .help = "displays a table of events defined for this target", + }, + { + .name = "curstate", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_current_state, + .help = "displays the current state of this target", + }, + { + .name = "arp_examine", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine, + .help = "used internally for reset processing", + .usage = "arp_examine ['allow-defer']", + }, + { + .name = "was_examined", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_was_examined, + .help = "used internally for reset processing", + .usage = "was_examined", + }, + { + .name = "examine_deferred", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine_deferred, + .help = "used internally for reset processing", + .usage = "examine_deferred", + }, + { + .name = "arp_halt_gdb", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt_gdb, + .help = "used internally for reset processing to halt GDB", + }, + { + .name = "arp_poll", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_poll, + .help = "used internally for reset processing", + }, + { + .name = "arp_reset", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_reset, + .help = "used internally for reset processing", + }, + { + .name = "arp_halt", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_halt, + .help = "used internally for reset processing", + }, + { + .name = "arp_waitstate", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_wait_state, + .help = "used internally for reset processing", + }, + { + .name = "invoke-event", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_invoke_event, + .help = "invoke handler for specified event", + .usage = "event_name", + }, + COMMAND_REGISTRATION_DONE + }; + + static int target_create(Jim_GetOptInfo *goi) + { + Jim_Obj *new_cmd; + Jim_Cmd *cmd; + const char *cp; + int e; + int x; + struct target *target; + struct command_context *cmd_ctx; + + cmd_ctx = current_command_context(goi->interp); + assert(cmd_ctx != NULL); + + if (goi->argc < 3) { + Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ?type? ..options..."); + return JIM_ERR; + } + + /* COMMAND */ + Jim_GetOpt_Obj(goi, &new_cmd); + /* does this command exist? */ + cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG); + if (cmd) { + cp = Jim_GetString(new_cmd, NULL); + Jim_SetResultFormatted(goi->interp, "Command/target: %s Exists", cp); + return JIM_ERR; + } + + /* TYPE */ + e = Jim_GetOpt_String(goi, &cp, NULL); + if (e != JIM_OK) + return e; + struct transport *tr = get_current_transport(); + if (tr->override_target) { + e = tr->override_target(&cp); + if (e != ERROR_OK) { + LOG_ERROR("The selected transport doesn't support this target"); + return JIM_ERR; + } + LOG_INFO("The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD"); + } + /* now does target type exist */ + for (x = 0 ; target_types[x] ; x++) { + if (0 == strcmp(cp, target_types[x]->name)) { + /* found */ + break; + } + + /* check for deprecated name */ + if (target_types[x]->deprecated_name) { + if (0 == strcmp(cp, target_types[x]->deprecated_name)) { + /* found */ + LOG_WARNING("target name is deprecated use: \'%s\'", target_types[x]->name); + break; + } + } + } + if (target_types[x] == NULL) { + Jim_SetResultFormatted(goi->interp, "Unknown target type %s, try one of ", cp); + for (x = 0 ; target_types[x] ; x++) { + if (target_types[x + 1]) { + Jim_AppendStrings(goi->interp, + Jim_GetResult(goi->interp), + target_types[x]->name, + ", ", NULL); + } else { + Jim_AppendStrings(goi->interp, + Jim_GetResult(goi->interp), + " or ", + target_types[x]->name, NULL); + } + } + return JIM_ERR; + } + + /* Create it */ + target = calloc(1, sizeof(struct target)); + /* set target number */ + target->target_number = new_target_number(); + cmd_ctx->current_target = target->target_number; + + /* allocate memory for each unique target type */ + target->type = calloc(1, sizeof(struct target_type)); + + memcpy(target->type, target_types[x], sizeof(struct target_type)); + + /* will be set by "-endian" */ + target->endianness = TARGET_ENDIAN_UNKNOWN; + + /* default to first core, override with -coreid */ + target->coreid = 0; + + target->working_area = 0x0; + target->working_area_size = 0x0; + target->working_areas = NULL; + target->backup_working_area = 0; + + target->state = TARGET_UNKNOWN; + target->debug_reason = DBG_REASON_UNDEFINED; + target->reg_cache = NULL; + target->breakpoints = NULL; + target->watchpoints = NULL; + target->next = NULL; + target->arch_info = NULL; + + target->display = 1; + + target->halt_issued = false; + + /* initialize trace information */ + target->trace_info = calloc(1, sizeof(struct trace)); + + target->dbgmsg = NULL; + target->dbg_msg_enabled = 0; + + target->endianness = TARGET_ENDIAN_UNKNOWN; + + target->rtos = NULL; + target->rtos_auto_detect = false; + + /* Do the rest as "configure" options */ + goi->isconfigure = 1; + e = target_configure(goi, target); + + if (target->tap == NULL) { + Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1); + e = JIM_ERR; + } + + if (e != JIM_OK) { + free(target->type); + free(target); + return e; + } + + if (target->endianness == TARGET_ENDIAN_UNKNOWN) { + /* default endian to little if not specified */ + target->endianness = TARGET_LITTLE_ENDIAN; + } + + cp = Jim_GetString(new_cmd, NULL); + target->cmd_name = strdup(cp); + + /* create the target specific commands */ + if (target->type->commands) { + e = register_commands(cmd_ctx, NULL, target->type->commands); + if (ERROR_OK != e) + LOG_ERROR("unable to register '%s' commands", cp); + } + if (target->type->target_create) + (*(target->type->target_create))(target, goi->interp); + + /* append to end of list */ + { + struct target **tpp; + tpp = &(all_targets); + while (*tpp) + tpp = &((*tpp)->next); + *tpp = target; + } + + /* now - create the new target name command */ + const struct command_registration target_subcommands[] = { + { + .chain = target_instance_command_handlers, + }, + { + .chain = target->type->commands, + }, + COMMAND_REGISTRATION_DONE + }; + const struct command_registration target_commands[] = { + { + .name = cp, + .mode = COMMAND_ANY, + .help = "target command group", + .usage = "", + .chain = target_subcommands, + }, + COMMAND_REGISTRATION_DONE + }; + e = register_commands(cmd_ctx, NULL, target_commands); + if (ERROR_OK != e) + return JIM_ERR; + + struct command *c = command_find_in_context(cmd_ctx, cp); + assert(c); + command_set_handler_data(c, target); + + return (ERROR_OK == e) ? JIM_OK : JIM_ERR; + } + + static int jim_target_current(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); + return JIM_ERR; + } + struct command_context *cmd_ctx = current_command_context(interp); + assert(cmd_ctx != NULL); + + Jim_SetResultString(interp, target_name(get_current_target(cmd_ctx)), -1); + return JIM_OK; + } + + static int jim_target_types(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (unsigned x = 0; NULL != target_types[x]; x++) { + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, target_types[x]->name, -1)); + } + return JIM_OK; + } + + static int jim_target_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, "Too many parameters"); + return JIM_ERR; + } + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + struct target *target = all_targets; + while (target) { + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, target_name(target), -1)); + target = target->next; + } + return JIM_OK; + } + + static int jim_target_smp(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + int i; + const char *targetname; + int retval, len; + struct target *target = (struct target *) NULL; + struct target_list *head, *curr, *new; + curr = (struct target_list *) NULL; + head = (struct target_list *) NULL; + + retval = 0; + LOG_DEBUG("%d", argc); + /* argv[1] = target to associate in smp + * argv[2] = target to assoicate in smp + * argv[3] ... + */ + + for (i = 1; i < argc; i++) { + + targetname = Jim_GetString(argv[i], &len); + target = get_target(targetname); + LOG_DEBUG("%s ", targetname); + if (target) { + new = malloc(sizeof(struct target_list)); + new->target = target; + new->next = (struct target_list *)NULL; + if (head == (struct target_list *)NULL) { + head = new; + curr = head; + } else { + curr->next = new; + curr = new; + } + } + } + /* now parse the list of cpu and put the target in smp mode*/ + curr = head; + + while (curr != (struct target_list *)NULL) { + target = curr->target; + target->smp = 1; + target->head = head; + curr = curr->next; + } + + if (target && target->rtos) + retval = rtos_smp_init(head->target); + + return retval; + } + + + static int jim_target_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv) + { + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc < 3) { + Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, + " [ ...]"); + return JIM_ERR; + } + return target_create(&goi); + } + + static const struct command_registration target_subcommand_handlers[] = { + { + .name = "init", + .mode = COMMAND_CONFIG, + .handler = handle_target_init_command, + .help = "initialize targets", + }, + { + .name = "create", + /* REVISIT this should be COMMAND_CONFIG ... */ + .mode = COMMAND_ANY, + .jim_handler = jim_target_create, + .usage = "name type '-chain-position' name [options ...]", + .help = "Creates and selects a new target", + }, + { + .name = "current", + .mode = COMMAND_ANY, + .jim_handler = jim_target_current, + .help = "Returns the currently selected target", + }, + { + .name = "types", + .mode = COMMAND_ANY, + .jim_handler = jim_target_types, + .help = "Returns the available target types as " + "a list of strings", + }, + { + .name = "names", + .mode = COMMAND_ANY, + .jim_handler = jim_target_names, + .help = "Returns the names of all targets as a list of strings", + }, + { + .name = "smp", + .mode = COMMAND_ANY, + .jim_handler = jim_target_smp, + .usage = "targetname1 targetname2 ...", + .help = "gather several target in a smp list" + }, + + COMMAND_REGISTRATION_DONE + }; + + struct FastLoad { + target_addr_t address; + uint8_t *data; + int length; + + }; + + static int fastload_num; + static struct FastLoad *fastload; + + static void free_fastload(void) + { + if (fastload != NULL) { + int i; + for (i = 0; i < fastload_num; i++) { + if (fastload[i].data) + free(fastload[i].data); + } + free(fastload); + fastload = NULL; + } + } + + COMMAND_HANDLER(handle_fast_load_image_command) + { + uint8_t *buffer; + size_t buf_cnt; + uint32_t image_size; + target_addr_t min_address = 0; + target_addr_t max_address = -1; + int i; + + struct image image; + + int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, + &image, &min_address, &max_address); + if (ERROR_OK != retval) + return retval; + + struct duration bench; + duration_start(&bench); + + retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL); + if (retval != ERROR_OK) + return retval; + + image_size = 0x0; + retval = ERROR_OK; + fastload_num = image.num_sections; + fastload = malloc(sizeof(struct FastLoad)*image.num_sections); + if (fastload == NULL) { + command_print(CMD_CTX, "out of memory"); + image_close(&image); + return ERROR_FAIL; + } + memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); + for (i = 0; i < image.num_sections; i++) { + buffer = malloc(image.sections[i].size); + if (buffer == NULL) { + command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", + (int)(image.sections[i].size)); + retval = ERROR_FAIL; + break; + } + + retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); + if (retval != ERROR_OK) { + free(buffer); + break; + } + + uint32_t offset = 0; + uint32_t length = buf_cnt; + + /* DANGER!!! beware of unsigned comparision here!!! */ + + if ((image.sections[i].base_address + buf_cnt >= min_address) && + (image.sections[i].base_address < max_address)) { + if (image.sections[i].base_address < min_address) { + /* clip addresses below */ + offset += min_address-image.sections[i].base_address; + length -= offset; + } + + if (image.sections[i].base_address + buf_cnt > max_address) + length -= (image.sections[i].base_address + buf_cnt)-max_address; + + fastload[i].address = image.sections[i].base_address + offset; + fastload[i].data = malloc(length); + if (fastload[i].data == NULL) { + free(buffer); + command_print(CMD_CTX, "error allocating buffer for section (%" PRIu32 " bytes)", + length); + retval = ERROR_FAIL; + break; + } + memcpy(fastload[i].data, buffer + offset, length); + fastload[i].length = length; + + image_size += length; + command_print(CMD_CTX, "%u bytes written at address 0x%8.8x", + (unsigned int)length, + ((unsigned int)(image.sections[i].base_address + offset))); + } + + free(buffer); + } + + if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { + command_print(CMD_CTX, "Loaded %" PRIu32 " bytes " + "in %fs (%0.3f KiB/s)", image_size, + duration_elapsed(&bench), duration_kbps(&bench, image_size)); + + command_print(CMD_CTX, + "WARNING: image has not been loaded to target!" + "You can issue a 'fast_load' to finish loading."); + } + + image_close(&image); + + if (retval != ERROR_OK) + free_fastload(); + + return retval; + } + + COMMAND_HANDLER(handle_fast_load_command) + { + if (CMD_ARGC > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + if (fastload == NULL) { + LOG_ERROR("No image in memory"); + return ERROR_FAIL; + } + int i; + int64_t ms = timeval_ms(); + int size = 0; + int retval = ERROR_OK; + for (i = 0; i < fastload_num; i++) { + struct target *target = get_current_target(CMD_CTX); + command_print(CMD_CTX, "Write to 0x%08x, length 0x%08x", + (unsigned int)(fastload[i].address), + (unsigned int)(fastload[i].length)); + retval = target_write_buffer(target, fastload[i].address, fastload[i].length, fastload[i].data); + if (retval != ERROR_OK) + break; + size += fastload[i].length; + } + if (retval == ERROR_OK) { + int64_t after = timeval_ms(); + command_print(CMD_CTX, "Loaded image %f kBytes/s", (float)(size/1024.0)/((float)(after-ms)/1000.0)); + } + return retval; + } + + static const struct command_registration target_command_handlers[] = { + { + .name = "targets", + .handler = handle_targets_command, + .mode = COMMAND_ANY, + .help = "change current default target (one parameter) " + "or prints table of all targets (no parameters)", + .usage = "[target]", + }, + { + .name = "target", + .mode = COMMAND_CONFIG, + .help = "configure target", + + .chain = target_subcommand_handlers, + }, + COMMAND_REGISTRATION_DONE + }; + + int target_register_commands(struct command_context *cmd_ctx) + { + return register_commands(cmd_ctx, NULL, target_command_handlers); + } + + static bool target_reset_nag = true; + + bool get_target_reset_nag(void) + { + return target_reset_nag; + } + + COMMAND_HANDLER(handle_target_reset_nag) + { + return CALL_COMMAND_HANDLER(handle_command_parse_bool, + &target_reset_nag, "Nag after each reset about options to improve " + "performance"); + } + + COMMAND_HANDLER(handle_ps_command) + { + struct target *target = get_current_target(CMD_CTX); + char *display; + if (target->state != TARGET_HALTED) { + LOG_INFO("target not halted !!"); + return ERROR_OK; + } + + if ((target->rtos) && (target->rtos->type) + && (target->rtos->type->ps_command)) { + display = target->rtos->type->ps_command(target); + command_print(CMD_CTX, "%s", display); + free(display); + return ERROR_OK; + } else { + LOG_INFO("failed"); + return ERROR_TARGET_FAILURE; + } + } + + static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size) + { + if (text != NULL) + command_print_sameline(cmd_ctx, "%s", text); + for (int i = 0; i < size; i++) + command_print_sameline(cmd_ctx, " %02x", buf[i]); + command_print(cmd_ctx, " "); + } + + COMMAND_HANDLER(handle_test_mem_access_command) + { + struct target *target = get_current_target(CMD_CTX); + uint32_t test_size; + int retval = ERROR_OK; + + if (target->state != TARGET_HALTED) { + LOG_INFO("target not halted !!"); + return ERROR_FAIL; + } + + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size); + + /* Test reads */ + size_t num_bytes = test_size + 4; + + struct working_area *wa = NULL; + retval = target_alloc_working_area(target, num_bytes, &wa); + if (retval != ERROR_OK) { + LOG_ERROR("Not enough working area"); + return ERROR_FAIL; + } + + uint8_t *test_pattern = malloc(num_bytes); + + for (size_t i = 0; i < num_bytes; i++) + test_pattern[i] = rand(); + + retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); + if (retval != ERROR_OK) { + LOG_ERROR("Test pattern write failed"); + goto out; + } + + for (int host_offset = 0; host_offset <= 1; host_offset++) { + for (int size = 1; size <= 4; size *= 2) { + for (int offset = 0; offset < 4; offset++) { + uint32_t count = test_size / size; + size_t host_bufsiz = (count + 2) * size + host_offset; + uint8_t *read_ref = malloc(host_bufsiz); + uint8_t *read_buf = malloc(host_bufsiz); + + for (size_t i = 0; i < host_bufsiz; i++) { + read_ref[i] = rand(); + read_buf[i] = read_ref[i]; + } + command_print_sameline(CMD_CTX, + "Test read %" PRIu32 " x %d @ %d to %saligned buffer: ", count, + size, offset, host_offset ? "un" : ""); + + struct duration bench; + duration_start(&bench); + + retval = target_read_memory(target, wa->address + offset, size, count, + read_buf + size + host_offset); + + duration_measure(&bench); + + if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { + command_print(CMD_CTX, "Unsupported alignment"); + goto next; + } else if (retval != ERROR_OK) { + command_print(CMD_CTX, "Memory read failed"); + goto next; + } + + /* replay on host */ + memcpy(read_ref + size + host_offset, test_pattern + offset, count * size); + + /* check result */ + int result = memcmp(read_ref, read_buf, host_bufsiz); + if (result == 0) { + command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", + duration_elapsed(&bench), + duration_kbps(&bench, count * size)); + } else { + command_print(CMD_CTX, "Compare failed"); + binprint(CMD_CTX, "ref:", read_ref, host_bufsiz); + binprint(CMD_CTX, "buf:", read_buf, host_bufsiz); + } + next: + free(read_ref); + free(read_buf); + } + } + } + + out: + free(test_pattern); + + if (wa != NULL) + target_free_working_area(target, wa); + + /* Test writes */ + num_bytes = test_size + 4 + 4 + 4; + + retval = target_alloc_working_area(target, num_bytes, &wa); + if (retval != ERROR_OK) { + LOG_ERROR("Not enough working area"); + return ERROR_FAIL; + } + + test_pattern = malloc(num_bytes); + + for (size_t i = 0; i < num_bytes; i++) + test_pattern[i] = rand(); + + for (int host_offset = 0; host_offset <= 1; host_offset++) { + for (int size = 1; size <= 4; size *= 2) { + for (int offset = 0; offset < 4; offset++) { + uint32_t count = test_size / size; + size_t host_bufsiz = count * size + host_offset; + uint8_t *read_ref = malloc(num_bytes); + uint8_t *read_buf = malloc(num_bytes); + uint8_t *write_buf = malloc(host_bufsiz); + + for (size_t i = 0; i < host_bufsiz; i++) + write_buf[i] = rand(); + command_print_sameline(CMD_CTX, + "Test write %" PRIu32 " x %d @ %d from %saligned buffer: ", count, + size, offset, host_offset ? "un" : ""); + + retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern); + if (retval != ERROR_OK) { + command_print(CMD_CTX, "Test pattern write failed"); + goto nextw; + } + + /* replay on host */ + memcpy(read_ref, test_pattern, num_bytes); + memcpy(read_ref + size + offset, write_buf + host_offset, count * size); + + struct duration bench; + duration_start(&bench); + + retval = target_write_memory(target, wa->address + size + offset, size, count, + write_buf + host_offset); + + duration_measure(&bench); + + if (retval == ERROR_TARGET_UNALIGNED_ACCESS) { + command_print(CMD_CTX, "Unsupported alignment"); + goto nextw; + } else if (retval != ERROR_OK) { + command_print(CMD_CTX, "Memory write failed"); + goto nextw; + } + + /* read back */ + retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf); + if (retval != ERROR_OK) { + command_print(CMD_CTX, "Test pattern write failed"); + goto nextw; + } + + /* check result */ + int result = memcmp(read_ref, read_buf, num_bytes); + if (result == 0) { + command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)", + duration_elapsed(&bench), + duration_kbps(&bench, count * size)); + } else { + command_print(CMD_CTX, "Compare failed"); + binprint(CMD_CTX, "ref:", read_ref, num_bytes); + binprint(CMD_CTX, "buf:", read_buf, num_bytes); + } + nextw: + free(read_ref); + free(read_buf); + } + } + } + + free(test_pattern); + + if (wa != NULL) + target_free_working_area(target, wa); + return retval; + } + + static const struct command_registration target_exec_command_handlers[] = { + { + .name = "fast_load_image", + .handler = handle_fast_load_image_command, + .mode = COMMAND_ANY, + .help = "Load image into server memory for later use by " + "fast_load; primarily for profiling", + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " + "[min_address [max_length]]", + }, + { + .name = "fast_load", + .handler = handle_fast_load_command, + .mode = COMMAND_EXEC, + .help = "loads active fast load image to current target " + "- mainly for profiling purposes", + .usage = "", + }, + { + .name = "profile", + .handler = handle_profile_command, + .mode = COMMAND_EXEC, + .usage = "seconds filename [start end]", + .help = "profiling samples the CPU PC", + }, + /** @todo don't register virt2phys() unless target supports it */ + { + .name = "virt2phys", + .handler = handle_virt2phys_command, + .mode = COMMAND_ANY, + .help = "translate a virtual address into a physical address", + .usage = "virtual_address", + }, + { + .name = "reg", + .handler = handle_reg_command, + .mode = COMMAND_EXEC, + .help = "display (reread from target with \"force\") or set a register; " + "with no arguments, displays all registers and their values", + .usage = "[(register_number|register_name) [(value|'force')]]", + }, + { + .name = "poll", + .handler = handle_poll_command, + .mode = COMMAND_EXEC, + .help = "poll target state; or reconfigure background polling", + .usage = "['on'|'off']", + }, + { + .name = "wait_halt", + .handler = handle_wait_halt_command, + .mode = COMMAND_EXEC, + .help = "wait up to the specified number of milliseconds " + "(default 5000) for a previously requested halt", + .usage = "[milliseconds]", + }, + { + .name = "halt", + .handler = handle_halt_command, + .mode = COMMAND_EXEC, + .help = "request target to halt, then wait up to the specified" + "number of milliseconds (default 5000) for it to complete", + .usage = "[milliseconds]", + }, + { + .name = "resume", + .handler = handle_resume_command, + .mode = COMMAND_EXEC, + .help = "resume target execution from current PC or address", + .usage = "[address]", + }, + { + .name = "reset", + .handler = handle_reset_command, + .mode = COMMAND_EXEC, + .usage = "[run|halt|init]", + .help = "Reset all targets into the specified mode." + "Default reset mode is run, if not given.", + }, + { + .name = "soft_reset_halt", + .handler = handle_soft_reset_halt_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "halt the target and do a soft reset", + }, + { + .name = "step", + .handler = handle_step_command, + .mode = COMMAND_EXEC, + .help = "step one instruction from current PC or address", + .usage = "[address]", + }, + { + .name = "mdd", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory words", + .usage = "['phys'] address [count]", + }, + { + .name = "mdw", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory words", + .usage = "['phys'] address [count]", + }, + { + .name = "mdh", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory half-words", + .usage = "['phys'] address [count]", + }, + { + .name = "mdb", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory bytes", + .usage = "['phys'] address [count]", + }, + { + .name = "mwd", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory word", + .usage = "['phys'] address value [count]", + }, + { + .name = "mww", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory word", + .usage = "['phys'] address value [count]", + }, + { + .name = "mwh", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory half-word", + .usage = "['phys'] address value [count]", + }, + { + .name = "mwb", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory byte", + .usage = "['phys'] address value [count]", + }, + { + .name = "bp", + .handler = handle_bp_command, + .mode = COMMAND_EXEC, + .help = "list or set hardware or software breakpoint", + .usage = "
[] ['hw'|'hw_ctx']", + }, + { + .name = "rbp", + .handler = handle_rbp_command, + .mode = COMMAND_EXEC, + .help = "remove breakpoint", + .usage = "address", + }, + { + .name = "wp", + .handler = handle_wp_command, + .mode = COMMAND_EXEC, + .help = "list (no params) or create watchpoints", + .usage = "[address length [('r'|'w'|'a') value [mask]]]", + }, + { + .name = "rwp", + .handler = handle_rwp_command, + .mode = COMMAND_EXEC, + .help = "remove watchpoint", + .usage = "address", + }, + { + .name = "load_image", + .handler = handle_load_image_command, + .mode = COMMAND_EXEC, + .usage = "filename address ['bin'|'ihex'|'elf'|'s19'] " + "[min_address] [max_length]", + }, + { + .name = "dump_image", + .handler = handle_dump_image_command, + .mode = COMMAND_EXEC, + .usage = "filename address size", + }, + { + .name = "verify_image_checksum", + .handler = handle_verify_image_checksum_command, + .mode = COMMAND_EXEC, + .usage = "filename [offset [type]]", + }, + { + .name = "verify_image", + .handler = handle_verify_image_command, + .mode = COMMAND_EXEC, + .usage = "filename [offset [type]]", + }, + { + .name = "test_image", + .handler = handle_test_image_command, + .mode = COMMAND_EXEC, + .usage = "filename [offset [type]]", + }, + { + .name = "mem2array", + .mode = COMMAND_EXEC, + .jim_handler = jim_mem2array, + .help = "read 8/16/32 bit memory and return as a TCL array " + "for script processing", + .usage = "arrayname bitwidth address count", + }, + { + .name = "array2mem", + .mode = COMMAND_EXEC, + .jim_handler = jim_array2mem, + .help = "convert a TCL array to memory locations " + "and write the 8/16/32 bit values", + .usage = "arrayname bitwidth address count", + }, + { + .name = "reset_nag", + .handler = handle_target_reset_nag, + .mode = COMMAND_ANY, + .help = "Nag after each reset about options that could have been " + "enabled to improve performance. ", + .usage = "['enable'|'disable']", + }, + { + .name = "ps", + .handler = handle_ps_command, + .mode = COMMAND_EXEC, + .help = "list all tasks ", + .usage = " ", + }, + { + .name = "test_mem_access", + .handler = handle_test_mem_access_command, + .mode = COMMAND_EXEC, + .help = "Test the target's memory access functions", + .usage = "size", + }, + + COMMAND_REGISTRATION_DONE + }; + static int target_register_user_commands(struct command_context *cmd_ctx) + { + int retval = ERROR_OK; + retval = target_request_register_commands(cmd_ctx); + if (retval != ERROR_OK) + return retval; + + retval = trace_register_commands(cmd_ctx); + if (retval != ERROR_OK) + return retval; + + + return register_commands(cmd_ctx, NULL, target_exec_command_handlers); + } diff --git a/src/target/target.h b/src/target/target.h index 4faf3119f..53f9e2614 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -25,13 +25,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TARGET_H -#define TARGET_H +#ifndef OPENOCD_TARGET_TARGET_H +#define OPENOCD_TARGET_TARGET_H #include @@ -95,7 +93,7 @@ enum target_endianness { }; struct working_area { - uint32_t address; + target_addr_t address; uint32_t size; bool free; uint8_t *backup; @@ -127,11 +125,14 @@ enum target_register_class { /* target_type.h contains the full definition of struct target_type */ struct target { struct target_type *type; /* target type definition (name, access functions) */ - const char *cmd_name; /* tcl Name of target */ + char *cmd_name; /* tcl Name of target */ int target_number; /* DO NOT USE! field to be removed in 2010 */ struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ + /** Should we defer examine to later */ + bool defer_examine; + /** * Indicates whether this target has been examined. * @@ -155,9 +156,9 @@ struct target { uint32_t working_area; /* working area (initialised RAM). Evaluated * upon first allocation from virtual/physical address. */ bool working_area_virt_spec; /* virtual address specified? */ - uint32_t working_area_virt; /* virtual address */ - bool working_area_phys_spec; /* virtual address specified? */ - uint32_t working_area_phys; /* physical address */ + target_addr_t working_area_virt; /* virtual address */ + bool working_area_phys_spec; /* physical address specified? */ + target_addr_t working_area_phys; /* physical address */ uint32_t working_area_size; /* size in bytes */ uint32_t backup_working_area; /* whether the content of the working area has to be preserved */ struct working_area *working_areas;/* list of allocated working areas */ @@ -172,17 +173,23 @@ struct target { struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */ uint32_t dbg_msg_enabled; /* debug message status */ void *arch_info; /* architecture specific information */ + void *private_config; /* pointer to target specific config data (for jim_configure hook) */ struct target *next; /* next target in list */ int display; /* display async info in telnet session. Do not display * lots of halted/resumed info when stepping in debugger. */ bool halt_issued; /* did we transition to halted state? */ - long long halt_issued_time; /* Note time when halt was issued */ + int64_t halt_issued_time; /* Note time when halt was issued */ bool dbgbase_set; /* By default the debug base is not set */ uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no * system in place to support target specific options * currently. */ + + bool ctibase_set; /* By default the debug base is not set */ + uint32_t ctibase; /* Really a Cortex-A specific option, but there is no + * system in place to support target specific options + * currently. */ struct rtos *rtos; /* Instance of Real Time Operating System support */ bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto" * and must be detected when symbols are offered */ @@ -351,7 +358,7 @@ int target_unregister_trace_callback( * yet it is possible to detect error conditions. */ int target_poll(struct target *target); -int target_resume(struct target *target, int current, uint32_t address, +int target_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); int target_halt(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); @@ -472,7 +479,7 @@ int target_get_gdb_reg_list(struct target *target, * This routine is a wrapper for target->type->step. */ int target_step(struct target *target, - int current, uint32_t address, int handle_breakpoints); + int current, target_addr_t address, int handle_breakpoints); /** * Run an algorithm on the @a target given. * @@ -525,9 +532,9 @@ int target_run_flash_async_algorithm(struct target *target, * This routine is a wrapper for target->type->read_memory. */ int target_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int target_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Write @a count items of @a size bytes to the memory of @a target at * the @a address given. @a address must be aligned to @a size @@ -546,9 +553,9 @@ int target_read_phys_memory(struct target *target, * This routine is wrapper for target->type->write_memory. */ int target_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int target_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* * Write to target memory using the virtual address. @@ -575,13 +582,13 @@ int target_write_phys_memory(struct target *target, * peripheral registers which do not support byte operations. */ int target_write_buffer(struct target *target, - uint32_t address, uint32_t size, const uint8_t *buffer); + target_addr_t address, uint32_t size, const uint8_t *buffer); int target_read_buffer(struct target *target, - uint32_t address, uint32_t size, uint8_t *buffer); + target_addr_t address, uint32_t size, uint8_t *buffer); int target_checksum_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t *crc); + target_addr_t address, uint32_t size, uint32_t *crc); int target_blank_check_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t *blank); + target_addr_t address, uint32_t size, uint32_t *blank, uint8_t erased_value); int target_wait_state(struct target *target, enum target_state state, int ms); /** @@ -657,14 +664,19 @@ void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_ void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf); void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf); -int target_read_u64(struct target *target, uint64_t address, uint64_t *value); -int target_read_u32(struct target *target, uint32_t address, uint32_t *value); -int target_read_u16(struct target *target, uint32_t address, uint16_t *value); -int target_read_u8(struct target *target, uint32_t address, uint8_t *value); -int target_write_u64(struct target *target, uint64_t address, uint64_t value); -int target_write_u32(struct target *target, uint32_t address, uint32_t value); -int target_write_u16(struct target *target, uint32_t address, uint16_t value); -int target_write_u8(struct target *target, uint32_t address, uint8_t value); +int target_read_u64(struct target *target, target_addr_t address, uint64_t *value); +int target_read_u32(struct target *target, target_addr_t address, uint32_t *value); +int target_read_u16(struct target *target, target_addr_t address, uint16_t *value); +int target_read_u8(struct target *target, target_addr_t address, uint8_t *value); +int target_write_u64(struct target *target, target_addr_t address, uint64_t value); +int target_write_u32(struct target *target, target_addr_t address, uint32_t value); +int target_write_u16(struct target *target, target_addr_t address, uint16_t value); +int target_write_u8(struct target *target, target_addr_t address, uint8_t value); + +int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value); +int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value); +int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value); +int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value); /* Issues USER() statements with target state information */ int target_arch_state(struct target *target); @@ -685,4 +697,4 @@ void target_handle_event(struct target *t, enum target_event e); extern bool get_target_reset_nag(void); -#endif /* TARGET_H */ +#endif /* OPENOCD_TARGET_TARGET_H */ diff --git a/src/target/target_request.c b/src/target/target_request.c index df2fc34ee..6ca204b50 100644 --- a/src/target/target_request.c +++ b/src/target/target_request.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/target_request.h b/src/target/target_request.h index 55ac0e9bf..1b1317338 100644 --- a/src/target/target_request.h +++ b/src/target/target_request.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TARGET_REQUEST_H -#define TARGET_REQUEST_H +#ifndef OPENOCD_TARGET_TARGET_REQUEST_H +#define OPENOCD_TARGET_TARGET_REQUEST_H struct target; struct command_context; @@ -54,4 +52,4 @@ int target_request_register_commands(struct command_context *cmd_ctx); */ bool target_got_message(void); -#endif /* TARGET_REQUEST_H */ +#endif /* OPENOCD_TARGET_TARGET_REQUEST_H */ diff --git a/src/target/target_type.h b/src/target/target_type.h index 234cdfb00..0960e6d59 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -19,13 +19,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TARGET_TYPE_H -#define TARGET_TYPE_H +#ifndef OPENOCD_TARGET_TARGET_TYPE_H +#define OPENOCD_TARGET_TARGET_TYPE_H #include @@ -55,11 +53,11 @@ struct target_type { /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); - int (*resume)(struct target *target, int current, uint32_t address, + /* See target.c target_resume() for documentation. */ + int (*resume)(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); - int (*step)(struct target *target, int current, uint32_t address, + int (*step)(struct target *target, int current, target_addr_t address, int handle_breakpoints); - /* target reset control. assert reset can be invoked when OpenOCD and * the target is out of sync. * @@ -113,27 +111,27 @@ struct target_type { * Target memory read callback. Do @b not call this function * directly, use target_read_memory() instead. */ - int (*read_memory)(struct target *target, uint32_t address, + int (*read_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Target memory write callback. Do @b not call this function * directly, use target_write_memory() instead. */ - int (*write_memory)(struct target *target, uint32_t address, + int (*write_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ - int (*read_buffer)(struct target *target, uint32_t address, + int (*read_buffer)(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ - int (*write_buffer)(struct target *target, uint32_t address, + int (*write_buffer)(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); - int (*checksum_memory)(struct target *target, uint32_t address, + int (*checksum_memory)(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum); - int (*blank_check_memory)(struct target *target, uint32_t address, - uint32_t count, uint32_t *blank); + int (*blank_check_memory)(struct target *target, target_addr_t address, + uint32_t count, uint32_t *blank, uint8_t erased_value); /* * target break-/watchpoint control @@ -177,15 +175,15 @@ struct target_type { */ int (*run_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t entry_point, - uint32_t exit_point, int timeout_ms, void *arch_info); + struct reg_param *reg_param, target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info); int (*start_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t entry_point, - uint32_t exit_point, void *arch_info); + struct reg_param *reg_param, target_addr_t entry_point, + target_addr_t exit_point, void *arch_info); int (*wait_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t exit_point, + struct reg_param *reg_param, target_addr_t exit_point, int timeout_ms, void *arch_info); const struct command_registration *commands; @@ -235,7 +233,7 @@ struct target_type { /* translate from virtual to physical address. Default implementation is successful * no-op(i.e. virtual==physical). */ - int (*virt2phys)(struct target *target, uint32_t address, uint32_t *physical); + int (*virt2phys)(struct target *target, target_addr_t address, target_addr_t *physical); /* read directly from physical memory. caches are bypassed and untouched. * @@ -245,13 +243,13 @@ struct target_type { * * Default implementation is to call read_memory. */ - int (*read_phys_memory)(struct target *target, uint32_t phys_address, + int (*read_phys_memory)(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); /* * same as read_phys_memory, except that it writes... */ - int (*write_phys_memory)(struct target *target, uint32_t phys_address, + int (*write_phys_memory)(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); int (*mmu)(struct target *target, int *enabled); @@ -278,4 +276,4 @@ struct target_type { uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); }; -#endif /* TARGET_TYPE_H */ +#endif /* OPENOCD_TARGET_TARGET_TYPE_H */ diff --git a/src/target/testee.c b/src/target/testee.c index b95cb82bc..5b6ccedd8 100644 --- a/src/target/testee.c +++ b/src/target/testee.c @@ -12,9 +12,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/trace.c b/src/target/trace.c index 9c2d3698c..63c477fbf 100644 --- a/src/target/trace.c +++ b/src/target/trace.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H diff --git a/src/target/trace.h b/src/target/trace.h index bb9c33637..2966bbd94 100644 --- a/src/target/trace.h +++ b/src/target/trace.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef TRACE_H -#define TRACE_H +#ifndef OPENOCD_TARGET_TRACE_H +#define OPENOCD_TARGET_TRACE_H struct target; struct command_context; @@ -58,4 +56,4 @@ int trace_register_commands(struct command_context *cmd_ctx); #define ERROR_TRACE_IMAGE_UNAVAILABLE (-1500) #define ERROR_TRACE_INSTRUCTION_UNAVAILABLE (-1501) -#endif /* TRACE_H */ +#endif /* OPENOCD_TARGET_TRACE_H */ diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index 3a26f71d1..34f92eaca 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -18,8 +18,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . * * Contact Information: * Intel Corporation @@ -49,8 +48,8 @@ static int read_mem(struct target *t, uint32_t size, uint32_t addr, uint8_t *buf); static int write_mem(struct target *t, uint32_t size, uint32_t addr, const uint8_t *buf); -static int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, - uint32_t *physaddr); +static int calcaddr_physfromlin(struct target *t, target_addr_t addr, + target_addr_t *physaddr); static int read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); static int write_phys_mem(struct target *t, uint32_t phys_address, @@ -114,7 +113,7 @@ int x86_32_common_mmu(struct target *t, int *enabled) return ERROR_OK; } -int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical) +int x86_32_common_virt2phys(struct target *t, target_addr_t address, target_addr_t *physical) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -135,8 +134,8 @@ int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physic } else { /* target halted in protected mode */ - if (calcaddr_pyhsfromlin(t, address, physical) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, + if (calcaddr_physfromlin(t, address, physical) != ERROR_OK) { + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, __func__, address); return ERROR_FAIL; } @@ -144,7 +143,7 @@ int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physic return ERROR_OK; } -int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_read_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -227,7 +226,7 @@ static int read_phys_mem(struct target *t, uint32_t phys_address, return retval; } -int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_write_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -236,7 +235,7 @@ int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, check_not_halted(t); if (!count || !buffer || !phys_address) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buffer, phys_address); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -445,7 +444,7 @@ static int write_mem(struct target *t, uint32_t size, return retval; } -int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) +int calcaddr_physfromlin(struct target *t, target_addr_t addr, target_addr_t *physaddr) { uint8_t entry_buffer[8]; @@ -569,16 +568,16 @@ int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) return ERROR_OK; } -int x86_32_common_read_memory(struct target *t, uint32_t addr, +int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", + LOG_DEBUG("addr=" TARGET_ADDR_FMT ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -592,9 +591,10 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, LOG_ERROR("%s could not disable paging", __func__); return retval; } - uint32_t physaddr = 0; - if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); + target_addr_t physaddr = 0; + if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, + __func__, addr); retval = ERROR_FAIL; } /* TODO: !!! Watch out for page boundaries @@ -604,7 +604,8 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, if (retval == ERROR_OK && x86_32_common_read_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to read memory from physical address 0x%08" PRIx32, __func__, physaddr); + LOG_ERROR("%s failed to read memory from physical address " TARGET_ADDR_FMT, + __func__, physaddr); retval = ERROR_FAIL; } /* restore PG bit if it was cleared prior (regardless of retval) */ @@ -616,7 +617,8 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, } else { /* paging is off - linear address is physical address */ if (x86_32_common_read_phys_mem(t, addr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to read memory from address 0%08" PRIx32, __func__, addr); + LOG_ERROR("%s failed to read memory from address " TARGET_ADDR_FMT, + __func__, addr); retval = ERROR_FAIL; } } @@ -624,16 +626,16 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, return retval; } -int x86_32_common_write_memory(struct target *t, uint32_t addr, +int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", + LOG_DEBUG("addr=" TARGET_ADDR_FMT ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -646,9 +648,9 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, LOG_ERROR("%s could not disable paging", __func__); return retval; } - uint32_t physaddr = 0; - if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, + target_addr_t physaddr = 0; + if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, __func__, addr); retval = ERROR_FAIL; } @@ -658,7 +660,7 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, */ if (retval == ERROR_OK && x86_32_common_write_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to write memory to physical address 0x%08" PRIx32, + LOG_ERROR("%s failed to write memory to physical address " TARGET_ADDR_FMT, __func__, physaddr); retval = ERROR_FAIL; } @@ -672,7 +674,7 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, /* paging is off - linear address is physical address */ if (x86_32_common_write_phys_mem(t, addr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to write memory to address 0x%08" PRIx32, + LOG_ERROR("%s failed to write memory to address " TARGET_ADDR_FMT, __func__, addr); retval = ERROR_FAIL; } @@ -853,7 +855,7 @@ int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp) int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all @@ -864,7 +866,7 @@ int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp) int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if (bp->set) @@ -1004,7 +1006,7 @@ static int unset_hwbp(struct target *t, struct breakpoint *bp) debug_reg_list[hwbp_num].used = 0; debug_reg_list[hwbp_num].bp_value = 0; - LOG_USER("%s hardware breakpoint %" PRIu32 " removed from 0x%08" PRIx32 " (hwreg=%d)", + LOG_USER("%s hardware breakpoint %" PRIu32 " removed from " TARGET_ADDR_FMT " (hwreg=%d)", __func__, bp->unique_id, bp->address, hwbp_num); return ERROR_OK; } @@ -1013,11 +1015,11 @@ static int set_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); - uint32_t physaddr; + target_addr_t physaddr; uint8_t opcode = SW_BP_OPCODE; uint8_t readback; - if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) + if (calcaddr_physfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; @@ -1033,7 +1035,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) return ERROR_FAIL; if (readback != SW_BP_OPCODE) { - LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32 ", check memory", + LOG_ERROR("%s software breakpoint error at " TARGET_ADDR_FMT ", check memory", __func__, bp->address); LOG_ERROR("%s readback=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, readback, *bp->orig_instr); @@ -1060,7 +1062,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) addto = addto->next; addto->next = new_patch; } - LOG_USER("%s software breakpoint %" PRIu32 " set at 0x%08" PRIx32, + LOG_USER("%s software breakpoint %" PRIu32 " set at " TARGET_ADDR_FMT, __func__, bp->unique_id, bp->address); return ERROR_OK; } @@ -1069,11 +1071,11 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); - uint32_t physaddr; + target_addr_t physaddr; uint8_t current_instr; /* check that user program has not modified breakpoint instruction */ - if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) + if (calcaddr_physfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, ¤t_instr)) return ERROR_FAIL; @@ -1082,7 +1084,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) if (write_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; } else { - LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32 ", check memory", + LOG_ERROR("%s software breakpoint remove error at " TARGET_ADDR_FMT ", check memory", __func__, bp->address); LOG_ERROR("%s current=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, current_instr, *bp->orig_instr); @@ -1108,7 +1110,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) } } - LOG_USER("%s software breakpoint %" PRIu32 " removed from 0x%08" PRIx32, + LOG_USER("%s software breakpoint %" PRIu32 " removed from " TARGET_ADDR_FMT, __func__, bp->unique_id, bp->address); return ERROR_OK; } @@ -1117,7 +1119,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) { int error = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (bp->set) { LOG_ERROR("breakpoint already set"); return error; @@ -1125,7 +1127,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) if (bp->type == BKPT_HARD) { error = set_hwbp(t, bp); if (error != ERROR_OK) { - LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error setting hardware breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return error; } @@ -1133,7 +1135,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) if (x86_32->sw_bpts_supported(t)) { error = set_swbp(t, bp); if (error != ERROR_OK) { - LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error setting software breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return error; } @@ -1148,7 +1150,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) static int unset_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (!bp->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; @@ -1156,13 +1158,13 @@ static int unset_breakpoint(struct target *t, struct breakpoint *bp) if (bp->type == BKPT_HARD) { if (unset_hwbp(t, bp) != ERROR_OK) { - LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error removing hardware breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return ERROR_FAIL; } } else { if (unset_swbp(t, bp) != ERROR_OK) { - LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error removing software breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return ERROR_FAIL; } @@ -1176,7 +1178,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; int wp_num = 0; - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); if (wp->set) { LOG_ERROR("%s watchpoint already set", __func__); @@ -1221,7 +1223,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) wp->set = wp_num + 1; debug_reg_list[wp_num].used = 1; debug_reg_list[wp_num].bp_value = wp->address; - LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", + LOG_USER("'%s' watchpoint %d set at " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); @@ -1232,7 +1234,7 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); if (!wp->set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; @@ -1250,7 +1252,7 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) debug_reg_list[wp_num].bp_value = 0; wp->set = 0; - LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", + LOG_USER("'%s' watchpoint %d removed from " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index af57a5f7e..0aaa963d7 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013-2016 Intel Corporation. * * Adrian Burns (adrian.burns@intel.com) * Thomas Faust (thomas.faust@intel.com) @@ -18,8 +18,7 @@ * General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . * * Contact Information: * Intel Corporation @@ -30,8 +29,8 @@ * This is the interface to the x86 32 bit memory and breakpoint operations. */ -#ifndef X86_32_COMMON_H -#define X86_32_COMMON_H +#ifndef OPENOCD_TARGET_X86_32_COMMON_H +#define OPENOCD_TARGET_X86_32_COMMON_H #include #include @@ -196,6 +195,11 @@ enum { WBINVD, }; +enum x86_core_type { + LMT1, + LMT3_5 +}; + struct swbp_mem_patch { uint8_t orig_byte; uint32_t swbp_unique_id; @@ -209,6 +213,7 @@ struct swbp_mem_patch { struct x86_32_common { uint32_t common_magic; void *arch_info; + enum x86_core_type core_type; struct reg_cache *cache; struct jtag_tap *curr_tap; uint32_t stored_pc; @@ -304,14 +309,14 @@ int x86_32_get_gdb_reg_list(struct target *t, int x86_32_common_init_arch_info(struct target *target, struct x86_32_common *x86_32); int x86_32_common_mmu(struct target *t, int *enabled); -int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical); -int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_virt2phys(struct target *t, target_addr_t address, target_addr_t *physical); +int x86_32_common_read_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); -int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_write_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); -int x86_32_common_read_memory(struct target *t, uint32_t addr, +int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf); -int x86_32_common_write_memory(struct target *t, uint32_t addr, +int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf); int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf); @@ -322,4 +327,4 @@ int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp); int x86_32_common_add_watchpoint(struct target *t, struct watchpoint *wp); int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp); -#endif /* X86_32_COMMON_H */ +#endif /* OPENOCD_TARGET_X86_32_COMMON_H */ diff --git a/src/target/xscale.c b/src/target/xscale.c index 82e41600e..8fe8a2cb9 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -19,9 +19,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ #ifdef HAVE_CONFIG_H @@ -61,7 +59,7 @@ /* forward declarations */ static int xscale_resume(struct target *, int current, - uint32_t address, int handle_breakpoints, int debug_execution); + target_addr_t address, int handle_breakpoints, int debug_execution); static int xscale_debug_entry(struct target *); static int xscale_restore_banked(struct target *); static int xscale_get_reg(struct reg *reg); @@ -75,7 +73,7 @@ static int xscale_read_trace(struct target *); * mini-ICache, which is 2K of code writable only via JTAG. */ static const uint8_t xscale_debug_handler[] = { -#include "xscale_debug.inc" +#include "../../contrib/loaders/debug/xscale/debug_handler.inc" }; static const char *const xscale_reg_list[] = { @@ -1122,7 +1120,7 @@ static void xscale_free_trace_data(struct xscale_common *xscale) } static int xscale_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1167,7 +1165,8 @@ static int xscale_resume(struct target *target, int current, enum trace_mode saved_trace_mode; /* there's a breakpoint at the current PC, we have to step over it */ - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); xscale_unset_breakpoint(target, breakpoint); /* calculate PC of next instruction */ @@ -1224,7 +1223,8 @@ static int xscale_resume(struct target *target, int current, LOG_DEBUG("disable single-step"); xscale_disable_single_step(target); - LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("set breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); xscale_set_breakpoint(target, breakpoint); } } @@ -1386,7 +1386,7 @@ static int xscale_step_inner(struct target *target, int current, } static int xscale_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct arm *arm = target_to_arm(target); struct breakpoint *breakpoint = NULL; @@ -1446,6 +1446,13 @@ static int xscale_assert_reset(struct target *target) { struct xscale_common *xscale = target_to_xscale(target); + /* TODO: apply hw reset signal in not examined state */ + if (!(target_was_examined(target))) { + LOG_WARNING("Reset is not asserted because the target is not examined."); + LOG_WARNING("Use a reset button or power cycle the target."); + return ERROR_TARGET_NOT_EXAMINED; + } + LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -1573,7 +1580,6 @@ static int xscale_deassert_reset(struct target *target) address += buf_cnt; } - ; retval = xscale_load_ic(target, 0x0, xscale->low_vectors); @@ -1774,7 +1780,7 @@ static int xscale_restore_banked(struct target *target) return ERROR_OK; } -static int xscale_read_memory(struct target *target, uint32_t address, +static int xscale_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -1782,7 +1788,7 @@ static int xscale_read_memory(struct target *target, uint32_t address, uint32_t i; int retval; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); @@ -1860,7 +1866,7 @@ static int xscale_read_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int xscale_read_phys_memory(struct target *target, uint32_t address, +static int xscale_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -1875,13 +1881,13 @@ static int xscale_read_phys_memory(struct target *target, uint32_t address, return ERROR_FAIL; } -static int xscale_write_memory(struct target *target, uint32_t address, +static int xscale_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); int retval; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); @@ -1959,7 +1965,7 @@ static int xscale_write_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int xscale_write_phys_memory(struct target *target, uint32_t address, +static int xscale_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -2663,7 +2669,7 @@ static int xscale_analyze_trace(struct target *target, struct command_context *c struct xscale_common *xscale = target_to_xscale(target); struct xscale_trace_data *trace_data = xscale->trace.data; int i, retval; - uint32_t breakpoint_pc; + uint32_t breakpoint_pc = 0; struct arm_instruction instruction; uint32_t current_pc = 0;/* initialized when address determined */ @@ -3089,7 +3095,7 @@ COMMAND_HANDLER(xscale_handle_cache_info_command) } static int xscale_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { struct xscale_common *xscale = target_to_xscale(target); uint32_t cb; @@ -3426,7 +3432,7 @@ COMMAND_HANDLER(xscale_handle_dump_trace_command) struct target *target = get_current_target(CMD_CTX); struct xscale_common *xscale = target_to_xscale(target); struct xscale_trace_data *trace_data; - struct fileio file; + struct fileio *file; int retval; retval = xscale_verify_pointer(CMD_CTX, xscale); @@ -3454,19 +3460,19 @@ COMMAND_HANDLER(xscale_handle_dump_trace_command) while (trace_data) { int i; - fileio_write_u32(&file, trace_data->chkpt0); - fileio_write_u32(&file, trace_data->chkpt1); - fileio_write_u32(&file, trace_data->last_instruction); - fileio_write_u32(&file, trace_data->depth); + fileio_write_u32(file, trace_data->chkpt0); + fileio_write_u32(file, trace_data->chkpt1); + fileio_write_u32(file, trace_data->last_instruction); + fileio_write_u32(file, trace_data->depth); for (i = 0; i < trace_data->depth; i++) - fileio_write_u32(&file, trace_data->entries[i].data | + fileio_write_u32(file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16)); trace_data = trace_data->next; } - fileio_close(&file); + fileio_close(file); return ERROR_OK; } diff --git a/src/target/xscale.h b/src/target/xscale.h index a71ec3514..a86edb2fb 100644 --- a/src/target/xscale.h +++ b/src/target/xscale.h @@ -16,13 +16,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef XSCALE_H -#define XSCALE_H +#ifndef OPENOCD_TARGET_XSCALE_H +#define OPENOCD_TARGET_XSCALE_H #include "arm.h" #include "armv4_5_mmu.h" @@ -187,4 +185,4 @@ enum { #define DCSR_TRAP_MASK \ (DCSR_TF | DCSR_TI | DCSR_TD | DCSR_TA | DCSR_TS | DCSR_TU | DCSR_TR) -#endif /* XSCALE_H */ +#endif /* OPENOCD_TARGET_XSCALE_H */ diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 7c6224a48..9076d9b68 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -1,11 +1,4 @@ -include $(top_srcdir)/common.mk - -#METASOURCES = AUTO -noinst_LTLIBRARIES = libtransport.la -libtransport_la_SOURCES = \ - transport.c - -noinst_HEADERS = \ - transport.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libtransport.la +%C%_libtransport_la_SOURCES = \ + %D%/transport.c \ + %D%/transport.h diff --git a/src/transport/transport.c b/src/transport/transport.c index c973e1c3a..708594712 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -12,8 +12,7 @@ * GNU General Public License for more details. * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ #ifdef HAVE_CONFIG_H diff --git a/src/transport/transport.h b/src/transport/transport.h index daf49604c..6c57067a3 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -13,12 +13,11 @@ * GNU General Public License for more details. * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * along with this program. If not, see . */ -#ifndef TRANSPORT_H -#define TRANSPORT_H +#ifndef OPENOCD_TRANSPORT_TRANSPORT_H +#define OPENOCD_TRANSPORT_TRANSPORT_H #include "helper/command.h" @@ -91,4 +90,4 @@ int allow_transports(struct command_context *ctx, const char * const *vector); bool transports_are_declared(void); -#endif +#endif /* OPENOCD_TRANSPORT_TRANSPORT_H */ diff --git a/src/xsvf/Makefile.am b/src/xsvf/Makefile.am index 1b9cfab00..61e6fb920 100644 --- a/src/xsvf/Makefile.am +++ b/src/xsvf/Makefile.am @@ -1,8 +1,2 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libxsvf.la -noinst_HEADERS = xsvf.h -libxsvf_la_SOURCES = xsvf.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libxsvf.la +%C%_libxsvf_la_SOURCES = %D%/xsvf.c %D%/xsvf.h diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c index a6de82397..63c891511 100644 --- a/src/xsvf/xsvf.c +++ b/src/xsvf/xsvf.c @@ -22,9 +22,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ /* The specification for SVF is available here: diff --git a/src/xsvf/xsvf.h b/src/xsvf/xsvf.h index 3f35aea52..aa0f4f040 100644 --- a/src/xsvf/xsvf.h +++ b/src/xsvf/xsvf.h @@ -13,13 +13,11 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see . * ***************************************************************************/ -#ifndef XSVF_H -#define XSVF_H +#ifndef OPENOCD_XSVF_XSVF_H +#define OPENOCD_XSVF_XSVF_H #include @@ -28,4 +26,4 @@ int xsvf_register_commands(struct command_context *cmd_ctx); #define ERROR_XSVF_EOF (-200) #define ERROR_XSVF_FAILED (-201) -#endif /* XSVF_H */ +#endif /* OPENOCD_XSVF_XSVF_H */