/***********************************************************************
*                    SEGGER Microcontroller GmbH                       *
*                        The Embedded Experts                          *
************************************************************************
*                                                                      *
*                  (c) SEGGER Microcontroller GmbH                     *
*                        All rights reserved                           *
*                          www.segger.com                              *
*                                                                      *
************************************************************************
*                                                                      *
************************************************************************
*                                                                      *
*                                                                      *
*  Licensing terms                                                     *
*                                                                      *
* The use in source and binary forms, with or without modification,    *
* is permitted for internal use only. The redistribution to any        *
* third party is prohibited.                                           *
*                                                                      *
*                                                                      *
* THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "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 COPYRIGHT HOLDER 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    : Template_UartTIF.JLinkScript
Purpose : This script shows how to use the JLINK_UART_XXX() functions to use UART as a target interface.

*/

/*********************************************************************
*
*       Constants (similar to defines)
*
**********************************************************************
*/

//
// User-specified constants to be used by PCode
//
__constant U32 _UART_BAUDRATE_HZ       = 9600;     // Use a baudrate all J-Link models can handle.
__constant U32 _PIN_OVERRIDE_TMS       = 2;        // TMS/SWDIO pin is used as UART communication pin
__constant U32 _TIMEOUT_SEND_1_BYTE    = 5;        // @9600 Baud, 1 char takes 10 * 104us for transmission. Considering that we might be at the edge of a MSInterrupt, add some additional delay. However, add some more as it does not really hurt
__constant U32 _TIMEOUT_RECEIVE_1_BYTE = 3;
__constant U32 _MAX_NUM_PINS_OVERRIDE  = 8;

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/

U32 _aPINMode[8];    // Keep in sync with _MAX_NUM_PINS_OVERRIDE
U32 _aPINState[8];   // Keep in sync with _MAX_NUM_PINS_OVERRIDE

/*********************************************************************
*
*       Local functions
*
**********************************************************************
*/

/*********************************************************************
*
*       _UART_WriteBytes
*
*  Function description
*    Writes bytes via UART to target and swallows echoed bytes.
*
*  Return value
*    >= 0  O.K.
*     < 0  Error
*/
static int _UART_WriteBytes(const U8* pData, int NumBytes, int TimeoutMs) {
  U8  Data;
  int r;
  int t;
  int NumBytesRem;

  NumBytesRem = NumBytes;
  JLINK_UART_Write(pData, NumBytesRem);
  t = JLINK_GetTime();
  //
  // J-Link firmware echoes everything we write, so make sure we swallow these bytes
  //
  do {
    r = JLINK_UART_Read(&Data, 1);
    if (r == 1) {
      NumBytesRem -= 1;
      if (NumBytesRem == 0) {            // Everything has been sent
        r = 0;
        break;
      }
    }
    r = JLINK_GetTime() - t;
    if (r > TimeoutMs) {
      //JLINK_SYS_Report1("Timeout while writing bytes: ", NumBytes);
      r = -1;
      break;
    }
  } while (1);
  return r;
}

/*********************************************************************
*
*       _UART_ReadCharTimeout
*
*  Function description
*    Reads a character with timeout.
*
*  Return value
*    >= 0  O.K., number of bytes read
*     < 0  Error
*/
static int _UART_ReadCharTimeout(U8* pData, int TimeoutMs) {
  int r;
  int t;

  t = JLINK_GetTime();
  do {
    r = JLINK_UART_Read(pData, 1);
    if (r == 1) {
      break;
    }
    r = JLINK_GetTime() - t;
    if (r > TimeoutMs) {
      //JLINK_SYS_Report1("Timeout while reading char: ", r);
      r = 0;
      break;
    }
  } while (1);
  return r;
}

/*********************************************************************
*
*       _CommandSequenceViaUART
*
*  Function description
*    Sends a arbitrary command sequence via UART
*
*  Return value
*    >= 0: O.K.
*     < 0: Error
*/
static int _CommandSequenceViaUART(void) {
  int i;
  int r;
  U8  ch0;
  U8  ch1;
  U8  ch2;

  while (JLINK_UART_Read(&ch0, 1) == 1);                      // Before PIN override is executed, a lot of zeros may be read into JLink's circular buffer. So clear the buffer
  ch0 = 0x00;                                                 // Trigger baudrate detection
  ch1 = 0x55;                                                 // Arbitrary Command
  i = 0;

  r = JLINK_UART_Read(&ch0, 1);
  do {                                                        // Sequence might need to be sent multiple times...
    _UART_WriteBytes(&ch0, 1, _TIMEOUT_SEND_1_BYTE);
    JLINK_Delay_us(2000);                                     // Arbitrary delay (may be needed)
    _UART_WriteBytes(&ch1, 1, _TIMEOUT_SEND_1_BYTE);
    ch2 = 0;
    r = _UART_ReadCharTimeout(&ch2, _TIMEOUT_RECEIVE_1_BYTE);
    if (r > 0) {                                              // Received response from target?
      break;
    }
    i += 1;
  } while(i < 5);                                             // Try 5 times
  if (r != 1) {
    //JLINK_SYS_Report1("Device did not respond: ", r);
    return 0;                                                 // Device may unresponsive
  }
  if (ch2 != 0xAA) {
    //JLINK_SYS_Report1(" Incorrect answer received from device", ch2);
    return -1;
  }
  JLINK_Delay_us(50000);                                      // Sleep
  return 0;
}

/*********************************************************************
*
*       Global functions
*
**********************************************************************
*/

/*********************************************************************
*
*       InitTarget()
*
*  Function description
*    If present, called right before performing generic connect sequence.
*    Usually used for targets which need a special connect sequence.
*    E.g.: TI devices with ICEPick TAP on them where core TAP needs to be enabled via specific ICEPick sequences first
*
*  Return value
*    >= 0:  O.K.
*     < 0:  Error
*
*  Notes
*    (1) Must not use high-level API functions like JLINK_MEM_ etc.
*    (2) For target interface JTAG, this device has to setup the JTAG chain + JTAG TAP Ids.
*    (3) __probe attribute specifies that this function is executed in the J-Link firmware rather than on the PC side, so changes to global variables may only be temporarily valid inside this function (not guaranteed to be valid later)
*/
__probe int InitTarget(void) {
  int i;
  int r;
  //
  // Configure half-duplex UART on TMS/SWDIO pin
  //
  i = 0;
  do {
    _aPINMode[i] = JLINK_PIN_OVERRIDE_MODE_RELEASE;                   // Do not override any pin by default
    i += 1;
  } while(i < _MAX_NUM_PINS_OVERRIDE);
  _aPINMode[_PIN_OVERRIDE_TMS] = JLINK_PIN_OVERRIDE_MODE_UART_RXTX;   // Half-duplex UART means Tx and Rx are on the same pin
  r = JLINK_PIN_Override(&_aPINMode[0], &_aPINState[0]);
  if (r < 0) {
    return r;
  }
  //
  // Init UART interface and send sequence
  //
  JLINK_UART_Init(_UART_BAUDRATE_HZ);
  r = _CommandSequenceViaUART();
  JLINK_UART_DeInit();
  //
  // Restore pin configuration of J-Link
  //
  i = 0;
  do {
    _aPINMode[i] = JLINK_PIN_OVERRIDE_MODE_RELEASE;   // Do not override any pin by default
    i += 1;
  } while(i < _MAX_NUM_PINS_OVERRIDE);
  JLINK_PIN_Override(&_aPINMode[0], &_aPINState[0]);
  return r;
}