搜索
bottom↓
回复: 97

开贴记录SWD 脱机烧录器开发过程,请各路大神指教

  [复制链接]

出0入0汤圆

发表于 2015-8-21 11:03:16 | 显示全部楼层 |阅读模式
参考 CMISI_DAP,BlackMagic代码。
预备下周末结案,目前方案:
1:Host用STM32F427,跑RTEMS系统, IO口模拟SWD时序。
2:flash的操作函数,由Host通过SWD下载入target ram执行。(CMISI_DAP采用这种方式)
     不知道jlink的flash操作是不是一样的原理。他要适用这么多芯片,那得有准备多少这样的小程序啊。。。
3:USB用的虚拟串口,用ST官方提供的驱动,上位机编程简单。tafget本身程序.bin文件由上位机通过虚拟串口传入。
     此虚拟串口的波特率,奇偶,起停位设置均形同虚设。

目前状态:
SWD时序基本调试通过,读写target ID/reg已经正常,暂时未经过高强度测试。。
正在弄flash操作。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2015-8-21 11:24:53 | 显示全部楼层
不这样写入个小程序,针对每个芯片,不还得再写另一套程序嘛。
CMSIS_DAP的至少可以通用MDK的,省了你很多事。

出0入0汤圆

 楼主| 发表于 2015-8-21 13:23:49 | 显示全部楼层
aozima 发表于 2015-8-21 11:24
不这样写入个小程序,针对每个芯片,不还得再写另一套程序嘛。
CMSIS_DAP的至少可以通用MDK的,省了你很多 ...

担心通过SWD去擦除比较慢!!
通过SWD 控制target的flash寄存器达到同样的效果。。。暂时还在实验中,但也会存在针对不同芯片寄存器表不同的问题。
写入小程序的方法,别人已经实现,成功的概率目前来看比较大!

出0入0汤圆

发表于 2015-8-21 14:12:11 | 显示全部楼层
精神上支持你

出0入0汤圆

发表于 2015-8-21 14:14:27 | 显示全部楼层
本帖最后由 hanshiruo 于 2015-8-21 14:16 编辑

...........

出0入0汤圆

发表于 2015-8-21 14:19:10 | 显示全部楼层
>>>IO口模拟SWD时序。
这个能否使用Timer驱动,速度或许能高些。

出0入0汤圆

发表于 2015-8-21 14:23:44 | 显示全部楼层
搬条板凳坐等》》》

出0入0汤圆

发表于 2015-8-21 14:28:22 | 显示全部楼层
abbott.yang 发表于 2015-8-21 13:23
担心通过SWD去擦除比较慢!!
通过SWD 控制target的flash寄存器达到同样的效果。。。暂时还在实验中,但 ...

擦除FLASH都是毫秒甚至秒级,由FLASH本身决定,这和SWD有毛关系?不用SWD能变快?

出0入0汤圆

发表于 2015-8-21 14:28:28 | 显示全部楼层
本帖最后由 hanshiruo 于 2015-8-21 14:39 编辑

有现成的SWD脱机下载器,已经卖出许多,稳定可靠

出0入0汤圆

发表于 2015-8-21 14:33:31 | 显示全部楼层
abbott.yang 发表于 2015-8-21 13:23
担心通过SWD去擦除比较慢!!
通过SWD 控制target的flash寄存器达到同样的效果。。。暂时还在实验中,但 ...

SWD擦除与FLASH自身参数有关,与SWD速度无关。

出0入0汤圆

发表于 2015-8-21 14:37:11 | 显示全部楼层
czdavid 发表于 2015-8-21 14:33
SWD擦除与FLASH自身参数有关,与SWD速度无关。

通过 SWD 控制target的flash寄存器达到同样的效果和
通过SWD下载程序到内部RAM来控制target的flash寄存器
两者速度是否会有些区别?

出0入0汤圆

发表于 2015-8-21 14:40:07 | 显示全部楼层
shangdawei 发表于 2015-8-21 14:37
通过 SWD 控制target的flash寄存器达到同样的效果和
通过SWD下载程序到内部RAM来控制target的flash寄存器 ...

区分在于你直接写FLASH的时候, 要等待FLASH完成才能传输新数据

RAM执行程序的话, 可以在RAM->FLASH的过程中接收SWD->RAM的新数据

出0入0汤圆

发表于 2015-8-21 14:47:35 | 显示全部楼层
shangdawei 发表于 2015-8-21 14:37
通过 SWD 控制target的flash寄存器达到同样的效果和
通过SWD下载程序到内部RAM来控制target的flash寄存器 ...

最简单和直接的就是直接SWD挂AHB总线控制target的FLASH寄存器。
当然为了效率和稳定性最好通过RAM缓冲。
至于时间上,不考虑稳定和出错这个因素,直接操作FLASH寄存器速度也不慢。

出0入0汤圆

发表于 2015-8-21 14:55:39 | 显示全部楼层



Freescale OSBDM JM60仿真器OSBDM Development Port Interfaces
BGND Interface

The BGND interface provides the standard 6 pin connection for the single wire BGND signal type development port.
Target types that apply this development port are the 9S08, RS08, and Coldfire V1.
+V_TRG, TBGND, TRG_RST*, and Ground are applied by this port type.
The BGND interface applies U4 as the signal transceiver.
U4 is a 74LVC1T45 logic gate with voltage level shifting features.
Operation on the target side (+V_TRG) is 1.8V to 5.5V.
The JM60 side is always +5V from the +5V_SW signal.

JM60 signals TBGND_EN, TBGND_IN, and TBGND_OUT provide the communication and control for this interface.

All these signals are associated with JM60 timer channels for precise timing capability to a 41.67ns time step period.
For more information on the input and output ports, refer to the Signal Chart section.

TBGND_ EN provides directional control for transmit or receive operations.
The signal is logic high for transmit output and logic low to receive input.
JM60 timer 2 channel 1 provides the primary signal direction control during the communication with the target.
The idle condition is low so that the interface is not driven unless the communication is intended.
During the communication, the direction is fixed to output the command to the target.
During the reception, the signal is timed in edge aligned PWM mode to provide the BGND start pulse prior to the target reply input.

TBGND_OUT provides the transmit signal output from the JM60 to the target.
Timer 2 channel 0 controls this signal in edge aligned PWM mode.
For data transmission, the timer channel will output an active low signal with a time period that represents a logic one bit value or logic 0 bit value.
In receive mode, the timer channel will provide a low output for the start bit on the BGND signal and then provide timing internally for the reply signal input time window.

TBGND_IN provides receive signal input from the target to the JM60.
Timer 1 channel 3 is applied to measure the input signal duration in capture mode (25Mhz BDC clock maximum).
This operation provides the timing to determine a logic 1 or 0 bit value input from the target.
RS08 type targets apply a lower speed communication technique that inputs the JM60 port value (sample mode) instead of using the timer capture.
This is due to the RS08 will not provide a stable input signal after the start bit generation and creates false timer capture edges.
Other undefined target types may exhibit the same issue and may apply sample mode, if required (10MHz BDC clock maximum).
NOTE The TBGND_OUT and TBGND_IN signals are connected with resistor R1. R1 provides isolation between the 2 timer channels.



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-21 15:03:27 | 显示全部楼层
sw离线烧录,留名,有时间自己整一个,通用的离线烧录器局限性太多!

出0入0汤圆

发表于 2015-8-21 15:04:00 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2015-8-21 16:12:32 | 显示全部楼层
shangdawei 发表于 2015-8-21 14:19
>>>IO口模拟SWD时序。
这个能否使用Timer驱动,速度或许能高些。

观察了SWD波形,想用SPI的8字节数据去套这个协议。。可惜都不是8字节对齐,中间还有有接收ACK。。。shangdawei 给的电路是要SPI的I/O接一起同时收发的意思?Out线上电阻不好挑,大了out线驱动力不足,小了IN线上target拉不低/高。还要配好数据发送,然后从回来的数据中挑出ACK以及数据,一样费CPU时间。 不知道Jlink里面是怎么控制速度的。它的波形很好,JTAG转SWD,它正好是56个时钟,估计是用的SPI吧,有了解的么?
用Timer如果快起来的话,Timer中断会很频繁,看Jlink可以设置10M。。。timer中断间隔就要设置为1/20M,50ns。我是怕1us以下的中断系统难以承受。。
这个尝试后面再说。先把基本的弄起来再考虑速度优化!

出0入0汤圆

 楼主| 发表于 2015-8-21 16:17:57 | 显示全部楼层
本帖最后由 abbott.yang 于 2015-8-21 16:19 编辑
shangdawei 发表于 2015-8-21 14:37
通过 SWD 控制target的flash寄存器达到同样的效果和
通过SWD下载程序到内部RAM来控制target的flash寄存器 ...


区别很小吧,特别是SWD速度够快的时候。blackmagic和DAP不同,它是用SWD直接操作target flash寄存器来完成的。
IO模拟速度慢,然后考虑的是做这个脱机烧录只是我要做的东西的一部分,后面会把整个产线的一些功能都集成进来,所以在启动时一次性把程序下进去完事。操作flash就可以少用几个SWD读写动作。
省点点时间,蚊子小也有肉。以前用资源,时钟很少很慢的低级MCU留下的习惯,比较抠门!

出0入0汤圆

 楼主| 发表于 2015-8-21 16:23:36 | 显示全部楼层
czdavid 发表于 2015-8-21 14:47
最简单和直接的就是直接SWD挂AHB总线控制target的FLASH寄存器。
当然为了效率和稳定性最好通过RAM缓冲。
...

David童鞋你的东西做好了没。。。。
我还想向你请教来着。就是积分低啊,不能发消息不能加好友!
万恶的积分!!!!

出0入0汤圆

发表于 2015-8-21 18:55:01 | 显示全部楼层





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-21 20:35:13 | 显示全部楼层
给自己公司做了一个SWD的烧写器,用的IO模拟,就是速度上不去

出0入0汤圆

发表于 2015-8-21 20:50:00 | 显示全部楼层
Programming Internal Flash Over the Serial Wire Debug Interface

This document explains how to access the debug interface of the EFM32 and how to use this interface to program devices (load applications into flash).
It also explains how to lock and unlock debug access to the MCU to protect the contents of the internal flash and SRAM.


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-21 20:57:49 | 显示全部楼层

Programming Internal Flash Over the Serial Wire Debug Interface





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出100入85汤圆

发表于 2015-8-22 07:38:56 来自手机 | 显示全部楼层
好样的,弄好了普及一下

出0入0汤圆

发表于 2015-8-22 09:50:44 | 显示全部楼层
abbott.yang 发表于 2015-8-21 16:12
观察了SWD波形,想用SPI的8字节数据去套这个协议。。可惜都不是8字节对齐,中间还有有接收ACK。。。shang ...

>> 正好是56个时钟 ?



拦截V9的波形,这个是51个时钟吧?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 17:50:13 | 显示全部楼层
Programming internal SRAM over SWD

This documentation describe how to programming ARM Cortex M3 internal SRAM over SWD(Serial Wire Debug) interface. For this purpose, something we too know.

SWD communication protocol. We need to know Low level timing requirement, that is foundation to exchange command and data between debugger and target MCU.
Read/write data from/to internal SRAM. We need to know how to program firmware into desired address, like SRAM(0x20000000). That needs us to know SW-DAP registers usage. Pass address and data over those registers and then into internal SRAM.
Make code running from SRAM. We need to change vector table entry from internal flash to SRAM; And SP and PC also needed change to SRAM location. That need us to know the cortex M3 debug and system registers usage.
We choose Silabs SiM3U167 as target MCU in this implementation. We implement a high level protocol with python script, it calls Silabs provided DLL file interface to access Silabs USB Debug Adapter. Also, we provide a firmware running from C8051F380, it contains a full implementation on both low level communicating timing and high level programming SRAM protocol.





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 18:11:50 | 显示全部楼层
Serial Wire Debug (SWD) Open Library for low level Debug Access Port (DAP) on new ARM Cortex CPU devices.

This is an official website of the LibSWD Project - Free and Open solution for accessing the SW-DP (Serial Wire Debug Port)
on ARM-Cortex CPU based embedded systems. Source code is released under "new" 3 clause BSD License.





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 18:30:35 | 显示全部楼层
MBED-HDK SWD Interface

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 21:15:57 | 显示全部楼层
IBDAP-CMSIS-DAP IO模拟SWD时序

Armstart's CMSIS-DAP firmware implementation in gcc and makefile.


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 21:19:13 | 显示全部楼层
swddude -- A SWD programmer for ARM Cortex microcontrollers.

需要提供底层驱动





  1. #ifndef SWD_H
  2. #define SWD_H

  3. /*
  4. * Abstract base class for SWD interface drivers.
  5. */

  6. #include "libs/error/error_stack.h"

  7. #include <stdint.h>

  8. /*
  9. * SWDDriver provides a low-level interface to SWD interface devices.
  10. * Each function maps directly to a SWD protocol concept.  The ARM ADIv5
  11. * specification explains the SWD protocol in more detail; it's available
  12. * behind a clickwrap license on ARM's site.
  13. *
  14. * Client software should rarely interact with SWDDriver directly.  Instead,
  15. * wrap it in another object that provides a higher-level more pleasant
  16. * interface with support for things like retries and named registers.
  17. */
  18. class SWDDriver {
  19. public:
  20.     /*
  21.      * Creates an instance of the driver.  Because the constructor can't
  22.      * return any meaningful error condition, implementations should only do
  23.      * things that can't fail -- such as copying in constructor arguments
  24.      * and initializing memory.
  25.      */
  26.     SWDDriver() {}

  27.     /*
  28.      * Destroys this driver instance.  Because the destructor can't return
  29.      * any meaningful error condition, any resource cleanup here is
  30.      * last-resort.  Clients should call the close() function to clean up
  31.      * resources in a way that can report errors.  Destructor
  32.      * implementations may optionally log attempts to destroy a driver
  33.      * instance without calling close(), as this indicates a programming
  34.      * error.
  35.      */
  36.     virtual ~SWDDriver() {}

  37.     /*
  38.      * Initialize the SWD link to the target, per the "Connection and line
  39.      * reset sequence" defined by the ARM ADI v5.  This has two parts:
  40.      *   1. 50 clocks with the SWDIO line held high by the master.
  41.      *   2. A read of the IDCODE register in the DP.
  42.      *
  43.      * Because this function reads IDCODE behind the scenes, it can
  44.      * optionally return it to the application through the pointer argument.
  45.      *
  46.      * If this function returns successfully, it indicates that the
  47.      * interface is functioning, and that an attached microprocessor has
  48.      * responded to us.  The state of the target is unknown -- in
  49.      * particular, the contents of the Debug Access Port's SELECT and
  50.      * CTRL/STAT registers are undefined.
  51.      *
  52.      * Return values:
  53.      *  Err::success - initialization complete, target responded, IDCODE
  54.      *                 valid.
  55.      *  Err::failure - initialization failed or target failed to respond.
  56.      */
  57.     virtual Err::Error initialize(uint32_t * idcode_out = 0) = 0;

  58.     /*
  59.      * Asserts the target's reset line continuously until a call to
  60.      * leave_reset.
  61.      *
  62.      * Return values:
  63.      *  Err::success - reset asserted.
  64.      *  Err::failure - communications with interface failed.
  65.      */
  66.     virtual Err::Error enter_reset() = 0;

  67.     /*
  68.      * Deasserts the target's reset line, allowing it to run.
  69.      *
  70.      * Return values:
  71.      *  Err::success - reset deasserted.
  72.      *  Err::failure - communications with interface failed.
  73.      */
  74.     virtual Err::Error leave_reset() = 0;

  75.     /*
  76.      * Reads a 32-bit register from either the Debug Access Port (when
  77.      * debug_port is true) or the Access Port bank named in the DAP's SELECT
  78.      * register (when debug_port is false).
  79.      *
  80.      * Access Port reads are delayed: each read returns the result of the
  81.      * previous operation.  To kick off a read without retrieving the
  82.      * results of the last one, pass a data pointer of zero; the result
  83.      * won't be written.  To retrieve the results of the last Access Port
  84.      * read without starting a new one, read the Debug Access Port's RDBUFF
  85.      * register instead.  
  86.      *
  87.      * Note that some registers can only be accessed in particular states of
  88.      * the CTRL/STAT register, and some registers can't be read at all.
  89.      *
  90.      * Refer to the ARM ADIv5 spec for more information.
  91.      *
  92.      * Implementation note: drivers should implement this function such that
  93.      * it will work regardless of mode.  In particular, it must not assume
  94.      * that Overrun Detection is enabled in the DAP.
  95.      *
  96.      * Return values:
  97.      *  Err::success   - read completed, data valid.
  98.      *  Err::try_again - target returned SWD WAIT response, read not
  99.      *                   completed.
  100.      *  Err::failure   - read failed, either in the interface or due to SWD
  101.      *                   FAULT.
  102.      */
  103.     virtual Err::Error read(unsigned   address,
  104.                             bool       debug_port,
  105.                             uint32_t * data) = 0;

  106.     /*
  107.      * Writes a 32-bit value into a register in either the Debug Access Port
  108.      * (when debug_port is true) or the Access Port bank named in the DAP's
  109.      * SELECT register (when debug_port is false).
  110.      *
  111.      * Access Port writes may take time to complete.  For a MEM-AP, monitor
  112.      * the status of the TrInProg (transaction in progress) bit of the
  113.      * Access Port's CSW register to detect when another write may be
  114.      * issued.
  115.      *
  116.      * Note that some registers can only be accessed in particular states of
  117.      * the CTRL/STAT register, and some registers can't be written at all.
  118.      *
  119.      * Refer to the ARM ADIv5 spec for more information.
  120.      *
  121.      * Implementation note: drivers should implement this function such that
  122.      * it will work regardless of mode.  In particular, it must not assume
  123.      * that Overrun Detection is enabled in the DAP.
  124.      *
  125.      * Return values:
  126.      *  Err::success   - write completed.
  127.      *  Err::try_again - target returned SWD WAIT response, write not
  128.      *                   completed.
  129.      *  Err::failure   - write failed, either in the interface or due to SWD
  130.      *                   FAULT.
  131.      */
  132.     virtual Err::Error write(unsigned address,
  133.                              bool     debug_port,
  134.                              uint32_t data) = 0;
  135. };

  136. #endif  // SWD_H
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 21:19:54 | 显示全部楼层
关注一下,虽然用这个,但是却对其不了解

出0入0汤圆

发表于 2015-8-22 22:28:45 | 显示全部楼层

http://mbed.org/handbook/cmsis-dap-interface-firmware

https://github.com/mbedmicro/CMSIS-DAP

The CMSIS-DAP Interface Firmware provides:

USB Mass Storage Device for drag and drop programming of the target chip
USB Communications Device Class for Serial Communication with the target chip
USB HID CMSIS-DAP for debugging
USB bootloader for updating the interface firmware itself

出0入0汤圆

发表于 2015-8-22 22:30:23 | 显示全部楼层
ARM调试接口SWD(Serial Wire Debug) 协议分析
http://www.amobbs.com/thread-5498445-1-1.html
(出处: amoBBS 阿莫电子论坛)

出0入0汤圆

发表于 2015-8-22 22:32:23 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-22 23:33:30 | 显示全部楼层


这个使用了 SPI 接口, 可以参考一下。

混合模式,传送 Request 和 Data 时用 SPI, 传送 ACK 时用模拟的。


  1. //=================================================================================
  2. // ARM SWD Mode Port Bit masks
  3. //
  4. #if (HW_CAPABILITY&CAP_SWD_HW)
  5. #ifndef DATA_PORT
  6. #define DATA_PORT          PTAD
  7. #define DATA_PORT_DDR      PTADD
  8. #define DATA_PORT_PER      PTAPE
  9. #endif

  10. // SWD data out pin
  11. #define SWD_OUT             PTAD_PTAD2
  12. #define SWD_OUT_BIT         (2)  // Bit number!
  13. #define SWD_OUT_MASK        (1<<SWD_OUT_BIT)
  14. #define SWD_OUT_PER         PTAPE_PTAPE2
  15. #define SWD_OUT_DDR         PTADD_PTADD2

  16. // SWD data out 3-state control
  17. #define SWD_OUT_EN          PTAD_PTAD4
  18. #define SWD_OUT_EN_BIT      (4)  // Bit number!
  19. #define SWD_OUT_EN_MASK     (1<<SWD_OUT_EN_BIT)
  20. #define SWD_OUT_EN_PER      PTAPE_PTAPE4
  21. #define SWD_OUT_EN_DDR      PTADD_PTADD4

  22. // Following assume pin already configured by SWD_LOW(),SWD_HIGH(),SWD_3STATE()
  23. #define SWD_ENABLE_ASM      BCLR SWD_OUT_EN_BIT,DATA_PORT
  24. #define SWD_3STATE_ASM      BSET SWD_OUT_EN_BIT,DATA_PORT
  25. #define SWD_LOW_ASM         BCLR SWD_OUT_BIT,DATA_PORT
  26. #define SWD_HIGH_ASM        BSET SWD_OUT_BIT,DATA_PORT
  27. #define SWD_DISABLE_ASM     BCLR SWD_OUT_EN_BIT,DATA_PORT_DDR
  28. #define SWD_ENABLE_DRV_ASM  BSET SWD_OUT_EN_BIT,DATA_PORT_DDR

  29. // Following configure pin & driver
  30. #define SWD_LOW()           (SWD_OUT=0, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
  31. #define SWD_HIGH()          (SWD_OUT=1, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
  32. #define SWD_3STATE()        (SWD_OUT_EN=1, SWD_OUT_EN_DDR=1, SWD_OUT_DDR=1)
  33. #define SWD_DISABLE()       (SWD_OUT_EN=1, SWD_OUT_EN_DDR=0, SWD_OUT_DDR=0) // PUPs

  34. // SWD data in pin
  35. #define SWD_IN              PTAD_PTAD0
  36. #define SWD_IN_BIT          (0)  // Bit number!
  37. #define SWD_IN_MASK         (1<<SWD_IN_BIT)
  38. #define SWD_IN_PER          PTAPE_PTAPE0
  39. #define SWD_IN_DDR          PTADD_PTADD0

  40. // SWCLK out pin
  41. #define SWCLK_OUT           PTAD_PTAD3
  42. #define SWCLK_OUT_BIT       (3)  // Bit number!
  43. #define SWCLK_OUT_MASK      (1<<SWCLK_OUT_BIT)
  44. #define SWCLK_OUT_PER       PTAPE_PTAPE3
  45. #define SWCLK_OUT_DDR       PTADD_PTADD3

  46. // SWCLK enable pin - controls buffer enable
  47. #define SWCLK_OUT_EN        PTBD_PTBD1
  48. #define SWCLK_OUT_EN_BIT    (1)  // Bit number!
  49. #define SWCLK_OUT_EN_MASK   (1<<SWCLK_OUT_EN_BIT)
  50. #define SWCLK_OUT_EN_PER    PTBPE_PTBPE1
  51. #define SWCLK_OUT_EN_DDR    PTBDD_PTBDD1

  52. // Following assume pin direction already set
  53. #define SWCLK_LOW_ASM       BCLR SWCLK_OUT_BIT,DATA_PORT
  54. #define SWCLK_HIGH_ASM      BSET SWCLK_OUT_BIT,DATA_PORT

  55. // Following configure pin & driver
  56. #define SWCLK_LOW()         (SWCLK_OUT=0, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
  57. #define SWCLK_HIGH()        (SWCLK_OUT=1, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
  58. #define SWCLK_3STATE()      (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=1, SWCLK_OUT_DDR=1) // PUPs
  59. #define SWCLK_DISABLE()     (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=0, SWCLK_OUT_DDR=0) // PUPs

  60. #endif // CAP_SWD
复制代码

  1. /*
  2. * SWD.h
  3. *
  4. *  Created on: 04/08/2012
  5. *      Author: PODonoghue
  6. */

  7. #ifndef SWD_H_
  8. #define SWD_H_

  9. #include "Common.h"

  10. // Ack values displaced by offset introduced during read (left justified 8-bit value)
  11. #define SWD_ACK_OK       (0x1<<5)
  12. #define SWD_ACK_WAIT     (0x2<<5)
  13. #define SWD_ACK_FAULT    (0x4<<5)
  14. #define SWD_ACK_PROTOCOL (0x7<<5)

  15. void swd_interfaceIdle(void);
  16. void swd_init(void);
  17. void swd_txIdle8(void);

  18. U8 swd_test(void);

  19. U8 swd_sendCommandWithWait(U8 command);

  20. U8 swd_connect(void);
  21. U8 swd_readReg(U8 command, U8 *data);
  22. U8 swd_writeReg(U8 command, const U8 *data);
  23. U8 swd_readAPReg(const U8 *address, U8 *buff);
  24. U8 swd_writeAPReg(const U8 *address, const U8 *buff);
  25. U8 swd_clearStickyError(void);
  26. U8 swd_abortAP(void);
  27. #endif /* SWD_H_ */
复制代码

  1. /*! \file
  2.     \brief ARM-SWD routines

  3.    \verbatim

  4.    USBDM

  5.    Copyright (C) 2007  Peter O'Donoghue

  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.

  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.

  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.    \endverbatim

  18.    Change History
  19.    +==================================================================================================
  20.    | 21 Feb 2014 | Fixed unbalanced stack in swd_sendCommandWithWait()                      V4.10.6.30
  21.    | 10 Feb 2014 | Dramatically extended retry times to allow for slow clocks               V4.10.6.20
  22.    | 30 Aug 2012 | ARM-JTAG & ARM-SWD Changes                                               V4.9.5
  23.    +==================================================================================================
  24.    \endverbatim
  25. */

  26. #include "Common.h"
  27. #include "Configure.h"
  28. #include "Commands.h"
  29. #include "SWD.h"
  30. #include "Commands.h"
  31. #include "BDM.h"
  32. #include "BDM_CF.h"
  33. #include "CmdProcessing.h"
  34. #include "BDMCommon.h"
  35. #include "SPI.h"
  36. #include "TargetDefines.h"
  37. #include "SWD.h"
  38.   
  39. #if TARGET_CAPABILITY & CAP_ARM_SWD

  40. //! SPI Masks - Mask to enable SPI as master Tx
  41. #define SPIxC1_OFF      (SPIxC1_MSTR_MASK)     //!< SPI Masks - Mask to disable SPI
  42. #define SPIxC1_M_ON_TX  (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK|SPIxC1_CPHA_MASK|SPIxC1_SSOE_MASK|SPIxC1_LSBFE_MASK)
  43. #define SPIxC1_M_ON_RX  (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK)                   //!< SPI Masks - Mask to enable SPI as master Tx
  44. #define SPIxC2_M_8      (0)                                                                   //!< SPI Masks - 8-bit mode
  45. #define SPIxC2_M_16     (SPIxC2_SPIMODE_MASK)                                                 //!< SPI Masks - 8-bit mode

  46. // Can't use enumerations in assembly code
  47. #define BDM_RC_OKx                 (0)
  48. #define BDM_RC_NO_CONNECTIONx      (5)
  49. #define BDM_RC_ACK_TIMEOUTx        (30)
  50. #define BDM_RC_ARM_PARITY_ERRORx   (51)
  51. #define BDM_RC_ARM_FAULT_ERRORx    (52)

  52. #define SWD_READ_IDCODE 0xA5 // (Park,Stop,Parity,A[32],R/W,AP/DP,Start) = 10100101

  53. // Masks for SWD_WR_DP_ABORT clear sticky
  54. #define SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3 0x1E

  55. // Masks for SWD_WR_DP_ABORT abort AP
  56. #define SWD_DP_ABORT_ABORT_AP_B3 0x01

  57. // Masks for SWD_RD_DP_STATUS
  58. #define SWD_RD_DP_STATUS_ANYERROR_B3 0xB2

  59. #pragma MESSAGE DISABLE C1404 // Disable warnings about missing return value
  60. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter

  61. //! Sets the SWD interface to an idle state
  62. //! RESET=3-state, SWCLK=High, SWDIO=3-state (SPI off)
  63. //!
  64. void swd_interfaceIdle(void) {
  65. #ifdef RESET_3STATE
  66.    RESET_3STATE();
  67. #endif   
  68.    SWD_3STATE();
  69.    SWCLK_HIGH();
  70.    SPIC1 = SPIxC1_OFF;
  71. }

  72. //! Initialise the SWD interface and sets it to an idle state
  73. //! RESET=3-state, SWCLK=High, SWDIO=3-state
  74. //!
  75. //! @note This includes once-off initialisation such as PUPs etc
  76. //!
  77. void swd_init(void) {
  78.    // 4 pins SWD_OUT, SWD_OUT_EN, SWCLK_OUT, SWCLK_OUT_EN
  79.    // Individually controlled PUPs
  80.    SWD_OUT_PER      = 1;     // Prevent float when disabled
  81.    SWD_OUT_EN_PER   = 1;     // Prevent drive when disabled
  82.    SWCLK_OUT_PER    = 1;     // Prevent float when disabled
  83.    SWCLK_OUT_EN_PER = 1;     // Prevent drive when disabled
  84.    
  85.    SWD_IN_DDR       = 0;  // Make input
  86.    SWD_IN_PER       = 1;  // Shouldn't be req. as external PUP for speed
  87.    
  88. #ifdef RESET_IN_DDR
  89.    RESET_IN_DDR     = 0;     // Make input
  90. #endif
  91. #ifdef RESET_IN_PER
  92.    RESET_IN_PER     = 1;     // Needed for input level translation to 5V
  93. #endif
  94. #ifdef RESET_OUT_PER
  95.    RESET_OUT_PER    = 1;     // Holds RESET_OUT inactive when unused
  96. #endif
  97.    (void)spi_setSpeed(0);
  98.    swd_interfaceIdle();
  99. }

  100. //!  Turns off the SWD interface
  101. //!
  102. //!  Depending upon settings, may leave target power on.
  103. //!
  104. void swd_off( void ) {
  105. #if ((HW_CAPABILITY & CAP_FLASH) != 0)
  106.    (void)bdmSetVpp(BDM_TARGET_VPP_OFF);
  107. #endif
  108.    if (!bdm_option.leaveTargetPowered) {
  109.       VDD_OFF();
  110.    }
  111.    swd_interfaceIdle();
  112.    SWCLK_DISABLE();
  113.    SWD_DISABLE();
  114.    RESET_DISABLE();
  115. }

  116. #define SWD_DATA1_CLK1 SWCLK_OUT_MASK|SWD_OUT_EN_MASK
  117. #define SWD_DATA0_CLK1 SWCLK_OUT_MASK|0

  118. //! Transmits 1 clock with SWDIO 3-state
  119. //!
  120. void swd_turnAround() {
  121.    asm {               
  122.       // 1 clock turn-around
  123.       mov    #SWD_OUT_MASK,DATA_PORT        // SWDIO=3-state,SWCLK=0
  124.       ldx    bitDelay                       // Low time delay
  125.       dbnzx  *-0                            // [4n fppp]
  126.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  127.       ldx    bitDelay                       // High time delay
  128.       dbnzx  *-0                            // [4n fppp]
  129.    }
  130. }

  131. //! Transmits 8-bits of idle (SDIO=0)
  132. //!
  133. void swd_txIdle8(void) {
  134.    asm {               
  135.      mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  136.      mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  137.      clr    DATA_PORT                      // Enable SWD drive
  138.      cmp    SPIxS                          // Dummy status read
  139.      clr    SPIxD                          // Tx data (=0)
  140.    L1:
  141.      brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Tx/Rx complete
  142.      lda    SPIxD                          // Discard rx data
  143.      mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  144.      clr    SPIC1                          // Disable SPI
  145.    }
  146. }

  147. #if (SWD_IN_BIT != 0)
  148. #error "SWD_IN must be bit #0"
  149. #endif
  150. #pragma MESSAGE DISABLE C5703  // Disable warnings about unused parameter
  151. //! SWD command phase
  152. //!
  153. //! Writes 8-bit command and receives 3-bit response
  154. //! It will retry on WAIT response a limited number of times
  155. //!
  156. //! @param command - 8-bit command to write to SWD (including parity!)
  157. //!
  158. //! @return \n
  159. //!    == \ref BDM_RC_OK              => Success        \n
  160. //!    == \ref BDM_RC_ARM_FAULT_ERROR => FAULT response from target \n
  161. //!    == \ref BDM_RC_ACK_TIMEOUT     => Excessive number of WAIT responses from target \n
  162. //!    == \ref BDM_RC_NO_CONNECTION   => Unexpected/no response from target
  163. //!
  164. //! @note A turn-around clock period will be added on error responses
  165. //!
  166. uint8_t swd_sendCommandWithWait(uint8_t command) {
  167.    asm {
  168.           sta    txTiming1                      // Save data (for retry)
  169.           ldx    #(2000/250)                    // Set up outer retry count

  170.    retry_outer:
  171.           pshx                                  // Save outer retry count
  172.       mov    #250,rxTiming1                 // Reset inner retry count

  173.    retry:
  174.    
  175.       // 8-bit Start|APnDP|R/W|Parity|Stop|Park
  176.       lda    txTiming1                      // Get Tx data
  177.       mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  178.       mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  179.       clr    DATA_PORT                      // Enable SWD drive
  180.       cmp    SPIxS                          // Dummy status read
  181.       sta    SPIxD                          // Tx data
  182.    L1:
  183.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Tx/Rx complete
  184.       ldx    SPIxD                          // Discard rx data
  185.       SWD_3STATE_ASM                        // SWD=3-state
  186.       clr    SPIC1                          // Disable SPI

  187.       // 1 clock turn-around
  188.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  189.       ldx    bitDelay                       // Low time delay
  190.       dbnzx  *-0                            // [4n fppp]
  191.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  192.       ldx    bitDelay                       // High time delay
  193.       dbnzx  *-0                            // [4n fppp]
  194.       
  195.       // 1st bit ACK
  196.       clra                                  // Clear initial data value
  197.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  198.       ldx    bitDelay                       // Low time delay
  199.       dbnzx  *-0                            // [4n fppp]
  200.       ldx    DATA_PORT                      // Capture data before rising edge
  201.       rorx
  202.       rora
  203.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  204.       ldx    bitDelay                       // High time delay
  205.       dbnzx  *-0                            // [4n fppp]

  206.       // 2nd bit ACK
  207.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  208.       ldx    bitDelay                       // Low time delay
  209.       dbnzx  *-0                            // [4n fppp]
  210.       ldx    DATA_PORT                      // Capture data before rising edge
  211.       rorx
  212.       rora
  213.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  214.       ldx    bitDelay                       // High time delay
  215.       dbnzx  *-0                            // [4n fppp]

  216.       // 3rd bit ACK
  217.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  218.       ldx    bitDelay                       // Low time delay
  219.       dbnzx  *-0                            // [4n fppp]
  220.       ldx    DATA_PORT
  221.       rorx
  222.       rora      
  223.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  224.       ldx    bitDelay                       // High time delay
  225.       dbnzx  *-0                            // [4n fppp]
  226.       
  227.       tax
  228.       lda    #BDM_RC_OKx
  229.       cbeqx  #SWD_ACK_OK,balanceStack
  230.       
  231.       // Do turn-around clock on anything other than ACK_OK response
  232.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  233.       lda    bitDelay                       // Low time delay
  234.       dbnza  *-0                            // [4n fppp]
  235.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  236.       lda    bitDelay                       // High time delay
  237.       dbnza  *-0                            // [4n fppp]
  238.       
  239.       // Check for wait response
  240.       cpx    #SWD_ACK_WAIT                  // Wait response?
  241.       bne    identifyError                  // No - exit with other error
  242.       
  243.       // Check for wait timeout
  244.       dbnz   rxTiming1,retry                // Retry limit reached
  245.       pulx
  246.       dbnzx  retry_outer   

  247.       lda    #BDM_RC_ACK_TIMEOUTx           // Too many retries
  248.       bra    done                           // Return error (stack already balanced)
  249.       
  250.    identifyError:
  251.       lda    #BDM_RC_ARM_FAULT_ERRORx       // Identify error
  252.       cbeqx  #SWD_ACK_FAULT,balanceStack
  253.       lda    #BDM_RC_NO_CONNECTIONx
  254.       
  255.    balanceStack:
  256.       pulx                                  // Balance stack
  257.       
  258.    done:
  259.    }
  260. }

  261. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  262. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  263. //! Transmits 32-bit value
  264. //!
  265. //! Sequence as follows:
  266. //!   - 1-clock turn-around
  267. //!   - 32-bit data value
  268. //!   - 1-bit parity
  269. //!   - 8-bit idle
  270. //!
  271. //! @param data - ptr to 32-bit data to Tx
  272. //!
  273. static void swd_tx32(const uint8_t *data) {
  274.    asm {
  275.       // 1 clock turn-around
  276.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  277.       lda    bitDelay                       // Low time delay
  278.       dbnza  *-0                            // [4n fppp]
  279.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1

  280.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  281.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  282.       clr    DATA_PORT                      // Enable SWD drive

  283.       cmp    SPIxS                          // Dummy status read
  284.       
  285.       lda    3,x                            // Start Tx 1st & 2nd bytes
  286.       sta    SPIxDL                        
  287.       lda    2,x
  288.       sta    SPIxDH                        
  289.       lda    0,x                            // Do byte-wide parity
  290.       eor    1,x
  291.       eor    2,x
  292.       eor    3,x
  293.       ldhx   0,x                            // Get 3rd & 4th bytes
  294.   L1:
  295.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until previous Tx/Rx complete
  296.       cphx   SPIxD16                        // Discard read data
  297.       sthx   SPIxD16                        // Tx 3rd & 4th bytes
  298.       
  299.       // Calculate nibble parity
  300.       psha             // [2]
  301.       nsa              // [1]
  302.       eor    1,sp      // [4]
  303.       ais    #1        // [2]
  304.       
  305.       // Calculate final parity
  306.       tax              // [1]
  307.       clra             // [1]
  308.       rorx             // [1]
  309.       adc    #0        // [2]
  310.       rorx             // [1]
  311.       adc    #0        // [2]
  312.       rorx             // [1]
  313.       adc    #0        // [2]
  314.       rorx             // [1]
  315.       adc    #0        // [2]
  316.       //parity in A.0

  317.   L2:
  318.      brclr  SPIS_SPRF_BIT,SPIxS,L2         // Wait until previous Tx/Rx complete
  319.      ldhx   SPIxD16                        // Discard read data
  320.       
  321. #if SWD_OUT_BIT >= 1                        // move to SWD_OUT position
  322.       lsla
  323. #endif
  324. #if SWD_OUT_BIT == 2
  325.       lsla
  326. #else
  327. #error Fix this code
  328. #endif
  329.       and    #SWD_OUT_MASK                  // SWD=p, SWCLK=0
  330.       sta    DATA_PORT                      // Set up - no effect yet
  331.       ldx    bitDelay                       // Low time delay
  332.       clr    SPIC1                          // Disable SPI,  
  333.       dbnzx  *-0                            // [4n fppp]
  334.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWD=p, SWCLK=1

  335.       // Start Tx of 8-bit idle
  336.      mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  337.      mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  338.      clr    DATA_PORT                      // Enable SWD drive
  339.      cmp    SPIxS                          // Dummy status read
  340.      clr    SPIxD                          // Tx data (=0)

  341.      // Wait for Idle Tx to complete
  342.    L3:
  343.      brclr  SPIS_SPRF_BIT,SPIxS,L3         // Wait until Tx/Rx complete
  344.      cmp    SPIxD                          // Discard rx data
  345.      mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  346.      clr    SPIC1                          // Disable SPI
  347.       rts
  348.    }
  349. }
  350. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  351. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  352. //! Receives a 32-bit value with parity at end (33 total)
  353. //!
  354. //! Sequence as follows:
  355. //!   - 32-bit data value
  356. //!   - 1-bit parity
  357. //!   - 8-bit idle
  358. //!
  359. //! @param data - ptr to buffer for Rx data
  360. //!
  361. //! @return BDM_RC_OK \n
  362. //!         BDM_RC_ARM_PARITY_ERROR
  363. //!
  364. static uint8_t swd_rx32(uint8_t *data) {
  365. #define SPIS_SPTEF_BIT (5)
  366. #define SPIS_SPRF_BIT  (7)

  367.    asm {
  368.       SWD_3STATE_ASM                        // SWD=3-state
  369.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  370.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  371.       cmp    SPIxS                          // Dummy status read

  372.       sthx   SPIxD16                        // Tx dummy/Rx                        
  373.   L1:
  374.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Rx complete
  375.       lda    SPIxDH                         // Save data
  376.       sta    2,x
  377.       lda    SPIxDL
  378.       sta    3,x
  379.       sthx   SPIxD16                        // Tx dummy/Rx                        
  380.   L2:
  381.       brclr  SPIS_SPRF_BIT,SPIxS,L2         // Wait until Rx complete
  382.       lda    SPIxDH                         // Save data
  383.       sta    0,x
  384.       lda    SPIxDL
  385.       sta    1,x

  386.       bclr   SWCLK_OUT_BIT,DATA_PORT        // Setup for SWCLK=0
  387.       clr    SPIC1                          // Disable SPI (SWCLK=0)

  388.       // Parity bit
  389.       lda    bitDelay                       // Low time delay
  390.       dbnza  *-0                            // [4n fppp]
  391.       lda    DATA_PORT                      // Capture data before rising clock edge
  392.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  393.       and    #SWD_IN_MASK                   // Convert parity to byte width
  394.       // Single Parity bit remains - position is unimportant

  395.       // Start Tx of 8-bit idle
  396.       mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  397.       mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  398.       clr    DATA_PORT                      // Enable SWD drive
  399.       cmp    SPIxS                          // Dummy status read
  400.       clr    SPIxD                          // Tx data (=0)

  401.       // Do parity calculation
  402.       eor    0,x                            // Do byte-wide parity on data & parity bit
  403.       eor    1,x
  404.       eor    2,x
  405.       eor    3,x

  406.       ldx    bitDelay                       // High time delay
  407.       dbnzx  *-0                            // [4n fppp]

  408.       // Calculate nibble parity
  409.       psha             // [2]
  410.       nsa              // [1]
  411.       eor    1,sp      // [4]
  412.       ais    #1        // [2]

  413.       // Calculate final parity
  414.       tax              // [1]
  415.       clra             // [1]
  416.       rorx             // [1]
  417.       adc    #0        // [2]
  418.       rorx             // [1]
  419.       adc    #0        // [2]
  420.       rorx             // [1]
  421.       adc    #0        // [2]
  422.       rorx             // [1]
  423.       adc    #0        // [2]
  424.       and    #1
  425.       // Parity in A.0 - should be 0
  426.       beq    okExit
  427.       lda    #BDM_RC_ARM_PARITY_ERRORx
  428.    okExit:

  429.       // Wait for Idle Tx to complete
  430.    L3:
  431.       brclr  SPIS_SPRF_BIT,SPIxS,L3         // Wait until Tx/Rx complete
  432.       cmp    SPIxD                          // Discard rx data
  433.       mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  434.       clr    SPIC1                          // Disable SPI
  435.       rts
  436.    }
  437. }
  438. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  439. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  440. //! Switches interface to SWD
  441. //!
  442. //! Sequence as follows:
  443. //!  - 64-bit sequence of 1's
  444. //!  - 8-bit magic number 0xE79E
  445. //!  - 64-bit sequence of 1's
  446. //!
  447. //! @note Interface is reset even if already in SWD mode so IDCODE must be read
  448. //!       to enable interface
  449. //!
  450. static void swd_JTAGtoSWD(void) {
  451.    asm {
  452.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  453.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  454.       clr    DATA_PORT                      // Enable SWD drive
  455.       cmp    SPIxS                          // Dummy status read
  456.       
  457.       bsr    txOnes                         // Send 64 clocks
  458.       ldhx   #0xE79E                        // Send magic #
  459.       sthx   SPIxD16                        
  460.   L5:
  461.       brclr  SPIS_SPTEF_BIT,SPIxS,L5        // Wait until Tx buffer empty
  462.       bsr    txOnes                         // Send 64 clocks
  463.   L6:
  464.       brclr  SPIS_SPTEF_BIT,SPIxS,L6                   // Wait until Tx buffer empty
  465.       ldhx   SPIxD16                                   // Discard last data
  466.       mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  467.   L7:
  468.       brclr  SPIS_SPRF_BIT,SPIxS,L7                    // Wait until Tx complete
  469.       ldhx   SPIxD16                                   // Discard rx data
  470.       clr    SPIC1                                     // Disable SPI (SWCLK=1)
  471.       rts
  472.       
  473.   txOnes:
  474.       ldhx   #0xFFFF                        // Tx 64 bits with '1'
  475.       sthx   SPIxD16                        
  476.   L1:
  477.       brclr  SPIS_SPTEF_BIT,SPIxS,L1        // Wait until Tx buffer empty
  478.       sthx   SPIxD16                        
  479.   L2:
  480.       brclr  SPIS_SPTEF_BIT,SPIxS,L2        // Wait until Tx buffer empty
  481.       sthx   SPIxD16                        
  482.   L3:
  483.       brclr  SPIS_SPTEF_BIT,SPIxS,L3        // Wait until Tx buffer empty
  484.       sthx   SPIxD16                        
  485.   L4:
  486.       brclr  SPIS_SPTEF_BIT,SPIxS,L4        // Wait until Tx buffer empty
  487.       rts
  488.    }
  489. }
  490. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  491. //! SWD - Try to connect to the target
  492. //!
  493. //! This will do the following:
  494. //! - Switch the interface to SWD mode
  495. //! - Read IDCODE
  496. //!
  497. //! @return \n
  498. //!    == \ref BDM_RC_OK              => Success        \n
  499. //!    == \ref BDM_RC_NO_CONNECTION   => Unexpected/no response from target
  500. //!
  501. uint8_t swd_connect(void) {
  502.    uint8_t buff[4];        
  503.    
  504.    swd_JTAGtoSWD();
  505.    swd_txIdle8();
  506.      
  507.    // Target must respond to read IDCODE immediately
  508.    return swd_readReg(SWD_READ_IDCODE, buff);
  509. }

  510. //! Read ARM-SWD DP & AP register
  511. //!
  512. //! @param command - SWD command byte to select register etc.
  513. //! @param data    - buffer for 32-bit value read
  514. //!
  515. //! @return \n
  516. //!    == \ref BDM_RC_OK               => Success        \n
  517. //!    == \ref BDM_RC_ARM_FAULT_ERROR  => FAULT response from target \n
  518. //!    == \ref BDM_RC_ACK_TIMEOUT      => Excessive number of WAIT responses from target \n
  519. //!    == \ref BDM_RC_NO_CONNECTION    => Unexpected/no response from target \n
  520. //!    == \ref BDM_RC_ARM_PARITY_ERROR => Parity error on data read
  521. //!
  522. //! @note Action and Data returned depends on register (some responses are pipelined)\n
  523. //!   SWD_RD_DP_IDCODE - Value from IDCODE reg \n
  524. //!   SWD_RD_DP_STATUS - Value from STATUS reg \n
  525. //!   SWD_RD_DP_RESEND - LAST value read (AP read or DP-RDBUFF), FAULT on sticky error    \n
  526. //!   SWD_RD_DP_RDBUFF - Value from last AP read and clear READOK flag in STRL/STAT, FAULT on sticky error \n
  527. //!   SWD_RD_AP_REGx   - Value from last AP read, clear READOK flag in STRL/STAT and INITIATE next AP read, FAULT on sticky error
  528. //!
  529. uint8_t swd_readReg(uint8_t command, uint8_t *data) {
  530.    uint8_t rc = swd_sendCommandWithWait(command);
  531.    if (rc != BDM_RC_OK) {
  532.       return rc;
  533.    }
  534.    return swd_rx32(data);
  535. }

  536. //! Write ARM-SWD DP & AP register
  537. //!
  538. //! @param command - SWD command byte to select register etc.
  539. //! @param data    - buffer containing 32-bit value to write
  540. //!
  541. //! @return \n
  542. //!    == \ref BDM_RC_OK               => Success        \n
  543. //!    == \ref BDM_RC_ARM_FAULT_ERROR  => FAULT response from target \n
  544. //!    == \ref BDM_RC_ACK_TIMEOUT      => Excessive number of WAIT responses from target \n
  545. //!    == \ref BDM_RC_NO_CONNECTION    => Unexpected/no response from target
  546. //!
  547. //! @note Action depends on register (some responses are pipelined)\n
  548. //!   SWD_WR_DP_ABORT   - Write value to ABORT register (accepted) \n
  549. //!   SWD_WR_DP_CONTROL - Write value to CONTROL register (may be pending), FAULT on sticky error. \n
  550. //!   SWD_WR_DP_SELECT  - Write value to SELECT register (may be pending), FAULT on sticky error. \n
  551. //!   SWD_WR_AP_REGx    - Write to AP register.  May initiate action e.g. memory access.  Result is pending, FAULT on sticky error.
  552. //!
  553. uint8_t swd_writeReg(uint8_t command, const uint8_t *data) {
  554.    uint8_t rc = swd_sendCommandWithWait(command);
  555.    if (rc != BDM_RC_OK) {
  556.       return rc;
  557.    }
  558.    swd_tx32(data);
  559.    return rc;
  560. }

  561. //! Write register of Access Port
  562. //!
  563. //! @param 16-bit address \n
  564. //!    A[15:8]  => DP-AP-SELECT[31:24] (AP # Select) \n
  565. //!    A[7:4]   => DP-AP-SELECT[7:4]   (Bank select within AP) \n
  566. //!    A[3:2]   => APACC[3:2]          (Register select within bank)
  567. //! @param buff \n
  568. //!   - [1..4]  =>  32-bit register value
  569. //!
  570. //! @return
  571. //!  == \ref BDM_RC_OK => success
  572. //!
  573. //! @note - Access is completed before return
  574. //!
  575. uint8_t swd_writeAPReg(const uint8_t *address, const uint8_t *buff) {
  576.    static const uint8_t writeAP[] = {SWD_WR_AP_REG0,   SWD_WR_AP_REG1,    SWD_WR_AP_REG2,   SWD_WR_AP_REG3};
  577.    uint8_t rc;
  578.    uint8_t regNo = writeAP[(address[1]&0xC)>>2];
  579.    uint8_t selectData[4];
  580.    selectData[0] = address[0];
  581.    selectData[1] = 0;
  582.    selectData[2] = 0;
  583.    selectData[3] = address[1]&0xF0;
  584.    
  585.    // Set up SELECT register for AP access
  586.    rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
  587.    if (rc != BDM_RC_OK) {
  588.       return rc;
  589.    }
  590.    // Initiate write to AP register
  591.    rc = swd_writeReg(regNo, buff);
  592.    if (rc != BDM_RC_OK) {
  593.       return rc;
  594.    }
  595.    // Read from READBUFF register to allow stall/status response
  596.    return swd_readReg(SWD_RD_DP_RDBUFF, selectData);
  597. }

  598. //! Read register of Access Port
  599. //!
  600. //! @param 16-bit address \n
  601. //!    A[15:8]  => DP-AP-SELECT[31:24] (AP # Select) \n
  602. //!    A[7:4]   => DP-AP-SELECT[7:4]   (Bank select within AP) \n
  603. //!    A[3:2]   => APACC[3:2]          (Register select within bank)
  604. //! @param buff \n
  605. //!   - [1..4]  =>  32-bit register value
  606. //!
  607. //! @return
  608. //!  == \ref BDM_RC_OK => success
  609. //!
  610. //! @note - Access is completed before return
  611. //!
  612. uint8_t swd_readAPReg(const uint8_t *address, uint8_t *buff) {
  613.    static const uint8_t readAP[]  = {SWD_RD_AP_REG0,   SWD_RD_AP_REG1,    SWD_RD_AP_REG2,   SWD_RD_AP_REG3};
  614.    uint8_t rc;
  615.    uint8_t regNo = readAP[(address[1]&0xC)>>2];
  616.    uint8_t selectData[4];
  617.    selectData[0] = address[0];
  618.    selectData[1] = 0;
  619.    selectData[2] = 0;
  620.    selectData[3] = address[1]&0xF0;

  621.    // Set up SELECT register for AP access
  622.    rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
  623.    if (rc != BDM_RC_OK) {
  624.      return rc;
  625.    }
  626.    // Initiate read from AP register (dummy data)
  627.    rc = swd_readReg(regNo, buff);
  628.    if (rc != BDM_RC_OK) {
  629.      return rc;           
  630.    }
  631.    // Read from READBUFF register
  632.    return swd_readReg(SWD_RD_DP_RDBUFF, buff);
  633. }

  634. //! ARM-SWD - clear sticky bits
  635. //!
  636. //! @return error code
  637. //!
  638. uint8_t swd_clearStickyError(void) {
  639.    static const uint8_t swdClearErrors[4] = {0,0,0,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3};
  640.    return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
  641. }

  642. //! ARM-SWD - clear sticky bits and abort AP transactions
  643. //!
  644. //! @return error code
  645. //!
  646. uint8_t swd_abortAP(void) {
  647.    static const uint8_t swdClearErrors[4] =
  648.       {0,0,0,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3|SWD_DP_ABORT_ABORT_AP_B3};
  649.    return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
  650. }

  651. uint8_t swd_test(void) {
  652.    return swd_connect();
  653. //   swd_JTAGtoSWD();
  654. //   return BDM_RC_OK;
  655. //   return swd_connect();
  656. }
  657. #endif // HW_CAPABILITY && CAP_SWD_HW
复制代码


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-25 16:19:31 | 显示全部楼层
abbott.yang 发表于 2015-8-21 16:12
观察了SWD波形,想用SPI的8字节数据去套这个协议。。可惜都不是8字节对齐,中间还有有接收ACK。。。shang ...

JLink 大概用到了 TIMER + SPI + DMA, 没有频繁的中断。

出0入0汤圆

发表于 2015-8-25 21:04:04 来自手机 | 显示全部楼层
如果不是非要脱电脑用 应该还是jlink dll加界面最省事通用

出0入0汤圆

发表于 2015-8-25 21:06:57 来自手机 | 显示全部楼层
abbott.yang 发表于 2015-8-21 16:12
观察了SWD波形,想用SPI的8字节数据去套这个协议。。可惜都不是8字节对齐,中间还有有接收ACK。。。shang ...

不知道jlink是怎么做的 能到10m

出0入0汤圆

发表于 2015-8-26 01:05:36 | 显示全部楼层
都支持些什么芯片呀。

出0入0汤圆

发表于 2015-8-26 07:55:21 | 显示全部楼层
支持,开发新产品成长才会快

出0入0汤圆

发表于 2015-8-26 13:43:17 | 显示全部楼层
支持,这个可以学习学习的。

出0入0汤圆

发表于 2015-8-28 18:07:26 | 显示全部楼层
目前进度如何?是否打算开源呢?

出0入0汤圆

发表于 2015-8-28 18:39:01 | 显示全部楼层
最近正好有需求,持续关注楼主进展

出0入0汤圆

 楼主| 发表于 2015-8-28 19:54:48 | 显示全部楼层
shangdawei 发表于 2015-8-22 09:50
>> 正好是56个时钟 ?

我用的V8,用jflash,点connect的时候,是56个时钟!
项目目前还是一周前差不多。我在外面,其他的同事在做其他功能部分。
让大家失望了。。。。。。。。

出0入0汤圆

发表于 2015-8-28 20:17:13 | 显示全部楼层
abbott.yang 发表于 2015-8-28 19:54
我用的V8,用jflash,点connect的时候,是56个时钟!
项目目前还是一周前差不多。我在外面,其他的同事在 ...

看来V9和V8的实现方法是不一样的。

出0入0汤圆

发表于 2015-8-28 20:19:30 | 显示全部楼层
本帖最后由 shangdawei 于 2015-8-28 21:27 编辑

KT-link Interface



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-30 09:51:06 | 显示全部楼层
LPC-Link2_v3_Rev_A1





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-8-31 12:25:33 | 显示全部楼层
半仙 发表于 2015-8-28 18:39
最近正好有需求,持续关注楼主进展

我有SWD脱机下载器成品,如果需要可以联系我

出0入0汤圆

 楼主| 发表于 2015-9-2 19:37:28 | 显示全部楼层
shangdawei 发表于 2015-8-28 18:07
目前进度如何?是否打算开源呢?

读各种ID,寄存器,读写RAM,读Flash都没问题了。
写Flash还是写不进去。。。虽然SWD给出的ACK是正确的,但是写完再读出来还是写之前的,擦除再写也一样,在查原因,写动作没有任何作用,尝试是否和flash锁定有关系。
寄存器有的写不进去,xpr,pc,lr写不进去。也是swd提示ACK_OK,读出来还是和写进去之前一样,原因待查。
等做完,确认各种动作都正常就开源吧,不过因为职业原因,只会给出SWD的操作函数源代码。这其实没多大意义,参考CMSIS—DAP和ARM以及CortexM3文档,应该难度不大的。
要的发消息给我吧,留下信箱,我还是新手上路,消息,加好友都不行,杯具了!!!

出0入0汤圆

发表于 2015-9-2 20:09:34 | 显示全部楼层
abbott.yang 发表于 2015-9-2 19:37
读各种ID,寄存器,读写RAM,读Flash都没问题了。
写Flash还是写不进去。。。虽然SWD给出的ACK是正确的, ...


论坛元老也加不了好友的。。。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-9-3 15:20:03 | 显示全部楼层
观望制作记录。

出0入0汤圆

发表于 2015-9-4 20:48:05 | 显示全部楼层
ARM® DSTREAM™ System and Interface Design Reference




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2015-9-5 13:31:37 | 显示全部楼层
abbott.yang 发表于 2015-9-2 19:37
读各种ID,寄存器,读写RAM,读Flash都没问题了。
写Flash还是写不进去。。。虽然SWD给出的ACK是正确的, ...

先擦除,然后读出来是不是已经擦除了。
写FLASH的时候要注意FLASH延迟。
我当时测STM32F030的时候FLASH的传输方式未用Packet模式,STM32F103是用的Packet模式。
迫于生计,以前做的离线下载器搞好了就给生产用了,并没花太多时间再继续深入研究,也只是搞了点皮毛,希望对你能有帮助。

出0入0汤圆

 楼主| 发表于 2015-9-5 17:04:43 | 显示全部楼层
czdavid 发表于 2015-9-5 13:31
先擦除,然后读出来是不是已经擦除了。
写FLASH的时候要注意FLASH延迟。
我当时测STM32F030的时候FLASH的 ...

这个是我自己疏忽,没有unclok flash所致。写几个pc。xpr等写不进去也是犯低级错误。往里写了奇数。。。
然后。。。flash操作函数是直接拷贝的stm32库函数。
只是把寄存器读写全换成swd读写。这样效率很低。当然擦除flash可以直接用swd操作,没啥影响。但是大数据编程的时候,时间都浪费在swd 波形传输上了,还是直接download程序到ram执行最快。
大家可以看看Keil,它也是download程序到ram去弄的,在keil程序目录下,有个flash文件夹,里面就是每个芯片都有一段flash操作程序。

出0入0汤圆

发表于 2015-9-5 21:43:56 来自手机 | 显示全部楼层
abbott.yang 发表于 2015-9-5 17:04
这个是我自己疏忽,没有unclok flash所致。写几个pc。xpr等写不进去也是犯低级错误。往里写了奇数。。。
...

如果不是非要脱机不可 不如用jlink做个上位机通用简单

出0入0汤圆

发表于 2015-9-5 22:12:37 来自手机 | 显示全部楼层
abbott.yang 发表于 2015-9-5 17:04
这个是我自己疏忽,没有unclok flash所致。写几个pc。xpr等写不进去也是犯低级错误。往里写了奇数。。。
...

这样可以直接参考KEIL的算法吧。

出0入0汤圆

 楼主| 发表于 2015-9-7 14:36:18 | 显示全部楼层
程序在内部ram中运行的速度,只有在内部flash内运行的一半左右。。

出20入0汤圆

发表于 2015-9-7 16:03:30 | 显示全部楼层
  此类需求好像已经有现成产品卖了。

出0入0汤圆

发表于 2015-9-16 14:37:23 | 显示全部楼层
不知道能不能一带多的脱机升级方案,不写bootloader的情况下。

出0入0汤圆

发表于 2015-9-17 09:34:44 | 显示全部楼层
收藏下!

出0入0汤圆

发表于 2015-10-28 20:06:48 | 显示全部楼层
Mark,留名~

出0入0汤圆

发表于 2015-10-28 22:21:53 | 显示全部楼层
火前留名

出0入70汤圆

发表于 2015-11-16 23:15:09 | 显示全部楼层
看得出来 shangdawei 收集研究了不少资料

出0入0汤圆

发表于 2015-12-6 23:11:26 | 显示全部楼层
楼主,你好,我也在研究SWD的协议,现在读DP-ID和AP-ID已经可以了,读写目标板的普通寄存器时,只有几个寄存器可以读,其他的读取时的ack不正确,能不能请教下,QQ853678594,谢谢~

出0入0汤圆

发表于 2016-2-5 14:15:27 | 显示全部楼层
看来通过swd个性定制的下载升级器还是有需求的,可以做成加密下载升级后自宫,还有就是生产上的bootload批量下载。也在研究中,想做个专用的bootload脱机下载器,

出0入0汤圆

发表于 2016-2-12 19:00:45 | 显示全部楼层
基本成功,用的JLink ARM-OB硬件通过swd直接控制FALSH寄存器操作,目标板也是stm32f103c8,没有做速度上的优化,用IO口模拟操作,全部写完后再校验的话,速度比用J-FLASH慢一半左右,只烧写不校验的话速度与J-FLASH基本一样,还没法擦除写保护后下载,还在研究中。想做个下载个小时程序到RAM中运行烧写的,有时间再研究下。这个帖子中shangdawei给的资料帮助不小,参考后做的。里边代码不少可以直接修改过来用。

出0入34汤圆

发表于 2016-2-13 15:51:40 | 显示全部楼层
abbott.yang 发表于 2015-9-2 19:37
读各种ID,寄存器,读写RAM,读Flash都没问题了。
写Flash还是写不进去。。。虽然SWD给出的ACK是正确的, ...

告知楼主在此坛加好友的方法,楼主您用您于此坛的 ID 登入后再购买一个新的 ID 号,这新的 ID 号已默认就是与您是已加好友的了。
当然,楼主您也可以取消此好友的连接关系!

出0入0汤圆

发表于 2016-2-14 21:10:08 | 显示全部楼层
tang0571 发表于 2015-8-21 15:03
sw离线烧录,留名,有时间自己整一个,通用的离线烧录器局限性太多!

确实是这样,我也期望能根据公司的需求DIY一个专属的,不需要支持那么多器件,只要能满足自己需求的就是最好的!!!

出0入0汤圆

发表于 2016-3-3 13:56:39 | 显示全部楼层
LZ,能给个完整的工程吗?现在正在弄SWD烧写器

出0入0汤圆

发表于 2016-3-3 17:12:27 | 显示全部楼层
收藏下!!!

出0入0汤圆

发表于 2016-3-29 17:58:41 | 显示全部楼层
本帖最后由 tgwfcc 于 2016-3-29 18:03 编辑
happyliu 发表于 2016-2-12 19:00
基本成功,用的JLink ARM-OB硬件通过swd直接控制FALSH寄存器操作,目标板也是stm32f103c8,没有做速度上的优 ...


你好,请教下,我现在能读写FLASH控制寄存器,但是往FLASH某一个地址写数据的时候,ACK出错,这个是什么原因呢?
比如往0x08070000 写一个字节0x11,写完后,读0x08070000,ACK出错。
谢谢

出0入0汤圆

发表于 2016-3-29 18:11:00 | 显示全部楼层
学习了,mark一下

出0入0汤圆

发表于 2016-3-29 18:12:58 | 显示全部楼层
学习了一下脱机下载,mark

出0入8汤圆

发表于 2016-5-20 14:28:09 | 显示全部楼层
这里好复杂,学习一下

出0入0汤圆

发表于 2016-6-20 10:37:22 | 显示全部楼层
czdavid 发表于 2015-9-5 13:31
先擦除,然后读出来是不是已经擦除了。
写FLASH的时候要注意FLASH延迟。
我当时测STM32F030的时候FLASH的 ...

stm32 swd离线下载,到了控制寄存器编程到flash那里不懂怎么搞,可以指导一下吗?

出0入0汤圆

发表于 2016-8-8 16:46:51 | 显示全部楼层
好东西,资料很全

出0入0汤圆

发表于 2016-8-8 17:34:59 | 显示全部楼层
Free_man 发表于 2016-6-20 10:37
stm32 swd离线下载,到了控制寄存器编程到flash那里不懂怎么搞,可以指导一下吗? ...

这个最简单就是直接操作 flash 寄存器,flash 的速度我自己的比较是
比用程序来刷慢 1 倍左右所以也没有差很多。我用的 swd 速度是 3M
左右。

flash 寄存器操作 ACK 经常有 wait 出现要正确处理。

你直接操作 flash 寄存器成功以后再考虑用程序加载。
程序那个调试建议些个单布调试打印每一步的寄存器内容,
包括将要执行的指令。

然后你就可以从调试记录里面看出来你加载的程序哪
一步出问题了。

出0入0汤圆

发表于 2016-8-10 10:36:43 | 显示全部楼层
helislayer 发表于 2016-8-8 17:34
这个最简单就是直接操作 flash 寄存器,flash 的速度我自己的比较是
比用程序来刷慢 1 倍左右所以也没有 ...

好的,谢谢!

出0入0汤圆

发表于 2016-11-3 18:39:50 | 显示全部楼层
我现在可以用swd直接操作flash的寄存器进行擦出操作,但擦除后怎么给写数据啊,我用swd在相应的地址写数据后,读FLASH_SR寄存器发现一只处于BUSY状态。之前写flash用的固件库,里面擦出页后,半字半字的写,不知到SWD里怎么写呀

出0入0汤圆

发表于 2016-11-5 23:08:04 | 显示全部楼层
太帅了,这种做法我觉得比较好,什么时候分享出来看看

出0入0汤圆

发表于 2017-4-13 19:35:56 | 显示全部楼层
模拟SWD, JTAG ,太好了,谢谢

出0入0汤圆

发表于 2017-8-4 20:42:28 | 显示全部楼层
good job

出0入0汤圆

发表于 2017-8-4 21:49:05 | 显示全部楼层
学习了,mark一下

出0入0汤圆

发表于 2017-8-7 12:02:54 | 显示全部楼层
正在学习做这个,顶一个

出0入0汤圆

发表于 2017-8-10 14:58:54 | 显示全部楼层
jinchenaquarius 发表于 2017-8-7 12:02
正在学习做这个,顶一个

你的进度怎样了呢?这几天也在看,云里雾里...

出0入0汤圆

发表于 2017-8-10 15:05:52 来自手机 | 显示全部楼层
我搞定了,嘿嘿

出0入0汤圆

发表于 2017-8-10 15:54:00 | 显示全部楼层

能分享一下经验吗?

出0入0汤圆

发表于 2017-8-10 15:55:08 | 显示全部楼层
aduecho 发表于 2017-8-10 14:58
你的进度怎样了呢?这几天也在看,云里雾里...

不是很好搞,先从模拟io做起吧,在转到硬件SPI上

出0入0汤圆

发表于 2017-10-19 18:29:54 | 显示全部楼层
你好,请问进展怎么样了,能否发我一份SWD的操作文件,pjf102@163.com    谢谢

出0入0汤圆

发表于 2017-12-19 13:20:53 | 显示全部楼层
。。。。。。。

出0入0汤圆

发表于 2018-6-3 13:32:52 | 显示全部楼层
像STM32在指定的地址写入要编程的半字(2字节),但是DAP操作好像都要4字节,不知道那部分写flash是怎么操作的

出0入0汤圆

发表于 2018-6-7 10:10:24 | 显示全部楼层
楼主的做出来了吗?

出30入54汤圆

发表于 2018-9-14 21:19:02 | 显示全部楼层
收藏收藏,日后看看

出0入0汤圆

发表于 2018-9-15 11:37:29 来自手机 | 显示全部楼层
gyd0317 发表于 2018-6-3 13:32
像STM32在指定的地址写入要编程的半字(2字节),但是DAP操作好像都要4字节,不知道那部分写flash是怎么操作 ...

可以设置宽度

出0入0汤圆

发表于 2019-11-8 01:24:31 | 显示全部楼层
666666666666666666666666666666666666

出0入0汤圆

发表于 2021-7-13 11:10:30 | 显示全部楼层
为什么我读的ID始终不对

出0入0汤圆

发表于 2021-7-13 13:55:24 | 显示全部楼层
为什么我的ID读出来始终不对

出0入0汤圆

发表于 2021-7-13 21:18:00 来自手机 | 显示全部楼层
songguoliang 发表于 2021-7-13 13:55
为什么我的ID读出来始终不对

你猜



回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 16:23

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表