/****************************************************************************** * Copyright (c) 2011 Texas Instruments Incorporated - http://www.ti.com * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ /************************************************************************************** * FILE PURPOSE: EEPROM writer utility ************************************************************************************** * FILE NAME: eepromwriter.c * * DESCRIPTION: A simple EEPROM writer using platform lib APIs to program the EEPROM * with an image that the ibl can read. * ***************************************************************************************/ #include #include #include #include #include "platform.h" #include "types.h" /* EEPROM writer utility version */ char version[] = "01.00.00.04"; /* The input file name is hard coded */ char *input_file = "eepromwriter_input.txt"; /* Parameters defined in the input_file */ #define FILE_NAME "file_name" #define BUS_ADDR "bus_addr" #define START_ADDR "start_addr" #define SWAP_DATA "swap_data" /* Memory address to store the write data */ #define WRITE_DATA_ADDRESS 0x80000000 /****************************************************************************** * Structure: EEPROM_WRITER_INFO_T * * EEPROM writer control data. This structure should be filled in * by the user before running ******************************************************************************/ #define MAX_LINE_LENGTH 40 typedef struct EEPROM_WRITER_INFO_tag { char file_name[MAX_LINE_LENGTH]; /* CCS format data file name */ uint32_t busAddr; /* Slave bus address */ uint32_t startAddr; /* Start address to write */ uint32_t swapData; /* Swap byte in the 32-bit word of the data */ uint32_t deviceTotalBytes; /* Total number of bytes available in the device */ uint32_t writeBytes; /* Number of bytes to be written into the device */ uint8_t *writeData; /* Address to store the write data */ uint8_t *readData; /* Address to store the read data */ } EEPROM_WRITER_INFO_T; EEPROM_WRITER_INFO_T eepromWriterInfo; /* OSAL functions for Platform Library */ uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment) { return malloc(num_bytes); } void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes) { /* Free up the memory */ if (dataPtr) { free(dataPtr); } } void Osal_platformSpiCsEnter(void) { return; } void Osal_platformSpiCsExit (void) { return; } /****************************************************************************** * Function: print_platform_errno ******************************************************************************/ void print_platform_errno ( void ) { printf ("Returned platform error number is %d\n", platform_errno); } /****************************************************************************** * Function: form_block * * Form a block of data to write to the NOR. The block is * created as a byte stream from the 4 byte stream in which * the MSB is always sent first. ******************************************************************************/ void formBlock ( uint32_t *data, uint32_t blockSize, uint8_t *scratch ) { uint32_t i, j; /* Convert the data to a byte stream */ for (i = j = 0; j < blockSize; i++, j+=4) { scratch[j+0] = (data[i] >> 24) & 0xff; scratch[j+1] = (data[i] >> 16) & 0xff; scratch[j+2] = (data[i] >> 8) & 0xff; scratch[j+3] = (data[i] >> 0) & 0xff; } } /****************************************************************************** * Function: flash_eeprom * * Write the data from memory to EEPROM. * Returns TRUE if the data is written successfully * FALSE if the data write fails ******************************************************************************/ Bool flash_eeprom ( PLATFORM_DEVICE_info *p_device ) { uint8_t *scrach_block; printf ("Writing %d bytes from DSP memory address 0x%08x to EEPROM bus address 0x%04x starting from device address 0x%04x ...\n", eepromWriterInfo.writeBytes, (uint32_t)eepromWriterInfo.writeData, eepromWriterInfo.busAddr, eepromWriterInfo.startAddr); if (eepromWriterInfo.swapData) { scrach_block = malloc(eepromWriterInfo.deviceTotalBytes); if (scrach_block == NULL) { printf ("Can not allocate scratch block memory!\n"); return (FALSE); } formBlock((uint32_t *)(eepromWriterInfo.writeData), eepromWriterInfo.deviceTotalBytes, scrach_block); } else { scrach_block = eepromWriterInfo.writeData; } if(platform_device_write(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK) { print_platform_errno(); if (eepromWriterInfo.swapData) free (scrach_block); return FALSE; } if(eepromWriterInfo.swapData) free (scrach_block); return TRUE; } /****************************************************************************** * Function: flash_verify * * Read back the data file that was just flashed. * Returns TRUE if the data verified correctly. * FALSE if the data verification failed ******************************************************************************/ Bool flash_verify ( PLATFORM_DEVICE_info *p_device ) { uint32_t i, j; uint8_t *scrach_block; uint32_t *read_data_w; printf ("Reading %d bytes from EEPROM bus address 0x%04x to DSP memory address 0x%08x starting from device address 0x%04x ...\n", eepromWriterInfo.writeBytes, eepromWriterInfo.busAddr, (uint32_t)eepromWriterInfo.readData, eepromWriterInfo.startAddr); if (eepromWriterInfo.swapData) { scrach_block = malloc(eepromWriterInfo.deviceTotalBytes); if (scrach_block == NULL) { printf ("Can not allocate scratch block memory!\n"); return (FALSE); } } else { scrach_block = eepromWriterInfo.readData; } if(platform_device_read(p_device->handle, eepromWriterInfo.startAddr, scrach_block, eepromWriterInfo.writeBytes) != Platform_EOK) { print_platform_errno(); return FALSE; } printf ("Verifying data read ...\n"); if (eepromWriterInfo.swapData) { /* Convert the packed data */ read_data_w = (uint32_t *)(eepromWriterInfo.readData); for (i = 0, j = 0; i < eepromWriterInfo.deviceTotalBytes; i += 4) read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3]; } for (i = 0; i < eepromWriterInfo.writeBytes; i++) { if (eepromWriterInfo.readData[i] != eepromWriterInfo.writeData[i]) { printf ("Failure at byte %d, expected 0x%08x, read 0x%08x\n", i, eepromWriterInfo.writeData[i], eepromWriterInfo.readData[i]); return (FALSE); } } return (TRUE); } int32_t xtoi ( char *xs, uint32_t *result ) { uint32_t szlen = strlen(xs); int32_t i, xv, fact; if (szlen > 0) { /* Converting more than 32bit hexadecimal value? */ if (szlen>8) return 2; /* exit */ /* Begin conversion here */ *result = 0; fact = 1; /* Run until no more character to convert */ for(i=szlen-1; i>=0 ;i--) { if (isxdigit(*(xs+i))) { if (*(xs+i)>=97) { xv = ( *(xs+i) - 97) + 10; } else if ( *(xs+i) >= 65) { xv = (*(xs+i) - 65) + 10; } else { xv = *(xs+i) - 48; } *result += (xv * fact); fact *= 16; } else { // Conversion was abnormally terminated // by non hexadecimal digit, hence // returning only the converted with // an error value 4 (illegal hex character) return 4; } } return 0; } // Nothing to convert return 1; } /****************************************************************************** * Function: parse_input_file ******************************************************************************/ static Bool parse_input_file ( FILE* fp ) { char line[MAX_LINE_LENGTH]; char tokens[] = " :=;\n\r"; char *key, *data; memset(line, 0, MAX_LINE_LENGTH); fgets(line, MAX_LINE_LENGTH, fp); key = (char *)strtok(line, tokens); data = (char *)strtok(NULL, tokens); if(strlen(data) == 0) { return FALSE; } if(strcmp(key, FILE_NAME) != 0) { return FALSE; } strcpy (eepromWriterInfo.file_name, data); fgets(line, MAX_LINE_LENGTH, fp); key = (char *)strtok(line, tokens); data = (char *)strtok(NULL, tokens); if(strlen(data) == 0) { return FALSE; } if(strcmp(key, BUS_ADDR) != 0) { return FALSE; } if ((data[0] == '0') && (data[1] == 'x' || data[1] == 'X')) { if (xtoi (&data[2], &eepromWriterInfo.busAddr) != 0) { return FALSE; } } else { eepromWriterInfo.busAddr = (uint32_t)atoi(data); } fgets(line, MAX_LINE_LENGTH, fp); key = (char *)strtok(line, tokens); data = (char *)strtok(NULL, tokens); if(strlen(data) == 0) { return FALSE; } if(strcmp(key, START_ADDR) != 0) { return FALSE; } eepromWriterInfo.startAddr = (uint32_t)atoi(data); fgets(line, MAX_LINE_LENGTH, fp); key = (char *)strtok(line, tokens); data = (char *)strtok(NULL, tokens); if(strlen(data) == 0) { return FALSE; } if(strcmp(key, SWAP_DATA) != 0) { return FALSE; } eepromWriterInfo.swapData = (uint32_t)atoi(data); return TRUE; } /****************************************************************************** * Function: find_file_length ******************************************************************************/ static Bool find_file_length ( FILE* fp ) { char line[MAX_LINE_LENGTH]; char *pEnd; char *ext; uint32_t data_len, write_addr; memset(line, 0, MAX_LINE_LENGTH); ext = strrchr(eepromWriterInfo.file_name, '.'); if (ext && (strcmp(ext, ".dat") == 0)) { fgets(line, MAX_LINE_LENGTH, fp); /* Read the write address from the CCS header */ strtoul (line,&pEnd,16); strtoul (pEnd,&pEnd,16); write_addr = strtoul (pEnd,&pEnd,16); strtoul (pEnd,&pEnd,16); /* Read the data length */ data_len = (strtoul (pEnd,NULL,16)) * 4; } else { /* find the data length by seeking to the end and getting position */ fseek(fp, 0, SEEK_END); data_len = ftell(fp); fseek(fp, 0, SEEK_SET); } if (data_len > (eepromWriterInfo.deviceTotalBytes - eepromWriterInfo.startAddr)) { printf ("The data file is too big to fit into the device.\n"); return FALSE; } eepromWriterInfo.writeBytes = data_len; if (write_addr != WRITE_DATA_ADDRESS) write_addr = WRITE_DATA_ADDRESS; eepromWriterInfo.writeData = (uint8_t *)write_addr; eepromWriterInfo.readData = (uint8_t *)(write_addr + eepromWriterInfo.deviceTotalBytes); return TRUE; } /****************************************************************************** * Function: main ******************************************************************************/ void main () { FILE *fp; platform_init_flags init_flags; platform_init_config init_config; PLATFORM_DEVICE_info *p_device; Bool ret; printf("EEPROM Writer Utility Version %s\n\n", version); fp = fopen(input_file, "r"); if (fp == NULL) { printf("Error in opening %s input file\n", input_file); return; } ret = parse_input_file(fp); fclose (fp); if (ret == FALSE) { printf("Error in parsing %s input file\n", input_file); return; } /* Initialize main Platform lib */ memset(&init_config, 0, sizeof(platform_init_config)); memset(&init_flags, 0x01, sizeof(platform_init_flags)); init_flags.pll = 0; init_flags.ddr = 0; init_flags.phy = 0; if (platform_init(&init_flags, &init_config) != Platform_EOK) { printf ("Platform init failed!\n"); print_platform_errno(); return; } p_device = platform_device_open(eepromWriterInfo.busAddr, 0); if (p_device == NULL) { printf ("EEPROM device open failed!\n"); print_platform_errno(); return; } eepromWriterInfo.deviceTotalBytes = p_device->block_count * p_device->page_count * p_device->page_size; /* Open and find the length of the data file */ fp = fopen (eepromWriterInfo.file_name, "rb"); if (fp == NULL) { printf ("Failed to open file %s\n", eepromWriterInfo.file_name); print_platform_errno(); platform_device_close(p_device->handle); return; } /* Parse the CCS format file */ ret = find_file_length(fp); fclose (fp); if (ret == FALSE) { printf("Error in parsing CCS file %s\n", eepromWriterInfo.file_name); platform_device_close(p_device->handle); return; } /* Write the EEPROM */ if (flash_eeprom (p_device) == FALSE) { printf ("EEPROM write failed\n"); platform_device_close(p_device->handle); return; } /* verify the flash */ if(flash_verify (p_device) == FALSE) { printf ("EEPROM read verify failed\n"); platform_device_close(p_device->handle); return; } printf ("EEPROM programming completed successfully\n"); platform_device_close(p_device->handle); return; }