function tic2000LoadExecutable(LoadCommandArgs,exeFileName,targetHardware,hCS)
% TIC2000LOADEXECUTABLE Code executed to download the executable to the target

% Copyright 2016-2023 The MathWorks, Inc.

if nargin < 4
    hCS = getActiveConfigSet(bdroot);
end
tgtInfo = codertarget.targethardware.getTargetHardware(hCS);
tgtAttributes = codertarget.attributes.getTargetHardwareAttributes(hCS);
programFile = exeFileName;

if ~isempty(hCS)
    selectedToolChain = get_param(hCS, 'Toolchain');
    allowedToolChains = {tgtInfo.ToolChainInfo(:).Name};
    [isMatch, ~] = ismember(selectedToolChain, allowedToolChains);
else
    % Unable to read the config set and the corresponsing toolchain, so
    % return as toolchain not matched
    isMatch = 0;
end

if ~isMatch
    % Not able to read proper config set or Toolchain is not one of the supported for this target
    error(message('TIC2000:codegen:IncorrectTargetConfiguration', exeFileName, targetHardware));
else
    toolRootDir = codertarget.tic2000.internal.getToolchainScriptingFolder(hCS);
    if (exist(toolRootDir, 'dir') == 7)
        if ispc
            cmd = '$(TARGET_SCRIPTING_ROOT)/bin/dss.bat';
        else
            cmd = '$(TARGET_SCRIPTING_ROOT)/bin/dss.sh';
        end
        cmd = strrep(cmd, '$(TARGET_SCRIPTING_ROOT)', toolRootDir);
        loadCommandArg1 = codertarget.utils.replaceTokens(hCS,LoadCommandArgs, tgtAttributes.Tokens);
        cmdEnd = codertarget.data.getParameterValue(hCS, 'Runtime.LoadCommandArg');
        loadCommandArg2 = codertarget.utils.replaceTokens(hCS, ...
            cmdEnd, tgtAttributes.Tokens);
        loadCommandArg1 = coder.make.internal.transformPaths(loadCommandArg1, 'pathType', 'alternate');
        loadCommandArg2 = coder.make.internal.transformPaths(loadCommandArg2, 'pathType', 'alternate');
        programFile = coder.make.internal.transformPaths(programFile, 'pathType', 'alternate');
        loadCommandArg = [loadCommandArg1 ' ' loadCommandArg2];
        
        argString = sprintf('%s "%s"', loadCommandArg, programFile);
        ccsVersion = codertarget.tic2000.internal.CCSVersionDetect(hCS);
        if (ccsVersion >= 5)
            if isequal(targetHardware, 'TI Delfino F2837xD') || isequal(targetHardware, 'TI Delfino F28379D LaunchPad')
                targetHardware = 'TI_Delfino_F2837xD';
                data = codertarget.data.getParameterValue(hCS, 'Runtime');
                cpu = codertarget.data.getParameterValue(hCS, 'ESB.ProcessingUnit');
                if isequal(cpu, 'c28xCPU1')
                    argString = [argString ' ' '"*" C28xx_CPU1' ' "' targetHardware '" ' num2str(data.FlashLoad)];
                else
                    argString = [argString ' ' '"*" C28xx_CPU2' ' "' targetHardware '" ' num2str(data.FlashLoad)];
                end
            elseif isequal(targetHardware, 'TI F2838x')
                targetHardware = 'TI_F2838x_C28x';
                data = codertarget.data.getParameterValue(hCS, 'Runtime');
                cpu = codertarget.data.getParameterValue(hCS, 'ESB.ProcessingUnit');
                if isequal(cpu, 'c28xCPU1')
                    argString = [argString ' ' '"*" C28xx_CPU1 ' targetHardware ' ' num2str(data.FlashLoad)];
                else
                    argString = [argString ' ' '"*" C28xx_CPU2 ' targetHardware ' ' num2str(data.FlashLoad)];
                end
            elseif isequal(targetHardware, 'TI F28P65x') || isequal(targetHardware, 'TI F28P650D LaunchPad')
                targetHardware = 'TI_F28P65x';
                data = codertarget.data.getParameterValue(hCS, 'Runtime');
                cpu = codertarget.data.getParameterValue(hCS, 'ESB.ProcessingUnit');
                if isequal(cpu, 'c28xCPU1')
                    argString = [argString ' ' '"*" C28xx_CPU1 ' targetHardware ' ' num2str(data.FlashLoad)];
                else
                    argString = [argString ' ' '"*" C28xx_CPU2 ' targetHardware ' ' num2str(data.FlashLoad)];
                end
            elseif isequal(targetHardware, 'TI Concerto F28M35x (C28x)') || isequal(targetHardware, 'TI Concerto F28M36x (C28x)')
                targetHardware = strrep(targetHardware,' ','_');
                targetHardware = strrep(targetHardware,'(','');
                targetHardware = strrep(targetHardware,')','');
                argString = [argString ' ' '"*" C28xx_CPU1 ' targetHardware ' "*"'];
            else
                targetHardware = strrep(targetHardware,' ','_');
                targetHardware = strrep(targetHardware,'/','_');
                argString = [argString ' ' '"*" C28xx_CPU1' ' "' targetHardware '" "*"'];
            end
        end
        
        % hCS.getModel will be empty in case of reference model PIL
        if ~isempty(hCS.getModel)
            %Create a new section in the diagonastic viewer for Deployment
            %stage
            download_stage = sldiagviewer.createStage('Download Executable to Hardware','ModelName', get_param(hCS.getModel,'Name'));
            errArg = ' the ''Download Executable to Hardware'' stage';
        else
            errArg = '';
        end
        cmd = [cmd ' ' argString];
        Simulink.output.info(DAStudio.message('TIC2000:codegen:Executabledownload'));
        [~,msg]=system(cmd,'-echo');

        if ~isempty(hCS.getModel)
            stageCleanup = onCleanup(@() delete(download_stage));
        end
        if(~any(strfind(msg,'LOAD & RUN DONE')))
            DAStudio.error('TIC2000:codegen:DownloadCallbackError',errArg);
        end
    else
        MSLDiagnostic('TIC2000:codegen:ThirdPartyToolNotSetup','TI Code Composer Studio').reportAsError;
    end
end
end
