Difference between revisions of "DCC"

From SEGGER Wiki
Jump to: navigation, search
m
(Source code)
 
(9 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
[[Category:Knowledge Base]]
 
[[Category:Knowledge Base]]
   
The Debug Communication Channel (DCC) is a simply communication mechanism which allows the debug probe to communicate
+
The Debug Communication Channel (DCC) is a simple communication mechanism which allows the debug probe to communicate
with the program running on the target processor, using the debug interface (typically JTAG).
+
with the program running on the target processor, using the debug interface (typically [[JTAG]], Scan chain 2).
 
In contrast to [[Semihosting]], which halts the target CPU, it allows communication with the
 
In contrast to [[Semihosting]], which halts the target CPU, it allows communication with the
 
processor without halting the program.
 
processor without halting the program.
Line 14: Line 14:
 
* A 32-bit read register, used to transfer data down from debugger to the target, so read from target, written via debug interface
 
* A 32-bit read register, used to transfer data down from debugger to the target, so read from target, written via debug interface
 
* A 32-bit write register, used to transfer data up to the debugger, so written from target
 
* A 32-bit write register, used to transfer data up to the debugger, so written from target
* A 32-bit control register (Where two bits are used, a 1 indicating that data is available). Set on write
+
* A 32-bit control register, with only 2 bits being used:
  +
<br>R - 1 if there is data for the target to read. Autoclears when the read register is read by the target.
  +
<br>W - 1 if there is data for the debug side to read. Autoclears when the write register is read by the debug probe.
  +
   
 
The target application can send data to the debugger using the write register.
 
The target application can send data to the debugger using the write register.
 
When a word is loaded into the register, the W bit in the control register is set to notify the debug probe / debugger.
 
When a word is loaded into the register, the W bit in the control register is set to notify the debug probe / debugger.
The debugger reads the write register, which automatically the W bit.
+
The debugger reads the write register, which automatically sets the W bit.
   
 
The target application can read data from the debugger using the read register.
 
The target application can read data from the debugger using the read register.
Line 32: Line 35:
 
Unfortunately, ARM failed to suggest a standard communication protocol.
 
Unfortunately, ARM failed to suggest a standard communication protocol.
 
DCC can be used with J-Link debug probes in different ways. It is completely up to the application programmer which data
 
DCC can be used with J-Link debug probes in different ways. It is completely up to the application programmer which data
he wants to transfer. The application programmer is free to define is own protocol and can use J-Link to read the data on the host side.
+
he wants to transfer. The application programmer is free to define his own protocol and can use J-Link to read the data on the host side.
   
 
It is most commonly used for debug printf output or for system information, such as in embOS View.
 
It is most commonly used for debug printf output or for system information, such as in embOS View.
   
 
== SEGGER DCC Protocol ==
 
== SEGGER DCC Protocol ==
The SEGGER DCC protocol has been created 2006 to allow terminal I/O and memory access during program execution on the ARM 7/9 class processors that have dominated the market at the time, before Cortex-M became popular in the Embedded World.
+
The SEGGER DCC protocol was created 2006 to allow terminal I/O and memory access during program execution on the ARM 7/9 class processors that dominated the market at the time, before Cortex-M became popular in the Embedded World.
 
The memory access part is optional. Memory access code should be used in debug versions only, as it allows reading of the entire memory space.<br>
 
The memory access part is optional. Memory access code should be used in debug versions only, as it allows reading of the entire memory space.<br>
  +
The main C file has a section which can be modified. Per default, a 1KB output buffer is used so that Terminal output (printf) does not
In order to use the code, the function JLINKDCC_Process() needs to be called periodically. One good way of this is in a tick handler,
 
  +
halt the processor.
  +
=== How to use ===
  +
The first step is obviously to add the Source file to the project, so to compile and link them.
  +
The second step is to make sure the function JLINKDCC_Process() is called periodically. This can be done in a "On Idle" function,
  +
such as OS_Idle(), but since this means the system is not responsive when busy, a better way is to call it from a tick handler,
 
an Interrupt service routine which is called typically once per ms. The frequency with which the handler is called determines the maximum throughput.
 
an Interrupt service routine which is called typically once per ms. The frequency with which the handler is called determines the maximum throughput.
  +
=== Source code ===
 
  +
Below the entire source code required. The same source code is also available from www.segger.com.
=== JLINKDCC.h - Interface for SEGGER DCC Protocol ===
 
  +
It is under a permissive license which makes it easy to use it in whatever project.
  +
==== JLINKDCC.h - Interface for SEGGER DCC Protocol ====
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
 
/*********************************************************************
 
/*********************************************************************
* SEGGER MICROCONTROLLER SYSTEME GmbH *
+
* SEGGER Microcontroller GmbH *
* Solutions for real time microcontroller applications *
+
* The Embedded Experts *
 
**********************************************************************
 
**********************************************************************
 
* *
 
* *
* (c) 2006 SEGGER Microcontroller Systeme GmbH *
+
* (c) 2006 - 2019 SEGGER Microcontroller GmbH *
 
* *
 
* *
* Internet: www.segger.com Support: support@segger.com *
+
* www.segger.com Support: support@segger.com *
 
* *
 
* *
 
**********************************************************************
 
**********************************************************************
  +
* *
----------------------------------------------------------------------
 
  +
* All rights reserved. *
  +
* *
  +
* Redistribution and use in source and binary forms, with or *
  +
* without modification, are permitted provided that the following *
  +
* condition is met: *
  +
* *
  +
* o Redistributions of source code must retain the above copyright *
  +
* notice, this condition and the following disclaimer. *
  +
* *
  +
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
  +
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
  +
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
  +
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
  +
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
  +
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
  +
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
  +
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
  +
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  +
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
  +
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
  +
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
  +
* DAMAGE. *
  +
* *
  +
**********************************************************************
  +
  +
-------------------------- END-OF-HEADER -----------------------------
  +
 
File : JLINKDCC.h
 
File : JLINKDCC.h
 
Purpose : Header file for J-Link ARM type DCC communication
 
Purpose : Header file for J-Link ARM type DCC communication
  +
---------------------------END-OF-HEADER------------------------------
 
 
*/
 
*/
   
Line 78: Line 115:
   
   
=== JLINKDCC_Process_ASM.s - access to DCC registers for target processor ===
+
==== JLINKDCC_Process_ASM.s - access to DCC registers for target processor ====
 
<syntaxhighlight lang="Assembly">
 
<syntaxhighlight lang="Assembly">
/**********************************************************
+
/*********************************************************************
  +
* SEGGER Microcontroller GmbH *
* SEGGER MICROCONTROLLER SYSTEME GmbH
 
  +
* The Embedded Experts *
* Solutions for real time microcontroller applications
 
***********************************************************
+
**********************************************************************
  +
* *
*
 
  +
* (c) 2006 - 2019 SEGGER Microcontroller GmbH *
  +
* *
  +
* www.segger.com Support: support@segger.com *
  +
* *
  +
**********************************************************************
  +
* *
  +
* All rights reserved. *
  +
* *
  +
* Redistribution and use in source and binary forms, with or *
  +
* without modification, are permitted provided that the following *
  +
* condition is met: *
  +
* *
  +
* o Redistributions of source code must retain the above copyright *
  +
* notice, this condition and the following disclaimer. *
  +
* *
  +
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
  +
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
  +
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
  +
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
  +
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
  +
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
  +
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
  +
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
  +
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  +
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
  +
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
  +
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
  +
* DAMAGE. *
  +
* *
  +
**********************************************************************
  +
  +
-------------------------- END-OF-HEADER -----------------------------
  +
 
* File : JLINKDCC_Process_ASM.s
 
* File : JLINKDCC_Process_ASM.s
 
* Purpose : Routines for setting and writing co-processor register CP14
 
* Purpose : Routines for setting and writing co-processor register CP14
 
(DCC-communication)
 
(DCC-communication)
--------- END-OF-HEADER ---------------------------------
 
 
*/
 
*/
   
Line 141: Line 210:
   
   
=== JLINKDCC_Process.c - C implementation of the protocol ===
+
==== JLINKDCC_Process.c - C implementation of the protocol ====
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
 
/*********************************************************************
 
/*********************************************************************
 
* SEGGER Microcontroller GmbH *
 
* SEGGER Microcontroller GmbH *
* Solutions for real time microcontroller applications *
+
* The Embedded Experts *
 
**********************************************************************
 
**********************************************************************
 
* *
 
* *
* (c) 1995 - 2018 SEGGER Microcontroller GmbH *
+
* (c) 2006 - 2019 SEGGER Microcontroller GmbH *
 
* *
 
* *
 
* www.segger.com Support: support@segger.com *
 
* www.segger.com Support: support@segger.com *
 
* *
 
* *
 
**********************************************************************
 
**********************************************************************
  +
* *
----------------------------------------------------------------------
 
  +
* All rights reserved. *
  +
* *
  +
* Redistribution and use in source and binary forms, with or *
  +
* without modification, are permitted provided that the following *
  +
* condition is met: *
  +
* *
  +
* o Redistributions of source code must retain the above copyright *
  +
* notice, this condition and the following disclaimer. *
  +
* *
  +
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
  +
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
  +
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
  +
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
  +
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
  +
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
  +
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
  +
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
  +
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  +
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
  +
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
  +
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
  +
* DAMAGE. *
  +
* *
  +
**********************************************************************
  +
  +
-------------------------- END-OF-HEADER -----------------------------
  +
 
File : JLINKDCC_Process.c
 
File : JLINKDCC_Process.c
 
Purpose : Data handler for ARM J-Link type communication via DCC (IAR version, using intrinsics)
 
Purpose : Data handler for ARM J-Link type communication via DCC (IAR version, using intrinsics)
Line 243: Line 339:
 
T->H 0x93800000 + (Channel << 16) + (Data8)
 
T->H 0x93800000 + (Channel << 16) + (Data8)
   
---------------------------END-OF-HEADER------------------------------
 
 
*/
 
*/
   
Line 639: Line 734:
 
*
 
*
 
* Function description
 
* Function description
* This function should be called more or less regularily to allow
+
* This function should be called more or less regularly to allow
 
* memory reads while the application progam is running.
 
* memory reads while the application progam is running.
 
* The more often it is called, the higher the transfer speed.
 
* The more often it is called, the higher the transfer speed.
Line 776: Line 871:
   
   
  +
</syntaxhighlight>
  +
  +
==== JLINKDCC_HandleDataAbort.s ====
  +
This file is entirely optional. It handles data aborts which can happen if the debugger tries to read invalid memory,
  +
and allows graceful recovery.
  +
<syntaxhighlight lang="Assembler">
   
 
/*********************************************************************
 
/*********************************************************************
* SEGGER MICROCONTROLLER SYSTEME GmbH *
+
* SEGGER Microcontroller GmbH *
* Solutions for real time microcontroller applications *
+
* The Embedded Experts *
 
**********************************************************************
 
**********************************************************************
 
* *
 
* *
* (c) 2006 SEGGER Microcontroller Systeme GmbH *
+
* (c) 2006 - 2019 SEGGER Microcontroller GmbH *
 
* *
 
* *
* Internet: www.segger.com Support: support@segger.com *
+
* www.segger.com Support: support@segger.com *
 
* *
 
* *
 
**********************************************************************
 
**********************************************************************
  +
* *
----------------------------------------------------------------------
 
  +
* All rights reserved. *
  +
* *
  +
* Redistribution and use in source and binary forms, with or *
  +
* without modification, are permitted provided that the following *
  +
* condition is met: *
  +
* *
  +
* o Redistributions of source code must retain the above copyright *
  +
* notice, this condition and the following disclaimer. *
  +
* *
  +
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
  +
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
  +
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
  +
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
  +
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
  +
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
  +
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
  +
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
  +
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  +
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
  +
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
  +
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
  +
* DAMAGE. *
  +
* *
  +
**********************************************************************
  +
  +
-------------------------- END-OF-HEADER -----------------------------
  +
 
File : JLINKDCC_HandleDataAbort.s
 
File : JLINKDCC_HandleDataAbort.s
 
Purpose : Data abort handler for ARM J-Link type communication via DCC
 
Purpose : Data abort handler for ARM J-Link type communication via DCC
Line 800: Line 928:
 
protocol used by IAR in the embedded workbench for ARM and allows
 
protocol used by IAR in the embedded workbench for ARM and allows
 
using the live data window in C-Spy
 
using the live data window in C-Spy
  +
---------------------------END-OF-HEADER------------------------------
 
 
*/
 
*/
   
Line 822: Line 950:
 
**********************************************************************
 
**********************************************************************
 
*/
 
*/
</syntaxhighlight>
 
   
=== JLINKDCC_HandleDataAbort.s ===
 
This file is entirely optional. It handles data aborts which can happen if the debugger tries to read invalid memory,
 
and allows graceful recovery.
 
<syntaxhighlight lang="Assembler">
 
 
/*********************************************************************
 
/*********************************************************************
 
*
 
*
Line 882: Line 1,005:
 
/*************************** end of file ****************************/
 
/*************************** end of file ****************************/
 
</syntaxhighlight>
 
</syntaxhighlight>
  +
  +
== References ==
  +
* ARM: There is not much more documentation there, but (one copy of) the ARM specification can be found here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471i/BEIHGIBB.html

Latest revision as of 14:59, 6 September 2019


The Debug Communication Channel (DCC) is a simple communication mechanism which allows the debug probe to communicate with the program running on the target processor, using the debug interface (typically JTAG, Scan chain 2). In contrast to Semihosting, which halts the target CPU, it allows communication with the processor without halting the program. Communication is bidirectional.

Supported devices

DCC is available on ARM7/ARM9/ARM11 and Cortex-A/Cortex-R processors. Similar mechanisms have been introduced by other silicon vendors for their cores.

Implementation

DCC is implemented in what ARM calls "coprocessor 14" and contains three registers:

  • A 32-bit read register, used to transfer data down from debugger to the target, so read from target, written via debug interface
  • A 32-bit write register, used to transfer data up to the debugger, so written from target
  • A 32-bit control register, with only 2 bits being used:


R - 1 if there is data for the target to read. Autoclears when the read register is read by the target.
W - 1 if there is data for the debug side to read. Autoclears when the write register is read by the debug probe.


The target application can send data to the debugger using the write register. When a word is loaded into the register, the W bit in the control register is set to notify the debug probe / debugger. The debugger reads the write register, which automatically sets the W bit.

The target application can read data from the debugger using the read register. The debugger can write a word to the read register and set the R bit in the control register to notify the target application. When the target application reads the read register, the R bit is cleared again.

Interrupts

The target application can poll the R and W bit of the control register to check whether it can send or receive data. Alternatively, changes of the bits can be made available as COMMRX and COMMTX interrupts to enable more efficient interrupt-driven communication. However, interrupts are rarley used in combination with DCC as they introduce additional complexity and are not available on all cores.

Protocol

DCC can be used to transfer any kind of data while the target CPU is running. Unfortunately, ARM failed to suggest a standard communication protocol. DCC can be used with J-Link debug probes in different ways. It is completely up to the application programmer which data he wants to transfer. The application programmer is free to define his own protocol and can use J-Link to read the data on the host side.

It is most commonly used for debug printf output or for system information, such as in embOS View.

SEGGER DCC Protocol

The SEGGER DCC protocol was created 2006 to allow terminal I/O and memory access during program execution on the ARM 7/9 class processors that dominated the market at the time, before Cortex-M became popular in the Embedded World. The memory access part is optional. Memory access code should be used in debug versions only, as it allows reading of the entire memory space.
The main C file has a section which can be modified. Per default, a 1KB output buffer is used so that Terminal output (printf) does not halt the processor.

How to use

The first step is obviously to add the Source file to the project, so to compile and link them. The second step is to make sure the function JLINKDCC_Process() is called periodically. This can be done in a "On Idle" function, such as OS_Idle(), but since this means the system is not responsive when busy, a better way is to call it from a tick handler, an Interrupt service routine which is called typically once per ms. The frequency with which the handler is called determines the maximum throughput.

Source code

Below the entire source code required. The same source code is also available from www.segger.com. It is under a permissive license which makes it easy to use it in whatever project.

JLINKDCC.h - Interface for SEGGER DCC Protocol

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*                        The Embedded Experts                        *
**********************************************************************
*                                                                    *
*            (c) 2006 - 2019 SEGGER Microcontroller GmbH             *
*                                                                    *
*       www.segger.com     Support: support@segger.com               *
*                                                                    *
**********************************************************************
*                                                                    *
* All rights reserved.                                               *
*                                                                    *
* Redistribution and use in source and binary forms, with or         *
* without modification, are permitted provided that the following    *
* condition is met:                                                  *
*                                                                    *
* o Redistributions of source code must retain the above copyright   *
*   notice, this condition and the following disclaimer.             *
*                                                                    *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
* DAMAGE.                                                            *
*                                                                    *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File    : JLINKDCC.h
Purpose : Header file for J-Link ARM type DCC communication

*/

#ifndef JLINKDCC_H
#define JLINKDCC_H             // Avoid multiple inclusion

void JLINKDCC_Process(void);
void JLINKDCC_HandleDataAbort(void);
void JLINKDCC_SendString(const char * s);
void JLINKDCC_SendChar(char c);
void JLINKDCC_SendOnChannel      (unsigned Channel, unsigned char* pData, int NumItems);
void JLINKDCC_SetpfOnRx          (unsigned Channel, void          (* pf)(unsigned Channel, unsigned char c));
void JLINKDCC_SetpfOnTx          (unsigned Channel, void          (* pf)(unsigned Channel));
void JLINKDCC_SendCharOnChannelNB(unsigned Channel, unsigned char Data);

#endif                         // Avoid multiple inclusion

/*************************** end of file ****************************/


JLINKDCC_Process_ASM.s - access to DCC registers for target processor

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*                        The Embedded Experts                        *
**********************************************************************
*                                                                    *
*            (c) 2006 - 2019 SEGGER Microcontroller GmbH             *
*                                                                    *
*       www.segger.com     Support: support@segger.com               *
*                                                                    *
**********************************************************************
*                                                                    *
* All rights reserved.                                               *
*                                                                    *
* Redistribution and use in source and binary forms, with or         *
* without modification, are permitted provided that the following    *
* condition is met:                                                  *
*                                                                    *
* o Redistributions of source code must retain the above copyright   *
*   notice, this condition and the following disclaimer.             *
*                                                                    *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
* DAMAGE.                                                            *
*                                                                    *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

* File    : JLINKDCC_Process_ASM.s
* Purpose : Routines for setting and writing co-processor register CP14 
            (DCC-communication)
*/

/*********************************************************************
*
*       GNU ARM
*
*/
        .text
        .global  CP14_ReadDCCStat
        .global  CP14_ReadDCC
        .global  CP14_WriteDCC
        .arm
        .section .text, "ax" 

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       CP14_ReadDCCStat
*/
CP14_ReadDCCStat:
  mrc P14,0,R0,C0,C0,0
  bx lr


/*********************************************************************
*
*       CP14_ReadDCC
*/
CP14_ReadDCC:
  mrc P14,0,R0,C1,C0,0
  bx lr

/*********************************************************************
*
*       CP14_WriteDCC
*/
CP14_WriteDCC:
  mcr P14,0,R0,C1,C0,0
  bx lr
  
  .end
/**************************** End of file ***************************/


JLINKDCC_Process.c - C implementation of the protocol

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*                        The Embedded Experts                        *
**********************************************************************
*                                                                    *
*            (c) 2006 - 2019 SEGGER Microcontroller GmbH             *
*                                                                    *
*       www.segger.com     Support: support@segger.com               *
*                                                                    *
**********************************************************************
*                                                                    *
* All rights reserved.                                               *
*                                                                    *
* Redistribution and use in source and binary forms, with or         *
* without modification, are permitted provided that the following    *
* condition is met:                                                  *
*                                                                    *
* o Redistributions of source code must retain the above copyright   *
*   notice, this condition and the following disclaimer.             *
*                                                                    *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
* DAMAGE.                                                            *
*                                                                    *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File    : JLINKDCC_Process.c
Purpose : Data handler for ARM J-Link type communication via DCC (IAR version, using intrinsics)
Changes : 08-10-08
          Support for "channels"added, where
          channel 0 is reserved for terminal
          channel 1 is reserved for OS communication such as embOSView
          11-11-15
          Cortex A/R defines modified.

Notes   : (1) How to use
              In order to use the DCC communication to read / write memory, the
                following needs to be done:
              * Add this file to the project / make-file
              * Make sure this data handler is called regularly
              * Add the JLINKDCC data abort handler (optional)
                For details, refer to the documentation or see file JLINKDCC_HandleDataAbort.s79.
          (2) Compatibility
              The J-Link ARM DCC handler is compatible to the DCC communication
              protocol used by IAR in the embedded workbench for ARM and allows
              using the live data window in C-Spy

Protocol
  Following response packets from target will be possible:
  00 00 00 XX - reading a byte XX
  00 00 XX XX - reading a half word XXXX
  XX XX XX XX - reading a word, except words starting with 93zX XXXX (10010011-1xxxxxxx-xxxxxxx-xxxxxxx)

  93 8z 00 XX - terminal I/O one byte XX to channel z=0-15
  93 9z 00 XX - terminal I/O one byte XX to channel z=16-31
  93 Az XX XX - terminal I/O two bytes XX XX to channel z=0-15
  93 Bz XX XX - terminal I/O two bytes XX XX to channel z=16-31

  93 C0 XX XX - escape sequence for words starting with 93XX, the lower 16-bit part is in XX XX
  93 C1 XX XX - escape sequence for words starting with 93XX, the upper 16-bit part is in XX XX
  93 C2 XX XX - data abort for reading
  91 CA XX XX - signature (same as before)

  There is a new capability flag. C-SPY will use the new protocol when this is set.
  #define DCC_CAP_TERM_OUT   0x80

Sequence for U8 write:
  H->T    Addr & 0xFFFFFFFE
  H->T    ((Addr & 1) << 31) | (Data << 2) | 0x40000001

Sequence for U16 write:
  H->T    Addr & 0xFFFFFFFE
  H->T    ((Addr & 1) << 31) | (Data << 2) | 0x20000001

Sequence for U32 write:
  H->T    Addr & 0xFFFFFFFE
  H->T    (Data & 0xFFFF) << 2
  H->T    ((Addr & 1) << 31) | ((Data >> 14) & 0xFFFF) | 0x10000001

Sequence for U8 Read:
  H->T    Addr & 0xFFFFFFFE
  H->T    ((Addr & 1) << 31) | (NumItems << 2) | 0x04000001
  if (Aborted) {
    T->H    0x93c20000
  } else {
    T->H    Data
  }

Sequence for U16 Read:
  H->T    Addr & 0xFFFFFFFE
  H->T    ((Addr & 1) << 31) | (NumItems << 2) | 0x02000001
  if (Aborted) {
    T->H    0x93c20000
  } else {
    T->H    Data
  }

Sequence for U32 Read:
  H->T    Addr & 0xFFFFFFFE
  H->T    ((Addr & 1) << 31) | (NumItems << 2) | 0x01000001
  if (Aborted) {
    T->H    0x93c20000
  } else if ((Data >> 24) != 0x93) {
    T->H    Data
  } else {
    T->H    0x93c0.0000 | (Data & 0xFFFF)
    T->H    0x93c1.0000 | (Data >> 16)
  }

Terminal IN:  (target receives data)
H->T   0x93000000 + (Channel << 19) + (Data8 << 1) + DCC_OP_COMMAND

Terminal OUT: (target sends data)
T->H   0x93800000 + (Channel << 16) + (Data8)

*/

#include "JLINKDCC.h"

#ifdef __ICCARM__
  /* With IAR workbench we use intrinsics for CP14 communication */
  #include <intrinsics.h>
#else
  #define __ARM7A__ 1
  #define __ARM7R__ 2
  #define __CORE__  0    // Default is: DCC module is designed for ARM7/9. In order to support Cortex-A/R, __CORE__ has to be set to __ARM7A__ or __ARM7R__
  /* We use external functions from assembly module JLINKDCC_Process_ASM.s */
  extern unsigned long CP14_ReadDCCStat(void);
  extern unsigned long CP14_ReadDCC(void);
  extern void CP14_WriteDCC(unsigned long Data);
#endif

/*********************************************************************
*
*       Defines, configurable
*
**********************************************************************
*/

#ifndef JLINKDCC_BUFFER_SIZE
  #define JLINKDCC_BUFFER_SIZE    1024          // Used for channel 0 (terminal out buffer)
#endif

#define NUM_CHANNELS              2

/*********************************************************************
*
*       Defines, non- configurable
*
**********************************************************************
*/

#define U8  unsigned char
#define U16 unsigned short
#define U32 unsigned long

#define DCC_OP_READ_U32   0x01000000
#define DCC_OP_READ_U16   0x02000000
#define DCC_OP_READ_U8    0x04000000
#define DCC_OP_GET_CAPS   0x08000000
#define DCC_OP_WRITE_U32  0x10000000
#define DCC_OP_WRITE_U16  0x20000000
#define DCC_OP_WRITE_U8   0x40000000
#define DCC_OP_ODD_ADDR   0x80000000
#define DCC_OP_COMMAND    0x00000001

#define DCC_SIGNATURE     0x91CA0000
#define DCC_CONFIG        0xFF       // All features are supported

#define DCC_CHANNEL_TERMINAL  0
#define DCC_CHANNEL_OS        1

//
// The bit positions for DCC RX and TX ready are different for ARM7/9 and Cortex-A/R,
// so we have to distinguish here.
//
#if (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
  #define RX_FULL_FLAG_SHIFT 30
  #define TX_FULL_FLAG_SHIFT 29
#else
  #define RX_FULL_FLAG_SHIFT 0
  #define TX_FULL_FLAG_SHIFT 1
#endif

/*********************************************************************
*
*       Global data
*
**********************************************************************
*/

U8 JLINKDCC_IsInHandler;
U8 JLINKDCC_AbortOccurred;

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

void (* _pfOnRx[2]) (unsigned Channel, U8 Data);
void (* _pfOnTx[2]) (unsigned Channel);


static U16  _NumReadItems;
static U32  _Command;
static U32  _Addr;

static char _acBuffer[JLINKDCC_BUFFER_SIZE];
static U16  _RdPos;
static U16  _WrPos;

static U8   _ActiveChannel   = 0;

static char _WritePendingNB  = 0;
static U32  _PendingPacketNB = 0;

static char _WritePending;
static U32  _Data;

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/

#ifdef __ICCARM__
/****** Use intrinsics for CP14 communication ***********************/

#if (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))

/*********************************************************************
*
*       _ReadDCCStat
*
*  IAR macro:     unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
*  Inst:          MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move from coproc to ARM reg
*  ARMv4 / ARMv5: MRC p14,0,<Rt>,c0,c0,0
*  ARMv7-AR:      MRC p14,0,<Rt>,c0,c1,0 DBGDSCR
*/
static int _ReadDCCStat(void) {
  return __MRC(14, 0, 0, 1, 0);
}

/*********************************************************************
*
*       _ReadDCC
*
*  IAR macro:     unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
*  Inst:          MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move from coproc to ARM reg
*  ARMv4 / ARMv5: MRC p14,0,<Rt>,c1,c0,0
*  ARMv7-AR:      MRC p14,0,<Rt>,c0,c5,0 DTRRX
*/
static U32 _ReadDCC(void) {
  return __MRC(14, 0, 0, 5, 0);
}

/*********************************************************************
*
*       _WriteDCC
*
*  IAR macro:     void __MCR(coproc, opcode_1, Data, CRn, CRm, opcode_2);
*  Inst:          MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move to coproc
*  ARMv4 / ARMv5: MCR P14,0,<Rt>,C1,C0,0
*  ARMv7-AR:      MCR p14,0,<Rt>,c0,c5,0 DTRTX
*/
static void _WriteDCC(U32 Data) {
  __MCR(14, 0, Data, 0, 5, 0);
}

#else // (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))

/*********************************************************************
*
*       _ReadDCCStat
*
*  IAR macro:     unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
*  Inst:          MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move from coproc to ARM reg
*  ARMv4 / ARMv5: MRC p14,0,<Rt>,c0,c0,0
*  ARMv7-AR:      MRC p14,0,<Rt>,c0,c1,0 DBGDSCR
*/
static __interwork __arm int _ReadDCCStat(void) {
  return __MRC( 14, 0, 0, 0, 0 );       // __asm("mrc P14,0,R0,C0,C0,0");
}

/*********************************************************************
*
*       _ReadDCC
*
*  IAR macro:     unsigned long __MRC(coproc, opcode_1, CRn, CRm, opcode_2);
*  Inst:          MRC<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move from coproc to ARM reg
*  ARMv4 / ARMv5: MRC p14,0,<Rt>,c1,c0,0
*  ARMv7-AR:      MRC p14,0,<Rt>,c0,c5,0 DTRRX
*/
static __interwork __arm U32 _ReadDCC(void) {
  return __MRC( 14, 0, 1, 0, 0 );       // __asm("mrc P14,0,R0,C1,C0,0");
}

/*********************************************************************
*
*       _WriteDCC
*
*  IAR macro:     void __MCR(coproc, opcode_1, Data, CRn, CRm, opcode_2);
*  Inst:          MCR<c> <coproc>,<opc1>,<Rt>,<CRn>,<CRm>{,<opc2>}  Move to coproc
*  ARMv4 / ARMv5: MCR P14,0,<Rt>,C1,C0,0
*  ARMv7-AR:      MCR p14,0,<Rt>,c0,c5,0 DTRTX
*/
static __interwork __arm void _WriteDCC(U32 Data) {
  __MCR( 14, 0, Data, 1, 0, 0 );        // __asm("mcr P14,0,R0,C1,C0,0");
}

#endif // (defined (__ARM7A__) && (__CORE__ == __ARM7A__)) || (defined (__ARM7R__) && (__CORE__ == __ARM7R__))
#else  //__ICCARM__

/****** Map externel CP14 communication routines ********************/
#define _ReadDCCStat     CP14_ReadDCCStat
#define _ReadDCC         CP14_ReadDCC
#define _WriteDCC(Data)  CP14_WriteDCC(Data)

#endif // __ICCARM__

/*********************************************************************
*
*       _HandleRead
*
*  Function description
*    Performs Command / data read from host
*/
static void _HandleRead(void) {
  U32 Data;

  if (((_ReadDCCStat() >> RX_FULL_FLAG_SHIFT)  & 1) == 0) {       // Data or command received ?
    return;      // Nothing received
  }

  Data = _ReadDCC();
  //
  // If item received does not have the command-flag set, it is the new addr.
  //
  if ((Data & DCC_OP_COMMAND) == 0) {
    _Addr = Data;
    return;
  }
  //
  // If item received is a terminal out command,
  //
  if ((Data & 0xFF000000) == 0x93000000) {
    unsigned Channel;
    Channel = (Data >> 19) & 0x1F;
    if (_pfOnRx[Channel]) {
      _pfOnRx[Channel](Channel, (Data >> 1) & 0xFF);
    }
    return;
  }
  //
  // We received a new command.
  //
  _Command = Data;
  if (_Command & DCC_OP_ODD_ADDR) {
    _Addr |= 1;
  }
  if (_Command & (DCC_OP_READ_U32 | DCC_OP_READ_U16 | DCC_OP_READ_U8 | DCC_OP_GET_CAPS)) {
    _NumReadItems = (_Command >> 2) & 0xffff;
  } else {
    // Clear before write
    JLINKDCC_AbortOccurred = 0;

    if (_Command & DCC_OP_WRITE_U32) {
      _Data |= (_Command << 14) & 0xffff0000;
    } else {
      _Data = (_Command >> 2) & 0xffff;
    }
    if (_Command & DCC_OP_WRITE_U8) {
      *(U8*)_Addr = _Data;
      _Addr += 1;
    }
    if (_Command & DCC_OP_WRITE_U16) {
      *(U16*)_Addr = _Data;
      _Addr += 2;
    }
    if (_Command & DCC_OP_WRITE_U32) {
      *(U32*)_Addr =_Data;
      _Addr += 4;
    }
  }
}

/*********************************************************************
*
*       _HandleWrite
*
*  Function description
*    Sends data back to host if there is space in DCC buffer and data to be send.
*/
static void _HandleWrite(void) {
  U32 Data;
  int DCCBusy;
  int NumBytes;

  Data = 0;
  DCCBusy = (_ReadDCCStat() >> TX_FULL_FLAG_SHIFT) & 1;
  if (DCCBusy) {                  // Can we send data ?
    return;                       // If not, we are done.
  }

  if (_ActiveChannel) {
    U32 Channel;

    Channel = _ActiveChannel;
    _ActiveChannel = 0;
    if (_WritePendingNB) {
      _WriteDCC(_PendingPacketNB);
      _WritePendingNB = 0;
    }
    if (_pfOnTx[Channel]) {
      _pfOnTx[Channel](Channel);
    }
    return;
  }

  //
  // Check if a data item is pending
  //
  if (_WritePending) {
    _WriteDCC(_Data);
    _WritePending = 0;
    return;
  }
  //
  // Check if a read command is pending
  //
  if (_NumReadItems) {
    if (_Command & DCC_OP_GET_CAPS) {
      Data = (DCC_CONFIG | DCC_SIGNATURE);
      Data |= (JLINKDCC_AbortOccurred << 8);  // write abort status
      JLINKDCC_AbortOccurred = 0;
    } else {

      // Clear before next read
      JLINKDCC_AbortOccurred = 0;

      if (_Command & DCC_OP_READ_U8) {
        Data = *(U8*)_Addr;
        _Addr += 1;
      } else if (_Command & DCC_OP_READ_U16) {
        Data = *(U16*)_Addr;
        _Addr += 2;
      } else if (_Command & DCC_OP_READ_U32) {
        Data = *(U32*)_Addr;
        _Addr += 4;
        if ((Data & 0xFF800000) == 0x93800000) {    // Do we need to use the escape sequence and split it up into 2 transfers ?
          _Data = 0x93c10000 | (Data >> 16);
          Data  = 0x93c00000 | (Data & 0xFFFF);
          _WritePending = 1;
        }
      }
      if (JLINKDCC_AbortOccurred) {
        Data = 0x93c20000;          // read abort status
        _WritePending = 0;
        JLINKDCC_AbortOccurred = 0; // clear it
      }
    }

    _WriteDCC(Data);
    _NumReadItems--;
    return;
  }
  //
  // Handle terminal out. Up to 2 bytes in one 32-bit unit
  //
  NumBytes = _WrPos - _RdPos;
  if (NumBytes < 0) {
    NumBytes += sizeof(_acBuffer);
  }
  if (NumBytes) {
    int i;
    if (NumBytes > 2) {
      NumBytes = 2;
    }
    if (NumBytes == 2) {
      Data = 0x93A00000;
    } else {
      Data = 0x93800000;
    }
    for (i = 0; i < NumBytes; i++) {
      Data |= _acBuffer[_RdPos] << (8*i);
      _RdPos++;
      if (_RdPos == sizeof(_acBuffer)) {
        _RdPos = 0;
      }
    }
    _WriteDCC(Data);
  }
}


/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       JLINKDCC_Process
*
*  Function description
*    This function should be called more or less regularly to allow
*    memory reads while the application progam is running.
*    The more often it is called, the higher the transfer speed.
*/
void JLINKDCC_Process(void) {
  //
  // Avoid problems if this code is called from multiple threads or interrupts
  //
  if (JLINKDCC_IsInHandler) {
    return;
  }
  JLINKDCC_IsInHandler = 1;
  _HandleRead();
  _HandleWrite();
   JLINKDCC_IsInHandler = 0;
}

/*********************************************************************
*
*       JLINKDCC_SendChar
*
*  Function description
*   Sends a single char to terminal out.
*/
void JLINKDCC_SendChar(char c) {
  int Pos;

  Pos = _WrPos + 1;
  if (Pos == sizeof(_acBuffer)) {
    Pos = 0;
  }
  if (Pos == _RdPos) {
    return;
  }
  _acBuffer[_WrPos] = c;
  _WrPos = Pos;
}

/*********************************************************************
*
*       JLINKDCC_SendString
*
*  Function description
*   Sends a NUL- terminated string to terminal out.
*/
void JLINKDCC_SendString(const char * s) {
  char c;
  while (1) {
    c = *s++;
    if (c == 0) {
      break;
    }
    JLINKDCC_SendChar(c);
  }
}

/*********************************************************************
*
*       JLINKDCC_SendCharOnChannelNB
*
*  Function description
*    Send data to the host on selected channel.
*    This function is non-blocking.
*    If data can not be send it is stored in a buffer
*    and sent later, when the DCC Handler is called.
*/
void JLINKDCC_SendCharOnChannelNB(unsigned Channel, U8 Data) {
  U32 DCCPacket;
  int DCCBusy;

  DCCPacket = 0x93800000 | (Channel << 16);
  DCCPacket |= Data;
  DCCBusy = _ReadDCCStat() & 2;
  if (DCCBusy == 0) {
    _WriteDCC(DCCPacket);
  } else {
    _WritePendingNB = 1;
    _PendingPacketNB = DCCPacket;
  }
  _ActiveChannel = Channel;
}

/*********************************************************************
*
*       JLINKDCC_SendOnChannel
*
*  Function description
*    Send data to the host.
*    32 channels are available, channel 0 is used for terminal output and is buffered,
*    all other channels are unbuffered.
*/
void JLINKDCC_SendOnChannel(unsigned Channel, U8 * pData, int NumItems) {
  U32 Data;

  if (Channel == DCC_CHANNEL_TERMINAL)  {
    while (NumItems-- > 0) {
      Data = *pData++;
      JLINKDCC_SendChar(Data);
    }
  } else {
    while (NumItems-- > 0) {
      Data = *pData++;
      if  (NumItems > 0) {
        Data |= *pData++ << 8;
        NumItems--;
        Data |= 0x200000;
      }
      Data |= 0x93800000;
      Data |= Channel << 16;
      while (_ReadDCCStat() & 2);       // Wait until we can send data
      _WriteDCC(Data);
    }
  }
}

/*********************************************************************
*
*       JLINKDCC_SetpfOnRx
*
*/
void JLINKDCC_SetpfOnRx(unsigned Channel, void (* pf)(unsigned Channel, U8 Data)) {
  _pfOnRx[Channel] = pf;
}

/*********************************************************************
*
*       JLINKDCC_SetpfOnTx
*
*/
void JLINKDCC_SetpfOnTx(unsigned Channel, void (* pf)(unsigned Channel)) {
  _pfOnTx[Channel] = pf;
}


/*************************** end of file ****************************/

JLINKDCC_HandleDataAbort.s

This file is entirely optional. It handles data aborts which can happen if the debugger tries to read invalid memory, and allows graceful recovery.

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*                        The Embedded Experts                        *
**********************************************************************
*                                                                    *
*            (c) 2006 - 2019 SEGGER Microcontroller GmbH             *
*                                                                    *
*       www.segger.com     Support: support@segger.com               *
*                                                                    *
**********************************************************************
*                                                                    *
* All rights reserved.                                               *
*                                                                    *
* Redistribution and use in source and binary forms, with or         *
* without modification, are permitted provided that the following    *
* condition is met:                                                  *
*                                                                    *
* o Redistributions of source code must retain the above copyright   *
*   notice, this condition and the following disclaimer.             *
*                                                                    *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           *
* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR           *
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  *
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;    *
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF      *
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT          *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE  *
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
* DAMAGE.                                                            *
*                                                                    *
**********************************************************************

-------------------------- END-OF-HEADER -----------------------------

File    : JLINKDCC_HandleDataAbort.s
Purpose : Data abort handler for ARM J-Link type communication via DCC
Notes   : (1) How to use
              In order to use the DCC abort handler, 3 things need to be done:
              * Place a branch to DCC_Abort at address 0x10 ("vector" used for data aborts)
              * Initialize the Abort-mode stack pointer to an area of at least 8 bytes of stack
                memory required by the handler
              * Add the DCC abort handler assembly file to the application
          (2) Compatibility
              The J-Link ARM DCC handler is compatible to the DCC communication
              protocol used by IAR in the embedded workbench for ARM and allows
              using the live data window in C-Spy
              
*/


/*********************************************************************
*
*       GNU ARM
*
*/
        .text
        .extern  JLINKDCC_IsInHandler
        .extern  JLINKDCC_AbortOccurred
        .global  JLINKDCC_HandleDataAbort
        .arm
        .section .text, "ax" 

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/

/*********************************************************************
*
*       JLINKDCC_HandleDataAbort
*
*  Function description
*    Data abort handler for J-Link ARM type DCC communication.
*
*  Notes
*    (1) Abort mode
*        This handler is supposed to be executed in abort mode by simply placing a
*        jump to the handler at address 0x10.
*        Just like an interrupt service routine, it needs to restore all registers
*        for other modes and may only permanently modify registers of abort mode (SPSR_ABT, R14_ABT)
*/
JLINKDCC_HandleDataAbort:
@
@ Check if exception stemmed from JLINKARM DCC communication. Otherwise, user abort handler is called
@
        STMDB     SP!, {R0,R1}            @ Save registers on stack
        LDR       R1, =JLINKDCC_IsInHandler
        LDRB      R0, [R1, #0]
        TST       R0, R0                  @ Check if abort occurred during execution of DCC handler
        LDMEQIA   SP!, {R0,R1}            @ Restore registers
        BEQ       UserAbortHandler
@
@ Set JLINKDCC_AbortOccurred so PC (via J-Link) has a chance to find out that memory operation was aborted
@
        LDR       R1, =JLINKDCC_AbortOccurred
        STRB      R0, [R1, #0]            @ Set abort occurred state
@
@ Continue code execution right after the instruction which caused the abort.
@
        MRS       R0, SPSR
        TST       R0, #0x20               @ Check thumb bit
        LDMIA     SP!, {R0,R1}            @ Restore registers
        SUBEQS    PC, R14, #4             @ Return after the aborted instruction (ARM mode)
        SUBS      PC, R14, #6             @ Return after the aborted instruction (Thumb mode)

/*********************************************************************
*
*       UserAbortHandler
*
*  Function description
*    User defined abort handler.
*    This function is called if a data abort occurs for other reasons than JLINK DCC comunication.
*    Feel free to modify and jump to your own handler as required.
*/
UserAbortHandler:
        B         UserAbortHandler        @ Modify this line to jump to your own handler if desired

        .end

/*************************** end of file ****************************/

References