/******************** (C) COPYRIGHT 2012 STMicroelectronics ********************
* File Name          : STMFlashLoader.cpp
* Author             : MCD Application Team
* Version            : v2.6.0
* Date               : 07-November-2012
* Description        : STM Flash Loader command line version
********************************************************************************
* THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
********************************************************************************
* FOR MORE INFORMATION PLEASE CAREFULLY READ THE LICENSE AGREEMENT FILE
* "MCD-ST Liberty SW License Agreement V2.pdf"
*******************************************************************************/

/* changes
- option -ow added
- getch() instead of getchar() to handle press any key correctly
- option --ep added to -d option to erase required pages before download

 
COMMENT: compile with
  ConfigurationProperties->General->ProjectDefaults->UseOfMFC = Use MFC in Static Library
                         ->C/C+->CodeGeneration->RunTimeLibrary = MultiThreaded /MT
*/


#include "stdafx.h"
#include "string.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <dos.h>
#include <conio.h>


#include "../STBLLIB/STBLLIB.h"
#include "../Files/Files.h"
#include "ini.h"

#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1

#define NONE = 0;
#define ODD  = 1;
#define EVEN = 2;

/* Options Bytes Areas*/

DWORD ADDR_F0_OPB     = 0x1FFFF800;
DWORD ADDR_F1_OPB     = 0x1FFFF800;
DWORD ADDR_F2_OPB     = 0x1FFFC000;
DWORD ADDR_L1_OPB     = 0x1FF80000;
DWORD ADDR_XX_OPB     = 0x1FFFF800;


typedef enum STATE {OK,KO};

char MapFile[256];
PMAPPING pmMapping;

int TimeBO = 100;

BOOL SHOW_OK = TRUE;  // Set to TRUE/FALSE to show/hide OK status  messages
BOOL SHOW_KO = TRUE;  // Set to TRUE/FALSE to show/hide KO status  messages
int family = 0;

/*******************************************************************************************/
/* Function    : FileExist                                                                 */
/* IN          : file name                                                                 */
/* OUT         : boolean                                                                   */
/* Description : verify if the given file exists                                           */
/*******************************************************************************************/
BOOL FileExist(LPCTSTR filename)
{
  // Data structure for FindFirstFile
  WIN32_FIND_DATA findData;

  // Clear find structure
  ZeroMemory(&findData, sizeof(findData));

  // Search the file
  HANDLE hFind = FindFirstFile( filename, &findData );
  if ( hFind == INVALID_HANDLE_VALUE )
  {
  // File not found
  return false;
  }

  // File found

  // Release find handle
  FindClose( hFind );
  hFind = NULL;

  // The file exists
  return true;
}

/*******************************************************************************************/
/* Function    : void man()                                                                */
/* IN          :                                                                           */
/* OUT         :                                                                           */
/* Description : print the manual on the standard output                                   */
/*******************************************************************************************/
void man()
{
  printf(" Usage : \n\n");
  printf(" STMFlashLoader.exe [options] [Agrument][[options] [Agrument]...] \n\n");
    
  printf("  -?                   Show this help\n");

  printf("  -c                   Establish connection to the COM port\n");
  printf("     --pn  port_nb     : e.g. 1, 2 ... (default 1)\n");
  printf("     --br  baud_rate   : e.g. 115200, 57600 ... (default 115200)\n");
  printf("     --db  data_bits   : value in {5,6,7,8} ... (default 8)\n");
  printf("     --pr  parity      : value in {NONE,ODD,EVEN} ... (default EVEN)\n");
  printf("     --sb  stop_bits   : value in {1,1.5,2} ... (default 1)\n");
  printf("     --ec  echo        : value OFF or ECHO or LISTEN ... (default OFF)\n");  
  printf("     --co  control     : Enable or Disable RTS and DTR outputs control \n");
  printf("                       : value OFF or ON ... (default OFF)\n");
  printf("     --to  time_out    : (ms) e.g 1000, 2000, 3000 ... (default 5000)\n");

  printf("  -Rts                 Set RTS line to Hi, Lo\n");
  printf("     --state           : state in {Hi, Lo}, e.g. --Hi\n");
  printf("  -Dtr                 Set DTR line to Hi, Lo\n");
  printf("     --state           : state in {Hi, Lo}, e.g. --Hi\n");
  
  printf("  -i  device_name      e.g. STM32_Low-density_16K (see the Map directory) \n");

  printf("  -e                   Erase flash pages\n");
  printf("     --all all pages   : erase all pages\n");
  printf("     --sec number_of_pages_group pages_group_codes: erase specified group pages\n");

  printf("  -u                   Upload flash contents to a .bin, .hex or .s19 file\n");
  printf("     --fn  file_name   : full path name of the file \n");

  printf("  -d                   Download the content of a file into MCU flash\n");
  printf("     --a   address(hex): start @ in hex ; ignored if it is not a binary file \n");
  printf("     --fn  file_name   : full path name (.bin, .hex or .s19 file) \n");
  printf("     --ep              : erase rquired pages before download\n"); //ow
  printf("     --v               : verify after download \n");
  printf("     --o               : optimize; removes FFs data \n");
  
  printf("  -r                   Run the flash code at the specified address\n");
  printf("     --a address(hex)  : address in hexadecimal, e.g. --a 8000000\n");

  printf("  -p                   Enable or Disable protections\n");
  printf("     --ewp             : enable write protection for sector codes, e.g. 1,2,etc\n");
  printf("     --dwp             : disable write protection \n");
  printf("     --drp             : disable read protection \n");
  printf("     --erp             : enable read protection, all arguments following this\n"); 
  printf("                         one will fail \n");

  printf("  -o                   Get or Set STM32F1x option bytes (use -d for others!)\n");              
  printf("     --get --fn file_name       : get option bytes from the device \n");
  printf("                                  and write it in the specified file \n");
  printf("     --set --fn file_name       : load option bytes from the specified file \n");
  printf("                                  and write it to the device \n");
  printf("     --set --vals --OPB hex_val : set the specified option byte; OPB in: User, \n");
  printf("                                  RDP, Data0, Data1, WRP0, WRP1, WRP2, WRP3 \n");

//ow
  printf("  -ow                  Set device name map automatically, call instead of -i\n");              
  printf("                       gets also device family, ID, option byte adr, flash size\n" );

}





/*******************************************************************************************/
/* Function    : ParityToInt                                                               */
/* IN          : parity as string (NONE, ODD, EVEN)                                        */
/* OUT         : integer                                                                   */
/* Description : Get the integer representation of the given parity                        */
/*******************************************************************************************/
int ParityToInt(char* parity)
{
  if (strcmp(parity,"NONE")==0) return 0;
  else if(strcmp(parity,"ODD")==0) return 1;
  else if(strcmp(parity,"EVEN")==0) return 2;
  else return 2;
}


/*******************************************************************************************/
/* Function    : ModeToInt                                                                 */
/* IN          : Mode as string (OFF, ECHO, LISTEN)                                        */
/* OUT         : int                                                                      */
/* Description : Get the int representation of the given string Mode                       */
/*******************************************************************************************/
int ModeToInt(char* status)
{
  if (strcmp(status,"OFF")==0) return 0;
  else if(strcmp(status,"ECHO")==0) return 1;
  else if(strcmp(status,"LISTEN")==0) return 2;
  else return 0;
}

/*******************************************************************************************/
/* Function    : StatusToBool                                                              */
/* IN          : Status as string (ON, OFF)                                                */
/* OUT         : Bool                                                                      */
/* Description : Get the boolean representation of the given string ON/OFF                 */
/*******************************************************************************************/
bool StatusToBool(char* status)
{
  if (strcmp(status,"OFF")==0) return false;
  else if(strcmp(status,"ON")==0) return true;
  else return false;
}


/*******************************************************************************************/
/* Function    : Is_Option                                                                 */
/* IN          : option as string                                                          */
/* OUT         : boolean                                                                   */
/* Description : Verify if the given string present an option                              */
/*******************************************************************************************/
bool Is_Option(char* option)
{
  if (strcmp(option,"-?")==0) return true;
  else if (strcmp(option,"-c")==0) return true;
  else if (strcmp(option,"-i")==0) return true;
  else if (strcmp(option,"-e")==0) return true;
  else if (strcmp(option,"-u")==0) return true;
  else if (strcmp(option,"-d")==0) return true;
  else if (strcmp(option,"-v")==0) return true;
  else if (strcmp(option,"-p")==0) return true;
  else if (strcmp(option,"-r")==0) return true;
  else if (strcmp(option,"-o")==0) return true;
  else if (strcmp(option,"-Rts")==0) return true;
  else if (strcmp(option,"-Dtr")==0) return true;
  else if (strcmp(option,"-ow")==0) return true; //ow
  else return false;
}

/*******************************************************************************************/
/* Function    : Is_SubOption                                                              */
/* IN          : sub-option as string                                                      */
/* OUT         : boolean                                                                   */
/* Description : Verify if the given string present a sub-option                           */
/*******************************************************************************************/
bool Is_SubOption(char* suboption)
{
  if (strcmp(suboption,"--pn")==0) return true;  
  else if (strcmp(suboption,"--br")==0) return true;  
  else if (strcmp(suboption,"--db")==0) return true;  
  else if (strcmp(suboption,"--pr")==0) return true;  
  else if (strcmp(suboption,"--sb")==0) return true;
  else if (strcmp(suboption,"--ec")==0) return true;
  else if (strcmp(suboption,"--co")==0) return true;
  else if (strcmp(suboption,"--to")==0) return true;  
  else if (strcmp(suboption,"--lcs")==0) return true; 
  else if (strcmp(suboption,"--all")==0) return true; 
  else if (strcmp(suboption,"--sec")==0) return true; 
  else if (strcmp(suboption,"--a")==0) return true;
  else if (strcmp(suboption,"--s")==0) return true;
  else if (strcmp(suboption,"--fn")==0) return true;
  else if (strcmp(suboption,"--v")==0) return true;
  else if (strcmp(suboption,"--o")==0) return true;
  else if (strcmp(suboption,"--erp")==0) return true;
  else if (strcmp(suboption,"--drp")==0) return true;
  else if (strcmp(suboption,"--ewp")==0) return true;
  else if (strcmp(suboption,"--dwp")==0) return true;
  else if (strcmp(suboption,"--get")==0) return true;
  else if (strcmp(suboption,"--set")==0) return true;
  else if (strcmp(suboption,"--vals")==0) return true;
  else if (strcmp(suboption,"--RDP")==0) return true;
  else if (strcmp(suboption,"--User")==0) return true;
  else if (strcmp(suboption,"--Data0")==0) return true;
  else if (strcmp(suboption,"--Data1")==0) return true;
  else if (strcmp(suboption,"--WRP0")==0) return true;
  else if (strcmp(suboption,"--WRP1")==0) return true;
  else if (strcmp(suboption,"--WRP2")==0) return true;
  else if (strcmp(suboption,"--WRP3")==0) return true;
  else if (strcmp(suboption,"--Hi")==0) return true;
  else if (strcmp(suboption,"--Lo")==0) return true;
  else if (strcmp(suboption,"--ep")==0) return true; //ow
  else return false;
}

/*******************************************************************************************/
/* Function    : write_debug_info                                                          */
/* IN          :                                                                           */
/* OUT         :                                                                           */
/* Description : print the output messages on the standart output                          */
/*******************************************************************************************/
void write_debug_info(char *msg, int page, DWORD addr, float size, STATE status)
{
  char d_info[256];

  if((page==0) && (addr==0) && (size==0))
  {
    if(status == OK) 
      sprintf(d_info, "%s \t\t\t\t [OK] \n", msg);  
    else 
      sprintf(d_info, "%s \t\t\t\t [KO] \n", msg); 
  }
  else if(status == OK) 
    sprintf(d_info, "%s \t page %i \t @0x %8X \t size %.2f(KB) \t [OK] \n", msg, page, addr, (float)size);  
  else 
    sprintf(d_info, "%s \t page %i \t @0x %8X \t size %.2f(KB) \t [KO] \n", msg, page, addr, (float)size); 

  if((SHOW_OK && (status == OK)) || (SHOW_KO && (status == KO))) printf(d_info);
}

/*******************************************************************************************/
/* Function    : main                                                                      */
/* IN          :                                                                           */
/* OUT         :                                                                           */
/* Description :                                                                           */
/*******************************************************************************************/
int main(int argc, char* argv[])
{
  START:

  BYTE Res = SUCCESS;
  BYTE User, RDP, Data0, Data1, WRP0, WRP1, WRP2, WRP3;
  bool WaitForMoreSubOpt = TRUE;

  //Initializing default serial connection parameters
  int    portname   = 1;
  long   BaudRate   = 115200; //57600 ;
  int    DataBits   = 8;
  int    parity     = ParityToInt("EVEN"); 
  double nbStopBit  = 1;
  int    timeout    = 5000;
  bool   control    = false;

  int    nsec     = 0;
  DWORD  address  = 0x00000000;
  DWORD  size     = 0x00000000;
  char*  filename;
  char   devname[256] = "STM32_Low-density_32K.STmap";
  bool   Verify = FALSE;
  bool   optimize = FALSE;
  int    becho = 0;

  char Drive[3], Dir[256], Fname[256], Ext[256];
  char *ptr;

  int    productID = 0; //ow
  bool   EraseRequiredPages = false; //ow


  printf("\nSTMicroelectronics UART Flash Loader command line v2.6.0 \n");
  printf("modified by OlliW, v18.05.2014\n\n"); //ow

  if (argc == 1)  // wrong parameters
    man();
  else
  {
    int arg_index = 1;

    while(arg_index < argc)
    {
      if(!Is_Option(argv[arg_index])) 
      {
        if (arg_index < argc - 1) 
          printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

        if(COM_is_Open())  
           COM_Close();

        return 0;  /* return  with success */
      }

      //============================ Show the man =========================================
      if (strcmp(argv[arg_index],"-?")==0) 
      {
        man(); 
        return 0;
      }

      //=============================== connect ============================================
      else if (strcmp(argv[arg_index],"-c")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) // Set default connection settings and continue with the next option
            break;
         
          else if(Is_SubOption(argv[arg_index])) // Get connection settings
          {
            if (arg_index< argc-1) 
              arg_index++;
            else 
              break;

            if (strcmp(argv[arg_index-1],"--pn")==0)       portname = atoi(argv[arg_index]);//port name  (e.g COM1, COM2 ..., default COM1) \n");
            else if (strcmp(argv[arg_index-1],"--br")==0)  BaudRate = atoi(argv[arg_index]);//baud reate (e.g 115200, 128000 ..., default 57600) \n");
            else if (strcmp(argv[arg_index-1],"--db")==0)  DataBits = atoi(argv[arg_index]);//data bits  (in {5,6,7,8} ..., default 8) \n");
            else if (strcmp(argv[arg_index-1],"--pr")==0)  parity   = ParityToInt(argv[arg_index]); //parity     (in {NONE,ODD,EVEN} ..., default EVEN) \n");
            else if (strcmp(argv[arg_index-1],"--sb")==0)  nbStopBit= atof(argv[arg_index]);//stop bits  (in {1,1.5,2} ..., default 1) \n");
            else if (strcmp(argv[arg_index-1],"--to")==0)  timeout  = atoi(argv[arg_index]);//time out   (e.g 1000, 2000, 3000 ..., default 5) \n");
            else if (strcmp(argv[arg_index-1],"--ec")==0)  becho  = ModeToInt(argv[arg_index]); // Echo back mode, default is OFF \n");
            else if (strcmp(argv[arg_index-1],"--co")==0)  control  = StatusToBool(argv[arg_index]); // Outputs Control ON/OFF, default is OFF \n");
          }
          else 
          {
            printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }

        // Apply serial connection settings
        TARGET_SetComIntType(0);
        SetCOMSettings(portname, BaudRate, DataBits, parity, nbStopBit);
        STBL_SetFlowControl(control);

        // Opening serial connection
        Res = COM_Open();
        SetTimeOut(1000);

        if (control== true)
        {
          /* Just for debug purposes */
        }

        if ((Res != SUCCESS) && (Res != COM_ALREADY_OPENED)) 
        {
          write_debug_info("Opening Port", 0 ,0, 0, KO);
          printf("ERROR: Cannot open the com port, the port may \nbe used by another application \n");

          if(COM_is_Open())  
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }
        else
          write_debug_info("Opening Port", 0 ,0, 0, OK);
       
        STBL_SetEcho(becho);  // Setting Echo back mode
      }

      //============================ command RTS pin =======================================
      else if (strcmp(argv[arg_index],"-Rts")==0)
      {
        //_sleep(1000);
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++; 
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;
          else if(Is_SubOption(argv[arg_index]))
          {
            if (strcmp(argv[arg_index],"--Hi")==0) 
            {
              write_debug_info("Set RTS line", 0 ,0, 0,OK);
              STBL_SetRts(TRUE); 
              Sleep(100);
            }
            else if (strcmp(argv[arg_index],"--Lo")==0)  
            {
              write_debug_info("Reset RTS line", 0 ,0, 0,OK);
              STBL_SetRts(FALSE);
              Sleep(100);
            }
            else 
            {
              write_debug_info("ERROR: bad parameter [Set RTS line] should be Hi or Lo ", 0 ,0, 0,KO);

              if (arg_index < argc - 1) 
                printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

              if(COM_is_Open()) 
                COM_Close(); 

              printf("\nPress any key to continue ...\n"); 
              _getch(); 
              return 1;
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }
      }

      //============================ command DTR pin =======================================
      else if (strcmp(argv[arg_index],"-Dtr")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;

          else if(Is_SubOption(argv[arg_index]))
          {
            if (strcmp(argv[arg_index],"--Hi")==0) 
            {
              write_debug_info("Set DTR line", 0 ,0, 0,OK);
              STBL_SetDtr(TRUE);
              Sleep(100);
            }
            else if (strcmp(argv[arg_index],"--Lo")==0)  
            {
              write_debug_info("Reset DTR line", 0 ,0, 0,OK);
              STBL_SetDtr(FALSE);
              Sleep(100);
            }
            else 
            {
              write_debug_info("ERROR: bad parameter [Set DTR line] should be Hi or Lo ", 0 ,0, 0,KO);

              if (arg_index < argc - 1) 
                printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

              if(COM_is_Open())  
                COM_Close(); 

              printf("\nPress any key to continue ...\n"); 
              _getch(); 
              return 1;
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 
  
            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }
      }
 
      //============================ ERASE =================================================
      else if (strcmp(argv[arg_index],"-e")==0)
      {
        while(arg_index < argc)
        {
          if (!WaitForMoreSubOpt) 
            break;
         
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;

          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            //******************** This section is only for STM8 boot loader *******************
            BYTE Version;
            Commands pCmds;
             CString m_Version;
             if (STBL_GET(&Version, &pCmds) == SUCCESS)
             {
              m_Version.Format("%x.%x",Version/16, Version & 0x0F)  ;
             }  
             CIni Ini((LPCSTR)MapFile);

             if(Ini.IsKeyExist((LPCTSTR)"Product",(LPCTSTR)m_Version))
             {
               CString E_W_ROUTINEs = Ini.GetString((LPCTSTR)"Product",(LPCTSTR)m_Version, "");
               CString Path(*__argv);

               char fullPath [MAX_PATH];

               GetModuleFileName(0, fullPath, (MAX_PATH));

               Path=fullPath;

               int j=Path.ReverseFind('\\')+1;
               if(j) Path=Path.Left(j);

               CString ToFind;

               ToFind.Format("%s%s%s", Path, "STM8_Routines\\", E_W_ROUTINEs);

               if(!E_W_ROUTINEs.IsEmpty())
               {
                 if(!FileExist((LPCTSTR)ToFind))
                 {
                   printf("\nWARNING: The erase or download operation may fail \n EW routines file is missing [%s]\n", ToFind); 
                 }
                 else
                 {
                  HANDLE Image;
                  if (FILES_ImageFromFile((LPSTR)(LPCSTR)ToFind,&Image, 1)== FILES_NOERROR)
                  {
                    FILES_SetImageName(Image,(LPSTR)(LPCSTR)ToFind);

                    DWORD NbElements; 
                    if (FILES_GetImageNbElement(Image, &NbElements) == FILES_NOERROR)
                    {
                      for (int el=0; el< (int)NbElements;el++)
                      {
                        IMAGEELEMENT Element={0};
                        if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                        {     
                          Element.Data=new BYTE[Element.dwDataLength];
                          if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                          {
                            if (STBL_DNLOAD(Element.dwAddress, Element.Data, Element.dwDataLength, FALSE) != SUCCESS)
                            {
                                
                            }
                          }
                        }
                      }

                      // Verify writen data
                      BOOL VerifySuccess = TRUE;
                      _sleep(100);;
//#ifndef _VS6_USED
                      int el;
//#endif
                      for (el=0; el< (int)NbElements;el++)
                      {
                        IMAGEELEMENT Element={0};
                        if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                        {
                          Element.Data=new BYTE[Element.dwDataLength];
                          if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                          {
                            if (STBL_VERIFY(Element.dwAddress, Element.Data, Element.dwDataLength, FALSE) != SUCCESS)
                            {
                              VerifySuccess = FALSE;
                              char str[255];
                              sprintf(str, "%s at address :0x%X. \n%s \nPlease disable the write protection then try agin.", "Data not matching ", Element.dwAddress, "The page may be write protected.");   
                              AfxMessageBox(str, MB_OK|MB_ICONEXCLAMATION);
                              return 1;
                            }
                          }
                        }
                      }
                    }
                  }
                      else
                  {
                     AfxMessageBox("Unable to load data from this file " + ToFind + " ...");
                     return -1;
                  }
                 }
               }
             }
             else
             {
               int family = Ini.GetInt((LPCTSTR)"Product",(LPCTSTR)"family", 0);
               if(family == 3)
               {
                 printf("\nWARNING: The erase or download operation may fail \n EW routines file is missing\n"); 
               }
             }
            //End****************** This section is only for STM8 boot loader *******************


            printf("\n ERASING ... \n");
            if (strcmp(argv[arg_index-1],"--all")==0)   
            {
              WaitForMoreSubOpt = false;
              Res = STBL_ERASE(0xFFFF, NULL);
              if (Res != SUCCESS) 
                write_debug_info("erasing all pages", 0 ,0, 0, KO);
              else 
                write_debug_info("erasing all pages", 0 ,0, 0, OK);
            }
            else if (strcmp(argv[arg_index-1],"--sec")==0) 
            {
              WaitForMoreSubOpt = true;

              nsec = atoi(argv[arg_index]);
              LPWORD sectors = (LPWORD)malloc(nsec *2 + 2);

              sectors[0] = 0;
              for(int i = 1; i<= nsec; i++)
              {
                sectors[0]++;
                arg_index++;
                sectors[sectors[0]] = atoi(argv[arg_index]);
              }

              WaitForMoreSubOpt = false;

              printf("\nerasing %i sectors : ", sectors[0]);

//#ifndef _VS6_USED
            int i;
//#endif
              for(i = 1; i<= nsec; i++)
              {
                printf("<%i>", sectors[i]);
              }
              printf("\n");

              Res = STBL_ERASE(nsec, (LPBYTE)sectors+2);
              if (Res != SUCCESS)  
              {
                write_debug_info("erasing", 0 ,0, 0, KO);
               
                if(COM_is_Open())  
                  COM_Close(); 
               
                printf("\nPress any key to continue ...\n"); 
                _getch(); 
                return 1;
              }
              else 
                write_debug_info("erasing", 0 ,0, 0, OK);

              arg_index++;
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }
      }

      //============================ UPLOAD ===============================================
      else if (strcmp(argv[arg_index],"-u")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;
 
          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            /*if (strcmp(argv[arg_index-1],"--a")==0)   
            {
              address = _tcstoul(argv[arg_index], 0, 16) ;
            }
            else if (strcmp(argv[arg_index-1],"--s")==0) 
            {
              size = _tcstoul(argv[arg_index], 0, 16) ;
            }
            else */if (strcmp(argv[arg_index-1],"--fn")==0) 
            {
              filename = argv[arg_index];
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }

        printf("\n UPLOADING ... \n\n");

        HANDLE Handle;
        FILES_CreateImage(&Handle, 0);

        FILES_CreateImageFromMapping(&Handle,pmMapping);

        DWORD NbElements = 0;
        if (FILES_GetImageNbElement(Handle, &NbElements) == FILES_NOERROR)
        {
          if (NbElements > 0)
          {
            for(int i = 0; i< (int)NbElements; i++)
            {
              IMAGEELEMENT Element={0};
              // Get element data size
              if (FILES_GetImageElement(Handle, i, &Element) == FILES_NOERROR)
              {
                //Upload element data
                Element.Data = (LPBYTE)malloc(Element.dwDataLength);
                if (STBL_UPLOAD(Element.dwAddress, Element.Data, Element.dwDataLength) == SUCCESS)
                {
                  //Insert elment in the Image
                  write_debug_info("Uploading", i ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, OK);
                  FILES_SetImageElement(Handle,i,FALSE,Element);
                }
                else 
                {
                  write_debug_info("Uploading", i ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, KO);
                    
                  if(COM_is_Open())  
                    COM_Close(); 
                    
                  printf("\nPress any key to continue ...\n"); 
                  _getch(); 
                  return 1;
                }
              }
            }
          }
        }

        if(!FileExist((LPCTSTR)filename))
        {
          printf( "file %s does not exist .. Creating file\n", filename);
          FILE* fp = fopen((LPCTSTR)filename, "a+");
          fclose(fp);
        }

        printf( "Writing data ...\n");

        if (FILES_ImageToFile((LPSTR)(LPCSTR)filename,Handle) != FILES_NOERROR)
        {
          printf( "ERROR: Cannot write to file %s \n", filename);
           
          if(COM_is_Open())  
           COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }
        else
          printf("\n Uploaded data is dumped on %s\n", filename); 

      }

      //============================ Get Device map file name ==============================
      else if (strcmp(argv[arg_index],"-i")==0)
      {
        if (arg_index< argc) 
          arg_index++;
        else 
          break;

        sprintf(devname,"%s.STmap", argv[arg_index]);

        char Drive[3], Dir[256], Fname[256], Ext[256];
        _splitpath(argv[0],Drive,Dir,Fname,Ext);
          
        sprintf(MapFile, "%s%s%s%s", Drive, Dir , "Map\\", devname);

        WORD PacketSize = 0;
        pmMapping = NULL;
        WORD Size = 0;
        char MapName[256]; 
        // Get the number of sectors in the flash target: pmMapping should be NULL
        // number of sectors is returned in the Size value
        BYTE PagePerSector = 0;

        if (!FileExist((LPCTSTR)MapFile))
        {
          printf("ERROR: This version does not support the <%s> target\n", argv[arg_index]);
          
          if(COM_is_Open())  
            COM_Close();

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }

        FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pmMapping, &PagePerSector);
        // Allocate the mapping structure memory
        pmMapping = (PMAPPING)malloc(sizeof(MAPPING));
        pmMapping->NbSectors = 0;
        pmMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR));

        // Get the mapping info
        FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pmMapping, &PagePerSector);
           
        SetPaketSize(PacketSize);

        //sending BL config byte (0x7F) & identifing target
        Res = STBL_Init_BL();
        if (Res == UNREOGNIZED_DEVICE)
        {
          write_debug_info("Activating device", 0 ,0, 0, KO);

          printf("ERROR: Unrecognized device.\n");
          printf("Please, reset your device and then try again.\n");

          if(COM_is_Open()) 
            COM_Close();

          printf("\nPress any key to continue ...\n\n"); 
          _getch();
          goto START;
        }
        else if (Res != SUCCESS)     
        {
          write_debug_info("Activating device", 0 ,0, 0, KO);
          printf("ERROR: No response from the target, the Bootloader cannot be started.\n");
		      printf("Please, verify the boot mode configuration, reset your device then try again.\n");
          
          if(COM_is_Open()) 
            COM_Close(); 
          
          printf("\nPress any key to continue ...\n\n"); 
          _getch();
          goto START;
        }

        _sleep(TimeBO);
         
        write_debug_info("Activating device", 0 ,0, 0, OK);
         
        //Getting Target informations (version, available commands)
        BYTE Version ;
        Commands pCmds;

        Res = STBL_GET(&Version, &pCmds);
        if (Res != SUCCESS)
        {
          if(COM_is_Open()) 
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1; 
        }

        printf( "Bootloader version %X\n", Version ); //ow

        SetTimeOut(timeout);

        /* */
         
        family = 0; // STM32F1 is selected by default
        DWORD PID = 0x00000000;
        ADDR_XX_OPB = ADDR_F1_OPB ;

        if (GetAckValue() == ST75)
          family = 1;  // STR750 is selected 
        else if (GetAckValue() == ST79)   // STM32, STR911 or STM8 is used, need to check other criteria    
        {   
          if (!pCmds.GET_ID_CMD)  // check if the GET ID command is available
          {         
            family = 2;  // STM8 is used
          }
          else
          {     // STM32 or STR911 is used
            BYTE size = 0x00;
            LPBYTE pID;  //Get the Device ID
            //Get the ID size in bytes before 
            if (STBL_GET_ID(&size,NULL) == SUCCESS)
            {
              pID = (LPBYTE)malloc(size);
            
              if (STBL_GET_ID(&size,pID) == SUCCESS) // Get the ID
              {
                for(int i=0; i<size; i++)
                {
                  PID = PID << 8;
                  PID = PID + (pID[i]);
                }

                if(PID == 0x25966041) 
                {
                  family = 3; // STR911 is used 
                }
                else if((PID == 0x416) || (PID == 0x436) || (PID == 0x427)) 
                {
                  family = 4; // STM32L is used 
                  ADDR_XX_OPB = ADDR_L1_OPB ;
                }
                else if(PID == 0x411 || (PID == 0x413) || (PID == 0x419)) 
                {
                  family = 5; // STM32F2 or F4 is used 
                  ADDR_XX_OPB = ADDR_F2_OPB ;
                }
                else if ((PID == 0x440) || (PID == 0x432) || (PID == 0x422) ||(PID == 0x444)) 
                {
                  family = 6; // STM32F0 or F3 is used 
                  ADDR_XX_OPB = ADDR_F0_OPB;
                }
        
              }
            }
          }
        }

        /**/

        if (arg_index< argc) 
          arg_index++;
        else 
          break;
      }

      //============================ DOWNLOAD ==============================================
      else if (strcmp(argv[arg_index],"-d")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;

          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            if (strcmp(argv[arg_index-1],"--a")==0)   
            {
              address = _tcstoul(argv[arg_index], 0, 16) ;
            }
            else if (strcmp(argv[arg_index-1],"--v")==0) 
            {
              Verify = true;
              arg_index--;
            }
            else if (strcmp(argv[arg_index-1],"--o")==0) 
            {
              optimize = TRUE;
              arg_index--;
            }
            else if (strcmp(argv[arg_index-1],"--ep")==0) //ow
            {                                             //ow
              EraseRequiredPages = true;                  //ow
              arg_index--;                                //ow
            }                                             //ow 
            else if (strcmp(argv[arg_index-1],"--fn")==0) 
            {
              filename = argv[arg_index];
              _splitpath(filename,Drive,Dir,Fname,Ext);
              ptr=strupr(Ext);
              strcpy(Ext, ptr);
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }

        PMAPPINGSECTOR pSector = pmMapping->pSectors;
        for(int i = 1; i<= (int)pmMapping->NbSectors; i++)
        {
          if ((strcmp(Ext, ".BIN")!=0) && (i==0))
            address = pSector->dwStartAddress;

          pSector->UseForOperation = TRUE;
          pSector++;
        }

        if(!FileExist((LPCTSTR)filename))
        {
          printf( "ERROR: file does not exist %s \n", filename);

          if(COM_is_Open())  
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }
   
        //****************** This section is only for STM8 boot loader *******************
        BYTE Version;
        Commands pCmds;
        CString m_Version;
        if (STBL_GET(&Version, &pCmds) == SUCCESS)
         {
          m_Version.Format("%x.%x",Version/16, Version & 0x0F)  ;
         }  
         CIni Ini((LPCSTR)MapFile);

         if(Ini.IsKeyExist((LPCTSTR)"Product",(LPCTSTR)m_Version))
         {
           CString E_W_ROUTINEs = Ini.GetString((LPCTSTR)"Product",(LPCTSTR)m_Version, "");
           CString Path(*__argv);
           int j=Path.ReverseFind('\\')+1;
           if(j) Path=Path.Left(j);

           CString ToFind;

           ToFind.Format("%s%s%s", Path, "STM8_Routines\\", E_W_ROUTINEs);

           if(!E_W_ROUTINEs.IsEmpty())
           {
             if(!FileExist((LPCTSTR)ToFind))
             {
               printf("\n!WARNING the erase or download operation may fail \n EW routines file is missing [%s]\n", ToFind); 
             }
             else
             {
              HANDLE Image;
              if (FILES_ImageFromFile((LPSTR)(LPCSTR)ToFind,&Image, 1)== FILES_NOERROR)
              {
                FILES_SetImageName(Image,(LPSTR)(LPCSTR)ToFind);

                DWORD NbElements; 
                if (FILES_GetImageNbElement(Image, &NbElements) == FILES_NOERROR)
                {
                  for (int el=0; el< (int)NbElements;el++)
                  {
                    IMAGEELEMENT Element={0};
                    if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                    {     
                      Element.Data=new BYTE[Element.dwDataLength];
                      if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                      {
                        if (STBL_DNLOAD(Element.dwAddress, Element.Data, Element.dwDataLength, FALSE) != SUCCESS)
                        {
                            
                        }
                      }
                    }
                  }

                  // Verify writen data
                  BOOL VerifySuccess = TRUE;
                  _sleep(100);
//#ifndef _VS6_USED
                  int el;
//#endif
                  for (el=0; el< (int)NbElements;el++)
                  {
                    IMAGEELEMENT Element={0};
                    if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                    {
                      Element.Data=new BYTE[Element.dwDataLength];
                      if (FILES_GetImageElement(Image, el, &Element) == FILES_NOERROR)
                      {
                        if (STBL_VERIFY(Element.dwAddress, Element.Data, Element.dwDataLength, FALSE) != SUCCESS)
                        {
                          VerifySuccess = FALSE;
                          char str[255];
                          sprintf(str, "%s at address :0x%X. \n%s \nPlease disable the write protection then try agin.", "Data not matching ", Element.dwAddress, "The page may be write protected.");   
                          AfxMessageBox(str, MB_OK|MB_ICONEXCLAMATION);
                          return 1;
                        }
                      }
                    }
                  }
                }
              }
                  else
              {
                 AfxMessageBox("Unable to load data from this file " + ToFind + " ...");
                 return -1;
              }
             }
           }
         }
         else
         {
           int family = Ini.GetInt((LPCTSTR)"Product",(LPCTSTR)"family", 0);
           if(family == 3)
           {
            printf("\n!WARNING the erase or download operation may fail \n EW routines file is missing\n"); 
           }
        }
        //End****************** This section is only for STM8 boot loader *******************

        printf("\n DOWNLOADING ... \n\n");

        HANDLE Handle;
        if (FILES_ImageFromFile((LPSTR)(LPCSTR)filename,&Handle, 1) == FILES_NOERROR)
        {
          FILES_SetImageName(Handle,(LPSTR)(LPCSTR)filename);

          DWORD NbElements = 0;
          if (FILES_GetImageNbElement(Handle, &NbElements) == FILES_NOERROR)
          {
            if ( NbElements > 0 )
            {   // if binary file -> change the elemnts address
              if (strcmp(Ext, ".BIN")==0)
              {
                for (int i=0;i< (int)NbElements;i++)
                {
                  IMAGEELEMENT Element={0};
                  if (FILES_GetImageElement(Handle, i, &Element) == FILES_NOERROR)
                  {
                    Element.Data= (LPBYTE)malloc(Element.dwDataLength);
                    if (FILES_GetImageElement(Handle, i, &Element) == FILES_NOERROR)
                    {
                      Element.dwAddress = Element.dwAddress + address; 
                      FILES_SetImageElement(Handle, i, FALSE, Element);
                    }
                  }
                }
              }
            }
          }

          FILES_FilterImageForOperation(Handle, pmMapping, OPERATION_UPLOAD, optimize);
        }
        else 
        {  
          printf("ERROR: Cannot open file %s \n", filename);

          if(COM_is_Open())  
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }

        DWORD NbElements = 0;
//ow ---------------
        bool DoDownload = true;

        if (FILES_GetImageNbElement(Handle, &NbElements) == FILES_NOERROR)
        {
          //copied from erase --sec section
          if (EraseRequiredPages){
              nsec = (int)NbElements;
              LPWORD sectors = (LPWORD)malloc(nsec *2 + 2);

              sectors[0] = 0;
              for(int i = 1; i<= nsec; i++)
              {
                sectors[0]++;
                sectors[sectors[0]] = i-1;
              }

              printf("erasing %i sectors : pages <0> to <%i>\n", sectors[0], (int)(NbElements-1));

              Res = STBL_ERASE(nsec, (LPBYTE)sectors+2);
              if (Res != SUCCESS)  
              {
                write_debug_info("erasing", 0 ,0, 0, KO);
               
                if(COM_is_Open())  
                  COM_Close(); 
               
                printf("\nPress any key to continue ...\n"); 
                _getch(); 
                return 1;
              }
              else 
                write_debug_info("erasing", 0 ,0, 0, OK);
          }
        }else{
          DoDownload = false;
          Verify = false;
        }

        if (DoDownload)
//ow-end---------------------
        {
          for (int el=0; el< (int)NbElements;el++)
          {
            IMAGEELEMENT Element={0};
            if (FILES_GetImageElement(Handle, el, &Element) == FILES_NOERROR)
            {     
              Element.Data= (LPBYTE)malloc(Element.dwDataLength);
              if (FILES_GetImageElement(Handle, el, &Element) == FILES_NOERROR)
              {
                if ((strcmp(Ext, ".BIN")==0) && (el==0)) 
                  Element.dwAddress = address;
                
                if (STBL_DNLOAD(Element.dwAddress, Element.Data, Element.dwDataLength, optimize) != SUCCESS)
                {
                  write_debug_info( "downloading", el ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, KO);
                  write_debug_info("ERROR: The flash may be read protected; use -p --drp to disable write protection." , 0, 0, 0, KO);
                  
                  if(COM_is_Open())
                    COM_Close(); 
                  
                  printf("\nPress any key to continue ...\n"); 
                  _getch(); 
                  return 1;
                }

                write_debug_info( "downloading", el ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, OK);
              }
            }
          }
        }

        bool VerifySuccess = true;
        if (Verify)
        {
          printf("\n VERIFYING ... \n\n");

          for (int el=0; el< (int)NbElements;el++)
          {
            IMAGEELEMENT Element={0};
            if (FILES_GetImageElement(Handle, el, &Element) == FILES_NOERROR)
            {
              Element.Data=(LPBYTE)malloc(Element.dwDataLength);
              if (FILES_GetImageElement(Handle, el, &Element) == FILES_NOERROR)
              {
                if ((strcmp(Ext, ".BIN")==0) && (el==0)) 
                  Element.dwAddress = address;

                if (STBL_VERIFY(Element.dwAddress, Element.Data, Element.dwDataLength, optimize) != SUCCESS)
                {
                  VerifySuccess = false;
                  write_debug_info("verifying" ,el ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, KO);
                  write_debug_info("ERROR: some pages may be write protected; use -p --dwp to disable write protection." , 0, 0, 0, KO);
                  
                  if(COM_is_Open())  
                    COM_Close(); 
                 
                  printf("\nPress any key to continue ...\n"); 
                  _getch(); 
                  return 1;
                }

                write_debug_info("verifying" ,el ,Element.dwAddress, (float)Element.dwDataLength/(float)1024, OK);
              }
            }
          }
        }
      }

      //============================ VERIFY ================================================
      else if (strcmp(argv[arg_index],"-v")==0)
      {
        if (arg_index< argc) 
          arg_index++;
        else 
          break;
      }

      //============================ Program option bytes ==================================
      else if (strcmp(argv[arg_index],"-o")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;

          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            if (strcmp(argv[arg_index-1],"--get")==0) 
            {
              if (arg_index< argc) 
                arg_index++;
              else 
                break;
                           
              if (strcmp(argv[arg_index-1],"--fn")==0) 
                filename = argv[arg_index];
             
              if(TARGET_GetOptionBytes(ADDR_XX_OPB, &User, &RDP, &Data0, &Data1, &WRP0, &WRP1, &WRP2, &WRP3) == SUCCESS)
              {
                write_debug_info("Getting Option bytes  data" ,0 ,0, 0, OK);

                HANDLE Image;
                if (FILES_CreateImage(&Image, 1) == FILES_NOERROR)
                {
                  IMAGEELEMENT Element={0};
                  Element.dwAddress   = ADDR_XX_OPB;
                  Element.dwDataLength = 16;
                  Element.Data = (LPBYTE)malloc(Element.dwDataLength);
                
                  if ((ADDR_XX_OPB == ADDR_F1_OPB) || ADDR_XX_OPB == ADDR_F0_OPB )
                  {
                    Element.Data[0]  = RDP;
                    Element.Data[1]  = ~RDP;
                    Element.Data[2]  = User;
                    Element.Data[3]  = ~User;
                    Element.Data[4]  = Data0;
                    Element.Data[5]  = ~Data0;
                    Element.Data[6]  = Data1;
                    Element.Data[7]  = ~Data1;
                    Element.Data[8]  = WRP0;
                    Element.Data[9]  = ~WRP0;
                    Element.Data[10] = WRP1;
                    Element.Data[11] = ~WRP1;
                    Element.Data[12] = WRP2;
                    Element.Data[13] = ~WRP2;
                    Element.Data[14] = WRP3;
                    Element.Data[15] = ~WRP3;
                  }
                  else  if (ADDR_XX_OPB == ADDR_L1_OPB )
                  {
                    Element.Data[0]  = RDP;
                    Element.Data[1]  = 0x00;
                    Element.Data[2]  = ~RDP;
                    Element.Data[3]  = 0xFF;
                    Element.Data[4]  = User;
                    Element.Data[5]  = 0x00;
                    Element.Data[6]  = ~User;
                    Element.Data[7]  = 0xFF;
                    Element.Data[8]  = WRP0;
                    Element.Data[9]  = WRP1;
                    Element.Data[10] = ~WRP0;
                    Element.Data[11] = ~WRP1;
                    Element.Data[12] = WRP2;
                    Element.Data[13] = WRP3;
                    Element.Data[14] = ~WRP2;
                    Element.Data[15] = ~WRP3;
                  }
                  else  if (ADDR_XX_OPB == ADDR_F2_OPB )
                  {
                    Element.Data[0]  = User;
                    Element.Data[1]  = RDP;
                    Element.Data[2]  = 0xFF;
                    Element.Data[3]  = 0xFF;
                    Element.Data[4]  = 0xFF;
                    Element.Data[5]  = 0xFF;
                    Element.Data[6]  = 0xFF;
                    Element.Data[7]  = 0xFF;
                    Element.Data[8]  = WRP0;
                    Element.Data[9]  = WRP1;
                    Element.Data[10] = 0xFF;
                    Element.Data[11] = 0xFF;
                    Element.Data[12] = 0xFF;
                    Element.Data[13] = 0xFF;
                    Element.Data[14] = 0xFF;
                    Element.Data[15] = 0xFF;
                  }
 
                  FILES_SetImageElement(Image,0,TRUE,Element);
                  if (FILES_ImageToFile((LPSTR)(LPCSTR)filename,Image) != FILES_NOERROR)
                  {
                    write_debug_info("Saving Option bytes  data",0 ,0, 0, KO);
                  }
                  else  
                    write_debug_info("Saving Option bytes  data",0 ,0, 0, OK); 
                }
              }
              else 
                write_debug_info("Getting Option bytes  data" ,0 ,0, 0, KO);
            }
            else if (strcmp(argv[arg_index-1],"--set")==0) 
            {
              if (arg_index< argc) 
                arg_index++;
              else 
                break;
                           
              if (strcmp(argv[arg_index-1],"--fn")==0) 
              {
                filename = argv[arg_index];

                HANDLE OPBImage;

                if(!FileExist((LPCTSTR)filename))
                {
                  printf( "file does not exist %s \n", filename);
                   
                  if(COM_is_Open())  
                    COM_Close(); 
                    
                  printf("\n Press any key to continue ...\n"); 
                  _getch(); 
                  return 1;
                }

                if (FILES_ImageFromFile((LPSTR)(LPCSTR)filename, &OPBImage, 0) == FILES_NOERROR)
                {
                  DWORD NbElements = 0;
                  if (FILES_GetImageNbElement(OPBImage, &NbElements) == FILES_NOERROR)
                  {
                    if ( NbElements == 1 )
                    {
                      IMAGEELEMENT Element={0};
                      if (FILES_GetImageElement(OPBImage, 0, &Element) == FILES_NOERROR)
                      {
                        Element.Data= (LPBYTE)malloc(Element.dwDataLength);
                        if (FILES_GetImageElement(OPBImage, 0, &Element) == FILES_NOERROR)
                        {
                          
                          if ((ADDR_XX_OPB == ADDR_F1_OPB) || (ADDR_XX_OPB == ADDR_F0_OPB ))
                          {
                            RDP   = Element.Data[0] ;
                            User  = Element.Data[2] ;
                            Data0 = Element.Data[4] ;
                            Data1 = Element.Data[6] ;
                            WRP0  = Element.Data[8] ;
                            WRP1  = Element.Data[10];
                            WRP2  = Element.Data[12];
                            WRP3  = Element.Data[14];
                          } 
                          else if (ADDR_XX_OPB == ADDR_L1_OPB )
                          {
                            RDP   = Element.Data[0] ;
                            User  = Element.Data[4];
                            Data0 = 0x00;
                            Data1 = 0x00;
                            WRP0  = Element.Data[8];
                            WRP1  = Element.Data[9];
                            WRP2  = Element.Data[12];
                            WRP3  = Element.Data[13];
                          }
                          else if (ADDR_XX_OPB == ADDR_F2_OPB )
                          {
                            RDP   = Element.Data[1] ;
                            User  = Element.Data[0];
                            Data0 = 0xFF;
                            Data1 = 0xFF;
                            WRP0  = Element.Data[8];
                            WRP1  = Element.Data[9];
                            WRP2  = 0xFF;
                            WRP3  = 0xFF;
                          }
                          
                          if (TARGET_SetOptionBytes(ADDR_XX_OPB, User, RDP, Data0, Data1, WRP0, WRP1, WRP2, WRP3) == SUCCESS)
                          {
                            write_debug_info("Setting Option bytes  data" ,0 ,0, 0, OK);
 
                            if(COM_is_Open())  
                              COM_Close();

                            COM_Open();

                            if(STBL_Init_BL() != SUCCESS) 
                              write_debug_info("Resetting device" ,0 ,0, 0, KO);
                            else 
                              write_debug_info("Resetting device" ,0 ,0, 0, OK);
                          }
                          else 
                            write_debug_info("Setting Option bytes  data" ,0 ,0, 0, KO);
                        }
                      }
                    }
                  }
                }
              }
              else if (strcmp(argv[arg_index-1],"--vals")==0) 
              {
                TARGET_GetOptionBytes(ADDR_XX_OPB, &User, &RDP, &Data0, &Data1, &WRP0, &WRP1, &WRP2, &WRP3);
                               
                while(arg_index< argc)
                {
                  if(Is_Option(argv[arg_index])) 
                    break;
                  else if(Is_SubOption(argv[arg_index]))
                  {
                    arg_index++;
                    if(strcmp(argv[arg_index-1],"--RDP")==0)       { RDP   = _tcstoul(argv[arg_index], 0, 16);arg_index++;}
                    else if(strcmp(argv[arg_index-1],"--User")==0) { User  = _tcstoul(argv[arg_index], 0, 16);arg_index++;} 
                    else if(strcmp(argv[arg_index-1],"--data0")==0){ Data0 = _tcstoul(argv[arg_index], 0, 16);arg_index++;}
                    else if(strcmp(argv[arg_index-1],"--data1")==0){ Data1 = _tcstoul(argv[arg_index], 0, 16);arg_index++;} 
                    else if(strcmp(argv[arg_index-1],"--WRP0")==0) { WRP0  = _tcstoul(argv[arg_index], 0, 16);arg_index++;} 
                    else if(strcmp(argv[arg_index-1],"--WRP1")==0) { WRP1  = _tcstoul(argv[arg_index], 0, 16);arg_index++;}
                    else if(strcmp(argv[arg_index-1],"--WRP2")==0) { WRP2  = _tcstoul(argv[arg_index], 0, 16);arg_index++;}
                    else if(strcmp(argv[arg_index-1],"--WRP3")==0) { WRP3  = _tcstoul(argv[arg_index], 0, 16);arg_index++;}
                  }
                }
                if (TARGET_SetOptionBytes(ADDR_XX_OPB,User, RDP, Data0, Data1, WRP0, WRP1, WRP2, WRP3) != SUCCESS)
                  write_debug_info("Setting Option bytes  data" ,0 ,0, 0, KO);
                else
                {
                  write_debug_info("Setting Option bytes  data" ,0 ,0, 0, OK);

                  if(COM_is_Open())  
                    COM_Close();

                  COM_Open();

                  if(STBL_Init_BL() != SUCCESS) 
                    write_debug_info("Resetting device" ,0 ,0, 0, KO);
                  else 
                    write_debug_info("Resetting device" ,0 ,0, 0, OK);
                }
                arg_index--;
              }
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }
      }

      //============================ Set/Unset R/W protection ==========================
      else if (strcmp(argv[arg_index],"-p")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;
          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            if (strcmp(argv[arg_index-1],"--erp")==0) 
            {
              if(STBL_READOUT_PROTECT() != SUCCESS) 
                write_debug_info( "enabling read protection", 0 , 0, 0, KO);
              else 
                write_debug_info( "enabling read protection", 0 , 0, 0, OK);
          
              _sleep(TimeBO);

              if(STBL_Init_BL() != SUCCESS) 
                write_debug_info( "reseting device", 0 , 0, 0, KO);
              else 
                write_debug_info( "reseting device", 0 , 0, 0, OK);

              arg_index--;
            }
            else if (strcmp(argv[arg_index-1],"--drp")==0) 
            {
              if(STBL_READOUT_PERM_UNPROTECT() == SUCCESS) 
              {
                write_debug_info( "disabling read protection", 0 , 0, 0, OK);

                _sleep(TimeBO);

                if(STBL_Init_BL() != SUCCESS) 
                  write_debug_info( "reseting device", 0 , 0, 0, KO);
                else 
                  write_debug_info( "reseting device", 0 , 0, 0, OK);
              }
              else 
                write_debug_info( "disabling read protection", 0 , 0, 0, KO);
             
              arg_index--;
            }
            else if (strcmp(argv[arg_index-1],"--ewp")==0) 
            {
              LPBYTE sectors;
              if(Is_Option(argv[arg_index])) break;

              nsec = atoi(argv[arg_index]);
              sectors = (LPBYTE)malloc(nsec + 1);

              sectors[0] = 0;
              for(int i = 1; i<= nsec; i++)
              {
                sectors[0]++;
                arg_index++;
                sectors[sectors[0]] = atoi(argv[arg_index]);
              }


              printf("\nenabling write protection %i sectors : ", sectors[0]);

//#ifndef _VS6_USED
            int i;
//#endif
              for(i = 1; i<= nsec; i++)
              {
                printf("<%i>", sectors[i]);
              }
              printf("\n");

              if(STBL_WRITE_PROTECT(((LPBYTE)sectors)[0],&((LPBYTE)sectors)[1]) != SUCCESS) 
                write_debug_info( "enabling write protection", 0 , 0, 0, KO);
              else 
                write_debug_info( "enabling write protection", 0 , 0, 0, OK);
             
              _sleep(TimeBO);

              if(STBL_Init_BL() != SUCCESS) 
                write_debug_info( "reseting device", 0 , 0, 0, KO);
              else 
                write_debug_info( "reseting device", 0 , 0, 0, OK);
            }
            else if (strcmp(argv[arg_index-1],"--dwp")==0) 
            {
              if(STBL_WRITE_PERM_UNPROTECT() != SUCCESS) 
                write_debug_info( "disabling write protection", 0 , 0, 0, KO);
              else 
                write_debug_info( "disabling write protection", 0 , 0, 0, OK);
             
              _sleep(TimeBO);

              if(STBL_Init_BL() != SUCCESS) 
                write_debug_info( "reseting device", 0 , 0, 0, KO);
              else 
                write_debug_info( "reseting device", 0 , 0, 0, OK);
              arg_index--;
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }
        }
      }

      //============================ Run at address ========================================
      else if (strcmp(argv[arg_index],"-r")==0)
      {
        while(arg_index < argc)
        {
          if (arg_index< argc-1) 
            arg_index++;
          else 
            break;

          if(Is_Option(argv[arg_index])) 
            break;
          else if(Is_SubOption(argv[arg_index]))
          {
            if (arg_index< argc) 
              arg_index++;
            else 
              break;

            PMAPPINGSECTOR pSector = pmMapping->pSectors;
              address = pSector->dwStartAddress;

            if (strcmp(argv[arg_index-1],"--a")==0)   
            {
              address = _tcstoul(argv[arg_index], 0, 16) ;
            }
          }
          else 
          {
            if (arg_index < argc - 1) 
              printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

            if(COM_is_Open())  
              COM_Close(); 

            printf("\nPress any key to continue ...\n"); 
            _getch(); 
            return 1;
          }

          printf("\n RUNNING ... \n\n");

          if (STBL_GO(address) == SUCCESS)
          {
            printf("Your code is running...\n");
          }
          else
          {
            printf( "ERROR: run failed \n");
          }
        }
      }
      

//ow:
      //============================ Get Device map file name automatically  ==============================
      else if (strcmp(argv[arg_index],"-ow")==0)
      {
        //sending BL config byte (0x7F) & identifing target
        Res = STBL_Init_BL();
        if (Res == UNREOGNIZED_DEVICE)
        {
          write_debug_info("Activating device", 0 ,0, 0, KO);

          printf("ERROR: Unrecognized device.\n");
          printf("Please, reset your device and then try again.\n");

          if(COM_is_Open()) 
            COM_Close();

          printf("\nPress any key to continue ...\n\n"); 
          _getch();
          goto START;
        }
        else if (Res != SUCCESS)     
        {
          write_debug_info("Activating device", 0 ,0, 0, KO);
          printf("ERROR: No response from the target, the Bootloader cannot be started.\n");
		      printf("Please, verify the boot mode configuration, reset your device then try again.\n");
          
          if(COM_is_Open()) 
            COM_Close(); 
          
          printf("\nPress any key to continue ...\n\n"); 
          _getch();
          goto START;
        }

        _sleep(TimeBO);
         
        write_debug_info("Activating device", 0 ,0, 0, OK);
         
        //Getting Target informations (version, available commands)
        BYTE Version ;
        Commands pCmds;

        Res = STBL_GET(&Version, &pCmds);
        if (Res != SUCCESS)
        {
          if(COM_is_Open()) 
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1; 
        }

        printf( "Bootloader version %X\n", Version ); //ow

        SetTimeOut(timeout);

        /* */
         
        family = 0; // STM32F1 is selected by default
        DWORD PID = 0x00000000;
        ADDR_XX_OPB = ADDR_F1_OPB;

        if (GetAckValue() == ST75)
          family = 1;  // STR750 is selected 
        else if (GetAckValue() == ST79)   // STM32, STR911 or STM8 is used, need to check other criteria    
        {   
          if (!pCmds.GET_ID_CMD)  // check if the GET ID command is available
          {         
            family = 2;  // STM8 is used
          }
          else
          {     // STM32 or STR911 is used
            BYTE size = 0x00;
            LPBYTE pID;  //Get the Device ID
            //Get the ID size in bytes before 
            if (STBL_GET_ID(&size,NULL) == SUCCESS)
            {
              pID = (LPBYTE)malloc(size);
            
              if (STBL_GET_ID(&size,pID) == SUCCESS) // Get the ID
              {
                for(int i=0; i<size; i++)
                {
                  PID = PID << 8;
                  PID = PID + (pID[i]);
                }

                if(PID == 0x25966041) 
                {
                  family = 3; // STR911 is used 
                }
                else if((PID == 0x416) || (PID == 0x436) || (PID == 0x427)) 
                {
                  family = 4; // STM32L is used 
                  ADDR_XX_OPB = ADDR_L1_OPB ;
                }
                else if(PID == 0x411 || (PID == 0x413) || (PID == 0x419)) 
                {
                  family = 5; // STM32F2 or F4 is used 
                  ADDR_XX_OPB = ADDR_F2_OPB ;
                }
                else if ((PID == 0x440) || (PID == 0x432) || (PID == 0x422) ||(PID == 0x444)) 
                {
                  family = 6; // STM32F0 or F3 is used 
                  ADDR_XX_OPB = ADDR_F0_OPB;
                }
        
              }
            }
          }
        }
/* families
f1=STM32F1
f2=STR75x
f3=STM8
f4=STR91xFA
f5=STM32L1
f6=STM32F2
f7=STM32F0
*/
		    switch(family){
        case 0: printf( "Device family STM32F1, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 1: printf( "Device family STR750, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 2: printf( "Device family STM8, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 3: printf( "Device family STR911, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 4: printf( "Device family STM32L, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 5: printf( "Device family STM32F2 or F4, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        case 6: printf( "Device family STM32F0 or F3, ID 0x%X, ADDR_XX_OPB 0x%X\n", PID, ADDR_XX_OPB ); break; //ow
        }

        //Getting Target information, Flash size
/*
[f1]	ADDR_FLASH_SIZE=1FFFF7E0; START_FLASH_ADDR=08000000;
[f2]  ADDR_FLASH_SIZE=FFFFFFFF; START_FLASH_ADDR=20000000;
[f3]	ADDR_FLASH_SIZE=FFFFFFFF; START_FLASH_ADDR=00008000;
[f4]	ADDR_FLASH_SIZE=FFFFFFFF; START_FLASH_ADDR=00080000;
[f5]  ADDR_FLASH_SIZE=1FF8004C; START_FLASH_ADDR=08000000;
[f6]	ADDR_FLASH_SIZE=1FFF7A22; START_FLASH_ADDR=08000000;
[f7]  ADDR_FLASH_SIZE=1FFFF7CC; START_FLASH_ADDR=08000000;
*/
        DWORD owAddrFlashSizeList[8]= { 0x1FFFF7E0, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF8004C, 0x1FFF7A22, 0x1FFFF7CC };
        WORD owFlashSize;

        Res = TARGET_GetFlashSize( owAddrFlashSizeList[family], &owFlashSize );
        if (Res != SUCCESS)
        {
          if(COM_is_Open()) 
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1; 
        }

        printf("Flashsize %uk\n", owFlashSize ); 

        //Construct device name file
/*
        if( family==2 )//STM8
        {
          sprintf(devname, "STM8_%uK.STmap", owFlashSize ); //how to identify L version???
        }
        else
        if( family==1 )//STR750
        {
          sprintf(devname, "STR750F.STmap", owFlashSize ); //how to identify L version???
        }
*/
		    switch(PID){
        //F1
        case 0x412: sprintf(devname, "STM32_Low-density_%uK.STmap", owFlashSize ); break; //ow
        case 0x410: sprintf(devname, "STM32_Med-density_%uK.STmap", owFlashSize ); break; //ow
        case 0x414: sprintf(devname, "STM32_High-density_%uK.STmap", owFlashSize ); break; //ow
        case 0x418: sprintf(devname, "STM32_Connectivity-line_%uK.STmap", owFlashSize ); break; //ow
        case 0x420: sprintf(devname, "STM32_Med-density-value_%uK.STmap", owFlashSize ); break; //ow
        case 0x428: sprintf(devname, "STM32_High-density-value_%uK.STmap", owFlashSize ); break; //ow
        case 0x430: sprintf(devname, "STM32_XL-density_%uK.STmap", owFlashSize ); break; //ow
        //L1
        case 0x416: sprintf(devname, "STM32L_Med-density-%uK.STmap", owFlashSize ); break; //ow
        case 0x436: sprintf(devname, "STM32L_High-density-%uK.STmap", owFlashSize ); break; //ow
        case 0x427: sprintf(devname, "STM32L_Med-density-Plus-%uK.STmap", owFlashSize ); break; //ow
        //F2
        case 0x411: sprintf(devname, "STM32F2_%uK.STmap", owFlashSize ); break; //ow
        //F0
        case 0x440: sprintf(devname, "STM32F0_%uK.STmap", owFlashSize ); break; //ow
        case 0x444: sprintf(devname, "STM32F0_Low-density_%uK.STmap", owFlashSize ); break; //ow
        //F4
        case 0x413: sprintf(devname, "STM32F4_%uK.STmap", owFlashSize ); break; //ow
        //case 0x419:  break; //ow
        //case 0x419:  break; //ow
        //F3
        case 0x432: sprintf(devname, "STM32F373_%uK.STmap", owFlashSize ); break; //ow
        case 0x422: sprintf(devname, "STM32F303_%uK.STmap", owFlashSize ); break; //ow
        //case 0x432:  break; //ow
        //case 0x422:  break; //ow
        default:
          printf("ERROR: device is not supported by -ow command, use -i\n"); 

          if(COM_is_Open()) 
            COM_Close(); 

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1; 
        }

        printf( devname );  printf( "\n" );

        //Here we go, can now continue as in -i with reading info from device name file
//        sprintf(devname,"%s.STmap", argv[arg_index]);

        char Drive[3], Dir[256], Fname[256], Ext[256];
        _splitpath(argv[0],Drive,Dir,Fname,Ext);
          
        sprintf(MapFile, "%s%s%s%s", Drive, Dir , "Map\\", devname);

        WORD PacketSize = 0;
        pmMapping = NULL;
        WORD Size = 0;
        char MapName[256]; 
        // Get the number of sectors in the flash target: pmMapping should be NULL
        // number of sectors is returned in the Size value
        BYTE PagePerSector = 0;

        if (!FileExist((LPCTSTR)MapFile))
        {
          printf("ERROR: This version does not support the <%s> target\n", argv[arg_index]);
          
          if(COM_is_Open())  
            COM_Close();

          printf("\nPress any key to continue ...\n"); 
          _getch(); 
          return 1;
        }

        FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pmMapping, &PagePerSector);
        // Allocate the mapping structure memory
        pmMapping = (PMAPPING)malloc(sizeof(MAPPING));
        pmMapping->NbSectors = 0;
        pmMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR));

        // Get the mapping info
        FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pmMapping, &PagePerSector);
           
        SetPaketSize(PacketSize);

        if (arg_index< argc) 
          arg_index++;
        else 
          break;
      }





      //============================ no valid option ==============================
      else
      {
        if (arg_index < argc - 1) 
          printf("ERROR: bad parameter [%s] \n", argv[arg_index]);

        if(COM_is_Open())  
          COM_Close(); 

        printf("\nPress any key to continue ...\n"); 
        _getch(); 
        return 1;
      }
    }
  }

  // commented 
  /*printf("command executed succesfully, press any key to close the COM port and exit");
  _getch();*/

  if(COM_is_Open()) 
    COM_Close();

  return 0;
}


/******************* (C) COPYRIGHT 2012 STMicroelectronics *****END OF FILE******/

/* copied from Default.conf:

[MCUs]
f1=STM32F1
f2=STR75x
f3=STM8
f4=STR91xFA
f5=STM32L1
f6=STM32F2
f7=STM32F0

[f1]	
ADDR_FLASH_SIZE=1FFFF7E0;
START_FLASH_ADDR=08000000;

[f2]
AN=AN2430
Title=STR75x System Memory boot mode	
ADDR_FLASH_SIZE=FFFFFFFF;
START_FLASH_ADDR=20000000;

[f3]		
ADDR_FLASH_SIZE=FFFFFFFF;
START_FLASH_ADDR=00008000;

[f4]		
ADDR_FLASH_SIZE=FFFFFFFF;
START_FLASH_ADDR=00080000;

[f5]		
ADDR_FLASH_SIZE=1FF8004C; 
START_FLASH_ADDR=08000000;

[f6]		
ADDR_FLASH_SIZE=1FFF7A22;
START_FLASH_ADDR=08000000;

[f7]	
ADDR_FLASH_SIZE=1FFFF7CC;
START_FLASH_ADDR=08000000;

*/



/* Device-dependent bootloader parameters:
• PID (product ID), which changes with the device
• Valid memory addresses (RAM, Flash memory, system memory, option byte areas)
accepted by the bootloader when the Read Memory, Go and Write Memory commands
are executed.
• Size of the Flash memory sector used when executing the Write Protect command.
*/

/*
Bootloader (protocol) version: version of the serial peripheral (USART, CAN, USB,
etc.) communication protocol used in the bootloader. This version can be retrieved
using the bootloader Get Version command.

Bootloader identifier (ID):
The bootloader ID is programmed in the last byte address - 1 of the device system
memory and can be read by using the bootloader “Read memory” command or by
direct access to the system memory via JTAG/SWD.

see also Table 46. Bootloader device-dependent parameters, page 130

*/



// from STUARTBLLIB
/************************************************************************************/
/* GetFlashSize
/*
/*
/************************************************************************************//*
STUARTBLLIB_API BYTE TARGET_GetFlashSize(DWORD Addr, LPWORD val)
{
	if (!Cur_COM.isConnected)  return NO_CON_AVAILABLE;
	if (!Target->READ_CMD) return CMD_NOT_ALLOWED;

	LPBYTE pData = new BYTE[sizeof(*val)];
	memset(pData, 0xFF, sizeof(*val));

	BYTE Result = STBL_READ(Addr, sizeof(*val),pData); //ADDR_FLASH_SIZE*
	if (Result != SUCCESS) return Result;
	else memcpy(val, pData, sizeof(*val));
    
	return SUCCESS;  
}
*/
/************************************************************************************/
/* GetMemoryAddress
/*
/*
/************************************************************************************//*
STUARTBLLIB_API BYTE TARGET_GetMemoryAddress(DWORD Addr, LPBYTE val)
{
	if (!Cur_COM.isConnected)  return NO_CON_AVAILABLE;
	if (!Target->READ_CMD) return CMD_NOT_ALLOWED;

	LPBYTE pData = new BYTE[sizeof(*val)];
	memset(pData, 0xFF, sizeof(*val));

	BYTE Result = STBL_READ(Addr, sizeof(*val),pData); //ADDR_RAM_SIZE
	if (Result != SUCCESS) return Result;
	else memcpy(val, pData, sizeof(*val));
    
	return SUCCESS;
}
*/

