OSD335x_EEPROM_during_boot_v04x OSD335x_EEPROM_During_Boot_ OSD335x EEPROM During Boot
User Manual: Pdf OSD335x_EEPROM_During_Boot_
Open the PDF directly: View PDF .
Page Count: 27
Download | |
Open PDF In Browser | View PDF |
OSD335x EEPROM During Boot Rev.1 6/11/2018 1 Introduction When creating a new embedded Linux design, getting a printed circuit board (PCB) to boot for the first time can have many unique challenges. These challenges can be hardware related: incorrect connections, improper voltages, bad component values, etc. or software related: incorrect device tree, improper drivers, bad configuration values etc. One common challenge: how to properly load and configure software drivers during boot It is important for the software running on the new design to recognize the unique set of peripherals and components used on the PCB so that the drivers can be properly loaded and configured. This can be accomplished in many different ways: pulling GPIO pins, programming hardware fuses, storing values in non-volatile memory, etc. This is an area where having non-volatile storage, like EEPROM, either inside a System-in-Package, as in the OSD335x-SM, or on the board can help. The Linux images from BeagleBoard.org used for the OSD335x Family of devices, identify designs by a unique code, a board ID, that is stored within an EEPROM attached to the I2C0 bus. This board ID is then used within U-Boot to properly configure the system. This article will discuss: how the board ID is used in U-Boot (Section 3); how to modify U-Boot to ignore the board ID (Section 4); and how to program the board ID in an EEPROM either before boot (Section 6) or within U-Boot (Section 5). Your preferred method to program the board ID, depends on the hardware in your system. For example, if you can boot from a microSD card, then modifying U-Boot to program the board ID (either Section 4.2 or Section 5) might be your preferred method. Similarly, if you have an external I2C programmer, you would prefer the programming method outlined in Section 6.1. If you would like to program the EEPROM over USB from a host PC (Section 6.2), software has been provided in the associated zip file and can also be found in Sections 8 and 9. Notice: The information provided within this document is for informational use only. Octavo Systems provides no guarantees or warranty to the information contained. Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 Table of Contents 1 Introduction .......................................................................................................................................... 1 2 Revision History ..................................................................................................................................... 3 3 Understanding the Board ID.................................................................................................................. 4 4 Modifying U-Boot to Ignore the Board ID ............................................................................................. 6 4.1 Hard-Coding the Board ID .............................................................................................................. 6 4.2 Recognizing a “Blank” Board ID ...................................................................................................... 7 5 Programming the Board ID Within U-Boot............................................................................................ 9 6 Programming the Board ID Outside of U-Boot .................................................................................... 11 6.1 Using an External I2C Programmer .............................................................................................. 11 6.2 Over USB From a Host PC ............................................................................................................. 12 6.2.1 Installing the Tools ................................................................................................................ 12 6.2.2 Compiling the Binary ............................................................................................................. 13 6.2.3 Programming the Device ....................................................................................................... 14 7 References ........................................................................................................................................... 18 8 Appendix A: hsi2cEeprom.c ................................................................................................................ 19 9 Appendix B: hsi2cEeprom.lds ............................................................................................................. 26 Octavo Systems LLC Copyright 2018 2 3 OSD335x EEPROM During Boot Rev.1 6/11/2018 2 Revision History Revision Number Revision Date Changes Author 1 6/11/2018 Initial Release Erik Welsh Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 3 Understanding the Board ID A board ID can be used for many different functions: • • • • • Distinguishing between different hardware designs Allowing inventory management and board tracking, such as differentiating between manufacturers Identifying and tracking failures for yield analysis Compatibility checking for software Encoding board revisions for debug During boot, it is especially important to distinguish between different hardware designs so that software drivers can be properly configured and loaded. As part of the Linux boot process for the OSD335x Family of devices, U-Boot uses the board ID to determine the printed circuit board (board) on which it is running. This makes U-Boot more flexible and allows a single U-Boot image to be used for many different development platforms. You can see that there are many functions defined in the UBoot file “./board/ti/am335x/board.h” that are used to control what functions are performed during the boot process (you can find the files by viewing the U-Boot source code, see reference section on page 18). For example, the following function is used to determine if the board is the Beagleboard.org® PocketBeagle®: static inline int board_is_pb(void) { return board_ti_is("A335PBGL"); } This function uses a common board detect infrastructure defined in “./board/ti/common/board_detect.c” and “./board/ti/common/board_detect.h” to determine the board. The board detect infrastructure in turn relies on a specific data structure, a ti_am_eeprom struct. This structure is found at the beginning of an EEPROM on an I2C bus (I2C0 in the case of the AM335x devices): /** * struct ti_am_eeprom - This structure holds data read in from the * AM335x, AM437x, AM57xx TI EVM EEPROMs. * @header: This holds the magic number * @name: The name of the board * @version: Board revision * @serial: Board serial number * @config: Reserved * @mac_addr: Any MAC addresses written in the EEPROM * * The data is this structure is read from the EEPROM on the board. * It is used for board detection which is based on name. It is used * to configure specific TI boards. This allows booting of multiple * TI boards with a single MLO and u-boot. */ struct ti_am_eeprom { unsigned int header; char name[TI_EEPROM_HDR_NAME_LEN]; char version[TI_EEPROM_HDR_REV_LEN]; char serial[TI_EEPROM_HDR_SERIAL_LEN]; char config[TI_EEPROM_HDR_CONFIG_LEN]; char mac_addr[TI_EEPROM_HDR_NO_OF_MAC_ADDR][TI_EEPROM_HDR_ETH_ALEN]; } __attribute__ ((__packed__)); Octavo Systems LLC Copyright 2018 4 5 OSD335x EEPROM During Boot Rev.1 6/11/2018 In the definition above, the header field is a “magic number”, i.e. a constant, TI_EEPROM_HEADER_MAGIC, with a value of 0xEE3355AA. This structure can be generically referred to as a “board ID” even though it has many different pieces of information. If you read the contents of an EEPROM from the Octavo Systems development board OSD3358-SM-RED, you can see that it follows the above data structure format: Address 00000000 00000010 Value AA 55 33 EE 00 00 00 00 41 33 33 35 00 00 00 00 42 4E 4C 54 00 00 00 00 4F 53 30 30 FF FF FF FF ASCII Value .U3.A335BNLTOS00 ................ Unfortunately, the reliance on the board ID during U-Boot can cause problems when first booting a board after manufacturing. By default, all EEPROMs are initially unprogrammed (i.e. all bytes have a value of 0xFF) when placed on a board. Therefore, when U-Boot first comes up and reads the unprogrammed board ID, it will read a value that does not match any board causing the software to hang because U-Boot is unable to know how to configure any peripheral to continue the boot. Unfortunately, the software hang occurs before the U-Boot console is active which can be mistaken for hardware bring-up problems (i.e. power is applied to the board, but nothing happens). To mitigate this issue, you can either modify U-Boot to ignore the board ID information within the EEPROM (i.e. hard code the board ID), or you can program the EEPROM to have the correct board ID information for the given system. Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 4 Modifying U-Boot to Ignore the Board ID One way to overcome an unprogrammed EEPROM is to modify U-Boot itself so that either the board ID is ignored by U-Boot or that the value of an unprogrammed EEPROM is recognized as a “blank” board. While modifying U-Boot can be a good short-term solution to work around this condition, it is not necessarily a good long-term solution to have U-Boot either ignore the board ID or for the board to be recognized as “blank”. Doing this in a production software image can be problematic in the case that revisions of the system have components that must be handled differently during boot. It also limits the reusability of the production software image across multiple products. Therefore, it is recommended to only ignore the board ID during the prototyping phase of a design and to program the EEPROM with a valid board ID during production (See Section 5). To modify U-Boot, you first must be familiar with the process needed to build U-Boot. You can find instructions on how to do this at https://eewiki.net/display/linuxonarm/BeagleBone+Black Once you are familiar with the process, there are two methods you can follow to update U-Boot to bypass the board ID checks. 4.1 Hard-Coding the Board ID In this first method, you can manually modify U-Boot to hard code a function within “./board/ti/am335x/board.h” so that the board has a fixed identity (i.e. the board ID is “hard coded”). For example, to make U-Boot always identify the board as “BeagleBone® Black”, you will need to make the following modification: static inline int board_is_bone_lt(void) { // return board_ti_is("A335BNLT"); -- Hard code board ID to BeagleBone Black return 1; } By returning “1” (i.e. true), this function will make U-Boot believe that the board is BeagleBone® Black and follow the boot process for BeagleBone® Black. If this works for your system (i.e. you have similar components to the BeagleBone® Black for booting, like an eMMC on MMC1 and an SD card on MMC0), then you can use this to bypass the board ID check. Octavo Systems LLC Copyright 2018 6 7 OSD335x EEPROM During Boot Rev.1 6/11/2018 4.2 Recognizing a “Blank” Board ID Another method to ignore the board ID, is to update U-Boot to recognize the unprogrammed EEPROM value as “blank”. To do this, a patch has been created that can help with this process. As part of the UBoot build process there are two patches that must be downloaded and applied to the U-Boot code base: wget -c https://rcn-ee.com/repos/git/u-boot-patches/v2018.03/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch wget -c https://rcn-ee.com/repos/git/u-boot-patches/v2018.03/0002-U-Boot-BeagleBone-Cape-Manager.patch In addition to these patches, another patch can be downloaded that will configure U-Boot to recognize the unprogrammed EEPROM value as a “blank” board and potentially program the EEPROM with a board ID. You can find this patch at: https://github.com/RobertCNelson/Bootloader-Builder/blob/master/patches/v2018.03-rc1/0002NFM-Production-eeprom-assume-device-is-BeagleBone-Bl.patch Caveat: The version of U-Boot and the patches listed above may not have be the same in the future. The correct versions and names should be listed in the instructions to build U-Boot. If you look at the patch, you can see how the files in U-Boot will be modified to ignore the board ID by recognizing the unprogrammed EEPROM as a “blank” (i.e. “A335BLNK”) board and then potentially program a board ID value into the EEPROM. If you look at lines 153 to 167 of the patch: @@ -190,6 +190,14 @@ "setenv fdtfile am335x-boneblack.dtb; " \ "fi; " \ + + + + + + + + "fi; " \ "if test $board_name = A335BLNK; then " \ "if test -e mmc 0:1 /boot/.eeprom.txt; then " \ "load mmc 0:1 ${loadaddr} /boot/.eeprom.txt;" \ "env import -t ${loadaddr} ${filesize};" \ "echo Loaded environment from /boot/.eeprom.txt;" \ "run eeprom_program; " \ "fi;" \ "setenv fdtfile am335x-boneblack-emmc-overlay.dtb; fi; " \ "if test $board_name = BBBW; then " \ "setenv fdtfile am335x-boneblack-wireless.dtb; fi; " \ "if test $board_name = BBG1; then " \ You can see that if the board is “blank” (i.e. “A335BLNK”), then the boot process will check to see if the file “/boot/.eeprom.txt” exists in the root file system of the boot image. If it does, then it will automatically run the eeprom_program command, defined in 0001-am335x_evm-uEnv.txt-bootz-nfixes.patch, utilizing the variables set in the “/boot/.eeprom.txt” file. If you look at the eeprom_program command (lines 1607 to 1617 of 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch): Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 + "eeprom_program="\ + "if test $board_eeprom_header = bbb_blank; then " \ + "run eeprom_dump; run eeprom_blank; run eeprom_bbb_header; run eeprom_dump; reset; fi; " \ + "if test $board_eeprom_header = bbbl_blank; then " \ + "run eeprom_dump; run eeprom_blank; run eeprom_bbb_header; run eeprom_bbbl_footer; run eeprom_dump; reset; fi; " \ + "if test $board_eeprom_header = bbbw_blank; then " \ + "run eeprom_dump; run eeprom_blank; run eeprom_bbb_header; run eeprom_bbbw_footer; run eeprom_dump; reset; fi; " \ + "if test $board_eeprom_header = os00_blank; then " \ + "run eeprom_dump; run eeprom_blank; run eeprom_bbb_header; run eeprom_os00_footer; run eeprom_dump; reset; fi; " \ + "if test $board_eeprom_header = beaglelogic_blank; then " \ + "run eeprom_dump; run eeprom_blank; run eeprom_beaglelogic; run eeprom_dump; reset; fi; \0" \ You can see that depending on the value of the variable board_eeprom_header, the appropriate board ID value will be programmed into the EEPROM. As of this writing, the acceptable values for board_eeprom_header are: • • • • • board_eeprom_header=bbb_blank board_eeprom_header=bbbl_blank board_eeprom_header=bbbw_blank board_eeprom_header=os00_blank board_eeprom_header=beaglelogic_blank If you need to add in a custom board ID value to be programmed into the EEPROM, it is straight forward to extend the code from the patches (i.e. the eeprom_program command and the EEPROM_PROGRAMMING #define). In this way, you can use the updated U-Boot image to program all of your systems so that they can have a valid board ID. Octavo Systems LLC Copyright 2018 8 9 OSD335x EEPROM During Boot Rev.1 6/11/2018 5 Programming the Board ID Within U-Boot If you used the “hard-coding method” or did not use the automated EEPROM programming functions of the “blank method” in Section 4, you can still program the board ID manually in U-Boot. Once you have been able to boot to the U-Boot console (i.e. you have bypassed the board ID check), it is straight forward to program values in the EEPROM corresponding to the board ID structure. From the U-Boot prompt, you only need to use the i2c command to program the EEPROM with the appropriate value. The commands below can be used to program the board ID for the OSD3358-SM-RED board. // Set i2c device i2c dev 0 // Set i2c mw i2c mw i2c mw i2c mw the EEPROM header “magic number”: 0x50 0x00.2 aa 0x50 0x01.2 55 0x50 0x02.2 33 0x50 0x03.2 ee 0xAA5533EE // Set i2c mw i2c mw i2c mw i2c mw the EEPROM name (bytes 0 – 4): 0x50 0x04.2 41 0x50 0x05.2 33 0x50 0x06.2 33 0x50 0x07.2 35 “A335” // Set i2c mw i2c mw i2c mw i2c mw the EEPROM name (bytes 4 – 7): 0x50 0x08.2 42 0x50 0x09.2 4e 0x50 0x0a.2 4c 0x50 0x0b.2 54 “BNLT” // Set i2c mw i2c mw i2c mw i2c mw the EEPROM version: 0x50 0x0c.2 4f 0x50 0x0d.2 53 0x50 0x0e.2 30 0x50 0x0f.2 30 “OS00” – OSD3358-SM-RED development platform Caveat: The version field of early revisions of the OSD3358-SM-RED had a value of “BBNR” (i.e. 42 42 4e 52) Each of the values passed to the I2C write command (e.g. 42 or 4e) is a hexadecimal ASCII value (https://www.asciitable.com/). Once the name and version fields of the EEPROM data structure are written, you can check that the programming was successful using an I2C read command: => i2c dev 0 Setting bus to 0 => i2c md 0x50 0x00.2 20 0000: aa 55 33 ee 41 33 33 35 42 4e 4c 54 4f 53 30 30 0010: 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff ff .U3.A335BNLTOS00 ................ Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 At this point, the board has been successfully programmed so that it can now boot a default Linux image from BeagleBoard.org®. However, if you would also like to add a serial number to the EEPROM, you may do so in the next twelve (12) bytes (above example has a serial number of: 000000000000). Octavo Systems LLC Copyright 2018 10 11 OSD335x EEPROM During Boot Rev.1 6/11/2018 6 Programming the Board ID Outside of U-Boot If there is no removable media, like an microSD card, in a system, it can be difficult to modify and load U-Boot to program an EEPROM. However, it is possible to program the board ID directly without modifying U-Boot by either using an external I2C programmer or over USB from a host PC. 6.1 Using an External I2C Programmer To program the board ID using an external I2C programmer, there are two requirements: 1. The I2C0 pins must be accessible (i.e. the pins must be brought out to a header or test points) so that they can be connected to an external I2C programmer 2. The AM335x within the OSD335x family of devices should be held in reset (i.e. WARMRSTN should be held low). Making the I2C0 pins accessible is straight forward but must be added during the hardware design phase of your system. If the I2C0 pins are not accessible, it will make using an external I2C programmer difficult to impossible. Also, the AM335x within the OSD335x family of devices should be held in reset when using an external I2C programmer. This will guarantee that there is only one master on the I2C0 bus and that there will be no conflicts with the AM335x trying to control the bus. This requires that a reset button or header exists that can hold the WARMRSTN pin low. Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 6.2 Over USB From a Host PC To program the board ID over USB from host PC, you can use a custom bare-metal program that will write values to the EEPROM. This method requires: • • • • • AM335x StarterWare 02.00.01.01 GCC cross compiler CCS UniFlash v3.4.1 Target system to boot from USB Optional: UART-to-USB adapter and Terminal Emulator (such as Putty2) For the target system to boot from USB, the boot mode must try to use the USB peripheral to download a boot image. For example, if the SYSBOOT[4:0] pins have a value of 11000b, i.e. the boot mode selected by the SD Boot button on the OSD3358-SM-RED, then the processor will try SPI0, MMC0, USB0, and UART0, in that order, to boot. This will allow programming over USB0. 6.2.1 Installing the Tools To install StarterWare and the GCC cross compiler, please follow the instructions from Sections 3 (Installing StarterWare for AM335x) and 4 (Installing Linaro GCC Compiler) of the Bare Metal Applications on OSD335x using U-Boot application note which can be found here. The instructions provided below assume that both of these tools were installed on a Linux system (Ubuntu 16.04 was used in the example). However, the instructions should be similar for a Windows system as long as the GCC compiler is used. To install the CCS UniFlash first follow the Installation Instructions from: http://processors.wiki.ti.com/index.php/CCS_UniFlash_v3.4.1_Release_Notes The instructions provided below assume that this tool was installed on a Windows system (Window 10 was used in the example). However, the instructions should be similar for a Linux system. Once the UniFlash tool is installed, you will need to modify the configuration files so that the tool uses more appropriate IP addresses. By default, the configuration files use the 192.168.100 subnet. However, the USB RNDIS connection on the example system was configured to use the 192.168.0 subnet. Therefore, the following configuration files need to be modified: File uniflash_3.4/third_party/sitara/opendhcp.ini: • Line 22: o Original version: § o • 192.168.100.1 New version: § 192.168.0.1 Lines 117 – 119: o Original version: § § § DHCPRange=192.168.100.2-192.168.100.254 NextServer=192.168.100.1 Router=192.168.100.1 Octavo Systems LLC Copyright 2018 12 13 OSD335x EEPROM During Boot Rev.1 6/11/2018 o New version: § § § DHCPRange=192.168.0.2-192.168.0.254 NextServer=192.168.0.1 Router=192.168.0.1 File uniflash_3.4/third_party/sitara/opentftp.ini: • Line 23: o Original version § o 192.168.100.1 New version § 192.168.0.1 Depending on your USB RNDIS connection configuration, you should adjust the default subnet accordingly. If you do not wish to modify the configuration files, you can always manually modify the subnet values when running the tool. 6.2.2 Compiling the Binary Next, you will need to modify the hsi2c_eeprom example in order to create a program that will program a custom value into the EEPROM to set the board ID. As part of the installation instruction for the GCC cross compiler, you should have set the LIB_PATH environment variable. This variable must be set for the makefiles for the GCC build to work correctly. 1. Replace the hsi2cEeprom.c file with the one provided (see Appendix A: hsi2cEeprom.c) a. Change directories to: AM335X_StarterWare_02_00_01_01/examples/beaglebone/hsi2c_eeprom b. Replace the contents of hsi2cEeprom.c with the provided code. This code uses a polling I2C method to read values from and write values to the EEPROM. 2. Modify the hsi2cEeprom.c file with your appropriate board ID value a. On approximately line 85, there are two #define variables that tell the program the number of bytes to write the EEPROM (NUM_BYTES_TO_WRITE) as well as the values to write to the EEPROM (EEPROM_VALUE_TO_WRITE). b. Currently, these values are set to the OSD3358-SM-RED board ID. These values should be updated to program your board ID. 3. Replace the hsi2c_eeprom linker command file with the one provided(See Appendix B: hsi2cEeprom.lds): a. Change directories to: AM335X_StarterWare_02_00_01_01/build/armv7a/gcc/am335x/beaglebone/hsi2c_eep rom b. Replace the contents of the linker command file, hsi2cEeprom.lds, with the provided code. This will place the program within the internal AM335x memory so that it can be used directly as a Secondary Program Loader (SPL) without having to initialize DDR. Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 4. Build the program a. In the same directory as the linker command file: AM335X_StarterWare_02_00_01_01/build/armv7a/gcc/am335x/beaglebone/hsi2c_eep rom b. Execute the following commands: i. ii. make clean make 5. Collect the compiled binary to program into the device a. Change directories to: AM335X_StarterWare_02_00_01_01/binary/armv7a/gcc/am335x/beaglebone/hsi2c_ee prom/Debug b. Collect the following file to be used to program the device: hsi2cEeprom.bin If you need to change the value programmed into the EEPROM for the board ID, you can update the hsi2cEeprom.c file from Step 2 and then recompile the executable using Step 4. 6.2.3 Programming the Device Now that you have the executable program, hsi2cEeprom.bin, that will program the board ID into the EEPROM, you need to use the UniFlash tool to load and run the program. 1. Update the UniFlash file to load into the device a. Open folder: C:\AM335x_Flashtool\images b. Copy hsi2cEeprom.bin to this directory c. Change the name of the file to u-boot-spl-restore.bin Octavo Systems LLC Copyright 2018 14 15 OSD335x EEPROM During Boot Rev.1 6/11/2018 2. Setup the UniFlash tool a. Open the UniFlash tool b. Select “New Target Configuration” c. Select “Sitara Flash Connections” for “Conection” d. Select “Sitara Flash Devices” for “Board or Device” e. At this point, you should see the following settings in the tool (These can be adjusted if they are not correct for your setup). Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 3. Optional: View program output a. Connection UART-to-USB adapter to the UART0 interface of the target system b. Start a terminal emulator program (such as Putty) This will allow you to see the output of the program on UART0 but is optional. 4. Load and execute the program a. Connect a USB cable from the appropriate USB interface of the target system to the host system that is running CCS UniFlash. b. Boot the board in the appropriate boot mode i. Note: In Windows, you should hear a notification that the target system has connected to the host using USB RNDIS. You should also be able to see this connection in the “Network Connections” window. By looking at this connection, you can debug any IP address issues you may have with the UniFlash IP settings. c. Click the “Start Flashing” button in UniFlash d. After a few seconds (up to a minute), you should see the target system populate a line in the “Status View”. This will always show a “Progress %” of “0%” even though the program has been loaded and executed by the target system. You can view the download of the executable with a tool such as WireShark3. Octavo Systems LLC Copyright 2018 16 17 OSD335x EEPROM During Boot Rev.1 6/11/2018 e. If you have the optional program output enabled, then you should see the following output on the UART0 interface (with the value that you set in the program instead of the default value pictured below). f. Close UniFlash since the target system has been successfully programmed. Caveat: Please ensure that the EEPROM is not write protected when you try to write the board ID value into the EEPROM. For the OSD335x-SM, this means pulling the EEPROM_WP pin low. Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 7 References For more information on software and optional tools, please refer to the following links: 1. U-Boot 2. Putty 3. WireShark https://github.com/u-boot/u-boot https://www.putty.org/ https://www.wireshark.org/ Octavo Systems LLC Copyright 2018 18 19 OSD335x EEPROM During Boot Rev.1 6/11/2018 8 Appendix A: hsi2cEeprom.c /** * \file * * \brief * * * * * * * * * * * * * * * * * * * * * * * */ eeprom_writer.c Application to write a blank EEPROM with a value. This will allow customers to set the Board ID to configure U-Boot. Application Configuration: Modules Used: I2C0 UART0 Configurable parameters: NUM_BYTES_TO_WRITE EEPROM_VALUE_TO_WRITE Hard-coded configuration of other parameters: Bus frequency - 100kHz Addressing mode - 7bit I2C Instance - 0 Slave Address - 0x50 EEPROM memory address - 0x0000 Limitations: With no flashed data in EEPROM, if the application tries to read from EEPROM, then the data values read would be "0xFF", which indicates an invalid EEPROM data. /* * Copyright (C) 2018 Octavo Systems, LLC - http://www.octavosystems.com/ */ /* * Copyright (C) 2010 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. * */ Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 #include #include #include #include #include #include #include #include #include "hw_types.h" "hw_control_AM335x.h" "hw_cm_wkup.h" "watchdog.h" "evmAM335x.h" "hsi2c.h" "uartStdio.h" "soc_AM335x.h" "stdio.h" /****************************************************************************** ** INTERNAL MACRO DEFINITIONS *******************************************************************************/ // // MODIFY THIS CODE // - NUM_BYTES_TO_WRITE should match the number of data values provided in EEPROM_VALUE_TO_WRITE // - NUM_BYTES_TO_WRITE should not exceed BUFFER_SIZE // #define NUM_BYTES_TO_WRITE (16) #define EEPROM_VALUE_TO_WRITE {0xAA, 0x55, 0x33, 0xEE, 0x41, 0x33, 0x33, 0x35, 0x42, 0x4E, 0x4C, 0x54, 0x4F, 0x53, 0x30, 0x30} // // END MODIFY THIS CODE // /* I2C address of AT24C256 eeprom */ #define I2C_SLAVE_ADDR (0x50) /* Higher byte address (i.e A8-A15) */ #define E2PROM_ADDR_MSB (0x00) /* Lower byte address (i.e A0-A7) */ #define E2PROM_ADDR_LSB (0x00) /* I2C instance #define I2C_0 (0x0u) */ /* System clock fed to I2C module - 48Mhz */ #define I2C_SYSTEM_CLOCK (48000000u) /* Internal clock used by I2C module - 12Mhz */ #define I2C_INTERNAL_CLOCK (12000000u) /* I2C bus speed or frequency - 100Khz */ #define I2C_OUTPUT_CLOCK (100000u) /* I2C interrupt flags to clear #define I2C_INTERRUPT_FLAG_TO_CLR /* Buffer Size */ #define BUFFER_SIZE */ (0x7FF) (1024) /****************************************************************************** ** INTERNAL FUNCTION PROTOTYPES *******************************************************************************/ static void setup_platform(void); static void print_data(unsigned char *data, unsigned int size); static void setup_I2C(void); static void setup_UART(void); static void SetupI2CTransmit(unsigned int dcount); static void SetupReception(unsigned int dcount); Octavo Systems LLC Copyright 2018 20 21 OSD335x EEPROM During Boot Rev.1 6/11/2018 /****************************************************************************** ** INTERNAL VARIABLE DEFINITIONS *******************************************************************************/ volatile unsigned char dataToSlave[BUFFER_SIZE]; volatile unsigned char dataFromSlave[BUFFER_SIZE]; volatile unsigned int tCount; volatile unsigned int rCount; /****************************************************************************** ** FUNCTION DEFINITIONS ******************************************************************************/ int main(void) { volatile unsigned char data[NUM_BYTES_TO_WRITE] = EEPROM_VALUE_TO_WRITE; volatile unsigned int i, j; // Setup the platform setup_platform(); // Initialize variables for (i = 0; i < (NUM_BYTES_TO_WRITE + 2); i++) { dataToSlave[i] = 0; dataFromSlave[i] = 0; } UARTPuts("Octavo Systems EEPROM Writer v0.1\n", -1); // Write data to the EEPROM // - Setup Address // - Copy data to write // - Transmit data // UARTPuts("Writing value to EEPROM\n", -1); tCount = 0; dataToSlave[0] = E2PROM_ADDR_MSB; dataToSlave[1] = E2PROM_ADDR_LSB; for (i = 0; i < NUM_BYTES_TO_WRITE; i++) {dataToSlave[i + 2] = data[i];} print_data((unsigned char *)&dataToSlave[2], NUM_BYTES_TO_WRITE); SetupI2CTransmit(NUM_BYTES_TO_WRITE + 2); UARTPuts("Done writing.\n", -1); // Wait for EEPROM to finish writing j = 0; for (i = 0; i < 1000000; i++) { j++; } // Read data back from EEPROM // - Use the address from the current dataToSlave buffer rCount = 0; tCount = 0; SetupReception(NUM_BYTES_TO_WRITE); // Print data from EEPROM UARTPuts("Value Written:\n", -1); print_data((unsigned char *)dataFromSlave, NUM_BYTES_TO_WRITE); UARTPuts("Done.\n", -1); while(1); } Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 /* * \brief This function Initializes WDT, UART, and I2C * * \param none * * \return none */ void setup_platform(void) { // Disable WDT HWREG(SOC_WDT_1_REGS + WDT_WSPR) = 0xAAAAu; while(HWREG(SOC_WDT_1_REGS + WDT_WWPS) != 0x00); HWREG(SOC_WDT_1_REGS + WDT_WSPR) = 0x5555u; while(HWREG(SOC_WDT_1_REGS + WDT_WWPS) != 0x00); /* Enable the control module */ HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CONTROL_CLKCTRL) = CM_WKUP_CONTROL_CLKCTRL_MODULEMODE_ENABLE; /* UART Initialization */ setup_UART(); UARTStdioInit(); /* I2C Initialization */ setup_I2C(); } /* ** Print data */ static void print_data(unsigned char *data, unsigned int size) { unsigned char ch[2]; unsigned char temp; unsigned int i; if ((BUFFER_SIZE / 4) < size) { // Print error message UARTPuts("Too much data requested \n", -1); return; } ch[1] = 0; // Print first character UARTPuts("[", 1); for (i = 0; i < size; i++) { // Collect the Most Significant Nibble of the data byte temp = ((data[i] & 0xF0) >> 4); if (temp < 10) { // UARTPrintf("%c", (temp + 0x30)); ch[0] = temp + 0x30; UARTPuts(ch, 1); } else { // UARTPrintf("%c", (temp + 0x37)); ch[0] = temp + 0x37; UARTPuts(ch, 1); } // Collect the Least Significant Nibble of the data byte temp = (data[i] & 0x0F); if (temp < 10) { // UARTPrintf("%c", (temp + 0x30)); ch[0] = temp + 0x30; Octavo Systems LLC Copyright 2018 22 23 OSD335x EEPROM During Boot Rev.1 6/11/2018 UARTPuts(ch, 1); } else { // UARTPrintf("%c", (temp + 0x37)); ch[0] = temp + 0x37; UARTPuts(ch, 1); } } } if (i < (size - 1)) { UARTPuts(", ", 2); } // Print final character UARTPuts("]\n", -1); /****************************************************************************** ** I2C FUNCTION DEFINITIONS ******************************************************************************/ /* * \brief Configure I2C0 on which the PMIC is interfaced * * \param none * * \return none */ void setup_I2C(void) { /* Enable the clock for I2C0 */ I2C0ModuleClkConfig(); I2CPinMuxSetup(I2C_0); /* Put i2c in reset/disabled state */ I2CMasterDisable(SOC_I2C_0_REGS); /* Disable auto Idle functionality */ I2CAutoIdleDisable(SOC_I2C_0_REGS); /* Configure i2c bus speed to 100khz */ I2CMasterInitExpClk(SOC_I2C_0_REGS, I2C_SYSTEM_CLOCK, I2C_INTERNAL_CLOCK, I2C_OUTPUT_CLOCK); /* Set i2c slave address */ I2CMasterSlaveAddrSet(SOC_I2C_0_REGS, I2C_SLAVE_ADDR); /* Bring I2C out of reset */ I2CMasterEnable(SOC_I2C_0_REGS); while(!I2CSystemStatusGet(SOC_I2C_0_REGS)); } /* * \brief Clear the status of all interrupts * * \param none. * * \return none */ void CleanupInterrupts(void) { I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INTERRUPT_FLAG_TO_CLR); } Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 /* * \brief Transmits data over I2C0 bus * * \param none * * \return none */ void SetupI2CTransmit(unsigned int dcount) { I2CSetDataCount(SOC_I2C_0_REGS, dcount); CleanupInterrupts(); I2CMasterControl(SOC_I2C_0_REGS, I2C_CFG_MST_TX); I2CMasterStart(SOC_I2C_0_REGS); while(I2CMasterBusBusy(SOC_I2C_0_REGS) == 0); while((I2C_INT_TRANSMIT_READY == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_TRANSMIT_READY)) && dcount--) { I2CMasterDataPut(SOC_I2C_0_REGS, dataToSlave[tCount++]); } I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY); I2CMasterStop(SOC_I2C_0_REGS); while(0 == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_STOP_CONDITION)); I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INT_STOP_CONDITION); } /* * \brief Receives data over I2C0 bus * * \param dcount - Number of bytes to receive. * * \return none */ void SetupReception(unsigned int dcount) { unsigned int num_addr_bytes = 2; // Transmit Address Bytes I2CSetDataCount(SOC_I2C_0_REGS, num_addr_bytes); CleanupInterrupts(); I2CMasterControl(SOC_I2C_0_REGS, I2C_CFG_MST_TX); I2CMasterStart(SOC_I2C_0_REGS); while(I2CMasterBusBusy(SOC_I2C_0_REGS) == 0); while((I2C_INT_TRANSMIT_READY == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_TRANSMIT_READY)) && num_addr_bytes--) { I2CMasterDataPut(SOC_I2C_0_REGS, dataToSlave[tCount++]); I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INT_TRANSMIT_READY); } I2CMasterStop(SOC_I2C_0_REGS); while(0 == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_ADRR_READY_ACESS)); Octavo Systems LLC Copyright 2018 24 25 OSD335x EEPROM During Boot Rev.1 6/11/2018 // Receive Data Bytes I2CSetDataCount(SOC_I2C_0_REGS, dcount); CleanupInterrupts(); I2CMasterControl(SOC_I2C_0_REGS, I2C_CFG_MST_RX); I2CMasterStart(SOC_I2C_0_REGS); /* Wait till the bus if free */ while(I2CMasterBusBusy(SOC_I2C_0_REGS) == 0); /* Read the data from slave of dcount */ while((dcount--)) { while(0 == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_RECV_READY)); dataFromSlave[rCount++] = I2CMasterDataGet(SOC_I2C_0_REGS); I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INT_RECV_READY); } I2CMasterStop(SOC_I2C_0_REGS); while(0 == (I2CMasterIntRawStatus(SOC_I2C_0_REGS) & I2C_INT_STOP_CONDITION)); I2CMasterIntClearEx(SOC_I2C_0_REGS, I2C_INT_STOP_CONDITION); } /****************************************************************************** ** UART FUNCTION DEFINITIONS ******************************************************************************/ /* * \brief This function is used to initialize and configure UART Module. * * \param none. * * \return none */ void setup_UART(void) { volatile unsigned int regVal; /* Enable clock for UART0 */ regVal = (HWREG(SOC_CM_WKUP_REGS + CM_WKUP_UART0_CLKCTRL) & ~(CM_WKUP_UART0_CLKCTRL_MODULEMODE)); regVal |= CM_WKUP_UART0_CLKCTRL_MODULEMODE_ENABLE; HWREG(SOC_CM_WKUP_REGS + CM_WKUP_UART0_CLKCTRL) = regVal; } UARTStdioInit(); Octavo Systems LLC Copyright 2018 OSD335x EEPROM During Boot Rev.1 6/11/2018 9 Appendix B: hsi2cEeprom.lds /* * Copyright (C) 2010 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. * */ /* ld script for StarterWare AM335x. */ /* ** The stack is kept at end of the image, and its size is 128 MB. ** The heap section is placed above the stack to support I/O ** operations using semihosting. The size of the section is 2KB. */ MEMORY { IRAM_MEM : } o = 0x402F0400, l = 0x1FBFF /* 127k internal Memory */ OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") OUTPUT_ARCH(arm) SECTIONS { .rsthand : { . = ALIGN(4); *bl_init.o } >IRAM_MEM (.text) .text : { . = ALIGN(4); *(.text*) *(.rodata*) } >IRAM_MEM .data : Octavo Systems LLC Copyright 2018 26 27 OSD335x EEPROM During Boot Rev.1 6/11/2018 { . = ALIGN(4); *(.data*) } >IRAM_MEM .bss : { . = ALIGN(4); _bss_start = .; *(.bss*) *(COMMON) _bss_end = .; } >IRAM_MEM .heap : { . = ALIGN(4); __end__ = .; end = __end__; __HeapBase = __end__; *(.heap*) . = . + 0x800; __HeapLimit = .; } >IRAM_MEM .stack : { . = ALIGN(256); __StackLimit = . ; *(.stack*) . = . + 0x800; __StackTop = .; } >IRAM_MEM _stack = __StackTop; } Octavo Systems LLC Copyright 2018
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf Linearized : No Page Count : 27 PDF Version : 1.4 Title : Microsoft Word - OSD335x_EEPROM_during_boot_v04.docx Producer : Mac OS X 10.12.6 Quartz PDFContext Creator : Word Create Date : 2018:06:13 16:13:48Z Modify Date : 2018:06:13 16:13:48ZEXIF Metadata provided by EXIF.tools