⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mxc_download.cpp

📁 Redboot, boot-loader of Linux for Freescale ARM family.
💻 CPP
字号:
#include <conio.h>
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#include <stdio.h>
#include <windows.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <io.h>
#include "mxc_download.h"

//#define PRINTK(fmt, args...) printk(fmt, ## args)

//#define MXC_DOWNLOAD_DEBUG
#ifdef MXC_DOWNLOAD_DEBUG
#define D_PRINTF printf
#else
#define D_PRINTF(x)
#endif

void Setup_Port(int baud);
HANDLE Open_Port(int Port_Num, char* port_name1, int baud);
void Shutdown_Port(char *port_name_, HANDLE portH);
#define READ_BUF_SIZE	0x1000	  // bytes
#define READ_BUF_SIZE1	0x1	  // bytes
static char read_buffer[READ_BUF_SIZE];

HANDLE hPort = NULL;				// Serial Port file pointer
BOOL     Port_Ready;
DCB      dcb;
COMMTIMEOUTS CommTimeouts;
DWORD g_bytes_written;
int default_BaudRate;
int default_Parity;
int default_ByteSize;
int default_StopBits;

#define PRINT_HELP_MSG() 										\
{																\
	printf("Syntax:\n");						\
	printf("    %s <COM Port> <Address> <File Name> <platform>\n", argv[0]);	\
	printf("\nFor example, to download Redboot binary to 0x81f00000 on \n");    \
    printf("MXC275-30 EVB via COM1, use:\n"); \
	printf("    %s COM1 0x81f00000 mxc27530evb_redboot.bin mxc27530evb\n", argv[0]);				\
	printf("For platforms like i.300-30 EVB, MXC300-30 EVB, MXC91131 EVB, \n");    \
    printf("MXC91131 MEM1 EVB:\n"); \
	printf("    %s COM1 0x83f00000 i30030evb_redboot.bin i30030evb\n", argv[0]);				\
	printf("    %s COM1 0x83f00000 mxc30030evb_redboot.bin i30030evb\n", argv[0]);				\
	printf("    %s COM1 0x83f00000 mxc91131evb_redboot.bin mxc91131evb\n", argv[0]);				\
	printf("    %s COM1 0x83f00000 mxc91131mem1evb_redboot.bin mxc91131mem1evb\n", argv[0]);				\
	printf("\n"); \
}


#define TEST_FILE

#ifdef TEST_FILE
const char *test_write_file = "readback.bin";
#endif

enum {
	e_I30030EVB,
	e_MXC27530EVB,
	e_MXC91131EVB,
	e_MXC91131EVBMEM1,
};

static char *dat_file[] = 
{
	"i30030evb.dat",
	"mxc27530evb.dat",
	"mxc91131evb.dat",
	"mxc91131mem1evb.dat",
};

char *chip_str[] = {
	"i300-30/MXC300-30 EVB",
	"MXC275-30 EVB",
	"MXC91131 EVB",
	"MXC91131 EVB with MEM1 card",
};

int parse_cmd_line(char* argv[], int *p_num, unsigned long *dn_addr, unsigned long *chip)
{
    int  val1, port;
	unsigned long download_addr = 0;
    char *ptr;

	// Check for COM port
	if ((argv[1][0] != 'C' && argv[1][0] != 'c') || (argv[1][1] != 'O' && argv[1][1] != 'o') ||
		(argv[1][2] != 'M' && argv[1][2] != 'm') || argv[1][3] == '\0') {
		printf("Use 'COM1', 'COM2', ...\n");
		return (__LINE__);
	}
	ptr = &argv[1][3];
	while ((val1 = *ptr++) != '\0') {
		if (val1 < '0' || val1 > '9') {
			printf("Wrong port number.\n");
            return (__LINE__);
		}
	}
	port = atoi(&(argv[1][3]));

	// Check for download address
	if (argv[2][0] != '0' || argv[2][1] != 'x') {
		printf("Wrong address, use hex format: 0x.... instead\n");
        return (__LINE__);
	}
	ptr = &argv[2][2];
	while ((val1 = *ptr++) != '\0') {
		download_addr *= 16;
		if (val1 >= 'a' && val1 <= 'f')
			download_addr += val1 - 'a' + 10;
		else if (val1 >= 'A' && val1 <= 'F')
			download_addr += val1 - 'A' + 10;
		else if (val1 >= '0' && val1 <= '9')
			download_addr += val1 - '0';
		else {
			printf("Wrong hex value for address \n");
            return (__LINE__);
		}
	}

	*dn_addr = download_addr;

	// Check for chip
	if (strcmp(argv[4], "i30030evb") == 0) {
		*chip = e_I30030EVB;
	} else if (strcmp(argv[4], "mxc27530evb") == 0) {
		*chip = e_MXC27530EVB;
	} else if (strcmp(argv[4], "mxc91131evb") == 0) {
		*chip = e_MXC91131EVB;
	} else if (strcmp(argv[4], "mxc91131mem1evb") == 0) {
		*chip = e_MXC91131EVBMEM1;
	} else {
		printf("Wrong chip\n\n");
		return -1;
	}

    return 0;
}

BOOL write_to_com(HANDLE handle, unsigned char* str, unsigned long len) {
	return WriteFile(handle, str, len, &g_bytes_written, NULL);
}

struct send_data {
    unsigned char *preamble;
    unsigned char *dst_addr;
    unsigned char *data_len_bytes;
    unsigned char *ubmr;
    unsigned char *data_buf;
    unsigned char *checksum;
};

struct send_data g_data;

//const DATA_LEN = 1024*16;
const DATA_LEN = 4*1024;
unsigned char buffer_to_send[DATA_LEN];
unsigned char buffer_to_send_download[DATA_LEN]; // 16KB data
unsigned char aA[] = {
	'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a',
    'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A', 'a', 'A',
};

unsigned char preamble[] = {0x55, 0x55, 0x55, 0xAA};
unsigned char dst_addr[][4] = {
	{0x1F, 0xFF, 0xd0, 0x00},	// MXC913x1
	{0x78, 0x00, 0x10, 0x00},	// MXC91231
	{0xB8, 0x02, 0x20, 0x00},	// MXC91131
	{0xB8, 0x02, 0x20, 0x00},	// MXC91131 on MEM1 EVB
};

#define DEBUG_BOARD

int main(int argc, char* argv[])
{
	int port, i;
	unsigned long download_addr = 0;
	char *file_name;
	char *port_name;
	HANDLE portH;

	FILE *fp, *fp_download;
	unsigned long filesize, checksum = 0, bytes_read, chip;
    unsigned char data_len_bytes[] = {DATA_LEN >> 8, (DATA_LEN & 0xFF)};
    unsigned char ubmr[] = {0, 0};

    g_data.preamble = preamble;
    g_data.ubmr     = ubmr;
    g_data.data_buf = buffer_to_send;
    g_data.data_len_bytes = data_len_bytes;

	printf("\n");
	if (argc == 1) {
        printf("This program is used to download a file to a memory location on the\n");
        printf("MXC platforms and then jump to it.\n\n");
		goto help_msg;
    }
	if (argc != 5) {
		printf("Wrong number of arguments.\n");
		goto help_msg;
	}
    if (parse_cmd_line(argv, &port, &download_addr, &chip) != 0) {
		goto help_msg;
    }

	port_name = argv[1];
	file_name = argv[3];
	g_data.dst_addr = dst_addr[chip];

	printf("Downloading %s via %s to 0x%x on %s board\n",
		   file_name, port_name, download_addr, chip_str[chip]);

	if ((portH = Open_Port(port, port_name, 19200)) == INVALID_HANDLE_VALUE) {
		printf("Error: %s is in use\n", port_name);
		return -1;
	}

/////////////// start board file read //////////////////////////////
	// Send file via serial port. Open the file first
	if ((fp = fopen(dat_file[chip],"rb")) == NULL) {
		printf("\nUnable to open %s\n", dat_file[chip]);
		exit (-1);
	}
	if ((fp_download = fopen(file_name,"rb")) == NULL) {
		printf("\nUnable to open file: %s\n", file_name);
		exit (-1);
	}

	filesize = filelength(fileno(fp));
    // read in board file to send
    i = fread(buffer_to_send, sizeof(char), DATA_LEN, fp);
//////////// end of board file read /////////////

//////////// Get the checksum value ///////////////////
    checksum = g_data.dst_addr[0] + g_data.dst_addr[1] + g_data.dst_addr[2] + g_data.dst_addr[3] +
        g_data.data_len_bytes[0] + g_data.data_len_bytes[1] +
        g_data.ubmr[0] + g_data.ubmr[1];

    for (i = 0; i < DATA_LEN; i++) {
        checksum += g_data.data_buf[i];
    }

    checksum = 0xFF - (checksum & 0xFF);

    g_data.checksum = (unsigned char *) &checksum;
//////////// End of the checksum value ///////////////////

///// Make sure to get back with 'Z' //////////
	D_PRINTF("line: %d\n", __LINE__);
    if (write_to_com(portH, aA, sizeof(aA)) == 0) {
        printf("Failed to write aA to COM port\n");
        exit (-1);
    }
    D_PRINTF("line: %d\n", __LINE__);
    if (ReadFile(portH, read_buffer, READ_BUF_SIZE1, &bytes_read, NULL) == 0) {
        printf("ReadFile failed at line: %d\n", __LINE__);
        goto func_out;

    }
    D_PRINTF("line: %d\n", __LINE__);

    if (read_buffer[0] != 'Z') {
        printf("Failed to initialize the board. Wrong value: 0x%x\n", read_buffer[0]);
        goto func_out;
    }
    D_PRINTF("Receiving Z\n");

////////// End of getting back with Z /////////

//////////// Downloading board file to internal RAM /////////
    if (write_to_com(portH, g_data.preamble, 4) == 0) {
        printf("Failed to write preamble to COM port\n");
        exit (-1);
    }
    if (write_to_com(portH, g_data.dst_addr, 4) == 0) {
        printf("Failed to write dest addr to COM port\n");
        exit (-1);
    }

    if (write_to_com(portH, g_data.data_len_bytes, 2) == 0) {
        printf("Failed to write data bytes to send to COM port\n");
        exit (-1);
    }

    if (write_to_com(portH, g_data.ubmr, 2) == 0) {
        printf("Failed to write ubmr to COM port\n");
        exit (-1);
    }

    if (write_to_com(portH, g_data.data_buf, DATA_LEN) == 0) {
        printf("Failed to write data buffer to COM port\n");
        exit (-1);
    }

    if (write_to_com(portH, g_data.checksum, 1) == 0) {
        printf("Failed to write checksum to COM port\n");
        exit (-1);
    }
//////////// Done downloading board file to internal RAM /////////

// Now the board file should be downloaded and the target should executing
// the board file. The board file contains program to change the uart baud
// rate to 115200 and start to download "read" downloaded file int

    // switch to higher baud rate after downloading bin into internal RAM
    // to be ready to download user-passed in file
    if (chip != e_MXC91131EVB && chip != e_MXC91131EVBMEM1) {
        D_PRINTF("Changing baud rate to 115200\n");
        Setup_Port(115200);
    }
    D_PRINTF("line: %d\n", __LINE__);

    ///////////// Check to see if "lucky" is ready ///////
    if (ReadFile(portH, read_buffer, 5, &bytes_read, NULL) == 0) {
        printf("ReadFile failed at line: %d\n", __LINE__);
        goto func_out;

    }
    D_PRINTF("line: %d\n", __LINE__);
    read_buffer[5] = '\0';
    if (strcmp(read_buffer, "Lucky") != 0) {
        printf("Not lucky. Got: %s\n", read_buffer);
        goto func_out;
    }
    D_PRINTF("line: %d\n", __LINE__);

    filesize = filelength(fileno(fp_download));
    if (write_to_com(portH, (unsigned char*)&download_addr, 4) == 0) {
        printf("Failed to write download addr to COM port\n");
        exit (-1);
    }
    D_PRINTF("line: %d\n", __LINE__);

    if (write_to_com(portH, (unsigned char*)&filesize, 4) == 0) {
        printf("Failed to write download size to COM port\n");
        exit (-1);
    }

    D_PRINTF("line: %d\n", __LINE__);
    // ready to send data
	printf("\n");
    while (1) {
		if ((i = fread(buffer_to_send_download, sizeof(char), DATA_LEN, fp_download)) > 0) {
			if (ReadFile(portH, read_buffer, READ_BUF_SIZE1, &bytes_read, NULL) == 0) {
				printf("ReadFile failed at line: %d\n", __LINE__);
				goto func_out;

			}

			if (read_buffer[0] != 'Z') {
			    printf("Failed to initialize the board. Wrong value: 0x%x\n", read_buffer[0]);
		        goto func_out;
			} else {
			    printf(".");
		    }


		    if (write_to_com(portH, buffer_to_send_download, i) == 0)
			{
				printf("Failed to write data buffer download to COM port\n");
				exit (-1);
			}
		}

		if (i < DATA_LEN) break;
	}
	printf("\n\nDone\n");

func_out:
	fclose(fp);
    Shutdown_Port(port_name, portH);

    exit (0); // Normal return

help_msg:
	PRINT_HELP_MSG();
	exit (-1);
}

/**************************************************************************************
 * Routine Name: Open_Port(int Port_Num, char* port_name1, int baud)
 *
 * This routine opens a serial port for reading or writing.
 **************************************************************************************/
HANDLE Open_Port(int Port_Num, char* port_name1, int baud)
{
	HANDLE hPort1;
		//printf("\nOpen_Port for RW Opening = %s \n",port_name);
		hPort1 = CreateFile (port_name1,// Pointer to the name of the port
		GENERIC_READ | GENERIC_WRITE,	// Access (read-write) mode
		0,								// Share mode
		NULL,							// Pointer to the security attribute
		OPEN_EXISTING,					// How to open the port
		0,								// Port attributes
		NULL);							// Handle to port with attribute

		if (hPort1 == INVALID_HANDLE_VALUE) {
			printf("Could not open %s\n", port_name1);   // process error
			return INVALID_HANDLE_VALUE;
		}
        else {
			//printf("Setting up port %s\n",port_name);
			Setup_Port(baud);
		}

	return hPort1;
}
/**************************************************************************************
 * Routine Name: Shutdown_Port
 *
 * This routine closes a port with a serial or parallel port printer.
 **************************************************************************************/
void Shutdown_Port(char *port_name_, HANDLE portH)
{
	//If a previous serial or parallel port is open and we've changed ports,
	//close the first one so the new one can be opened.
	if (portH != NULL)
	{
		CloseHandle(portH);
	}
}

/**************************************************************************************
 * Routine Name: Setup_Port(int baud)
 *
 * This routine will setup the serial or parallel port currently selected
 **************************************************************************************/
void Setup_Port(int baud)
{

	//Check the returned handle for INVALID_HANDLE_VALUE and then set the buffer sizes.

	Port_Ready = SetupComm(hPort, PACKET_SIZE, PACKET_SIZE); // set buffer sizes

	//Port settings are specified in a Data Communication Block (DCB).
	//The easiest way to initialize a DCB is to call GetCommState to
	//fill in its default values, override the values that you want to
	//change and then call SetCommState to set the values.

	//Set up transmission information
	//Also see DOS Mode command:  Mode COM1: 9600,N,8,1
	Port_Ready = GetCommState(hPort, &dcb);

	default_BaudRate = dcb.BaudRate;
	default_Parity = dcb.Parity;
	default_ByteSize = dcb.ByteSize;
	default_StopBits = dcb.StopBits;
	dcb.BaudRate = baud;
	dcb.Parity = NOPARITY;
	dcb.ByteSize = 8;
	dcb.StopBits = 1;
	dcb.fAbortOnError = TRUE;

	Port_Ready = SetCommState(hPort, &dcb);

	//Communication timeouts are optional but can be set similarly to DCB values
	//This will prevent the program from hanging should the port does not respond.
	Port_Ready = GetCommTimeouts (hPort, &CommTimeouts);

	CommTimeouts.ReadIntervalTimeout = 50;
	CommTimeouts.ReadTotalTimeoutConstant = 50;
	CommTimeouts.ReadTotalTimeoutMultiplier = 10;
	CommTimeouts.WriteTotalTimeoutConstant = 50;
	CommTimeouts.WriteTotalTimeoutMultiplier = 10;

	Port_Ready = SetCommTimeouts (hPort, &CommTimeouts);

	//If all of these API's were successful then the port is ready for use.
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -