Thứ Sáu, 14 tháng 12, 2018

How To Use SPM To load Application from EEPROM

Developed By: 

Akshay Daga
In any microcontroller the Boot-Loader is the first code which executes before the application code does. The major function of the Boot-Loader is to load the application code into the flash memory of the microcontroller and execute it. In AVR microcontroller the Self Programming Mode(SPM) helps the Boot-Loader to load a particular application from where the application binary is stored.The Boot-Loader may receive the code binary from other memory chips, SD-cards or through the serial port of the microcontroller in case of serial programming.
It is then with the help of the SPM that the microcontroller write the binary code into the application flash section.
In this particular project the operation of a Boot-Loader code using the SPM is demonstrated by re-writing flash memory with the code binary which has already been flashed into the built-in EEPROM of the ATMEGA16. The hardware used in this project includes ATMEGA16 as microcontroller, USBASP as the programmer and the software used are AVR STUDIO 4 as IDE and AVR-BURNO-MAT as the burner software.
How To Use SPM To load Application from EEPROM

The BLS section is normally used for storing the Boot-loader code for the microcontroller. The Boot-Loader code can be used for initializing the peripherals in the microcontroller, initialize the devices connected to the microcontroller, select the application to load and execute from a storage medium, load the selected application to the application section, jump to the application section and execute the application. The code running in the BLS section can execute Self Programing Mode (SPM) instructions which are blocked for the code running in the Application section. Using SPM instructions the code from the BLS can rewrite the code in the application section or the code in the BLS itself.







Configuring SPM To load Application from EEPROM in AVR Prototype
Fig. 2: Block Diagram of SPM function with BLS in AVR
The task of writing the BLS code with SPM has been made simple by the APIs available in the header file <avr/boot.h>. The following are the important APIs available in the header file which helps in the SPM.
FUNCTION
DESCRIPTION
PARAMETER
boot_page_erase (address)
Erase the flash page that is referred by address
A byte address in flash
boot_page_fill             (address, data)   
Fill the Boot-Loader temporary page buffer for flash address with data word
The address is a byte address. The data is a word
boot_page_write (address)
Write the Boot-Loader temporary page buffer to flash page that contains address
Byte address in flash
Fig. 3: Important APIs for AVR's SPM Function
 Using the above APIs one can write a code for SPM in an AVR microcontroller provided that the code should follow certain steps in the order.
·         Step: 1 Erase the flash page which is about to write into
{C·         Step: 2 Store the binaries in a temporary buffer before write into a flash page
{C}·         Step: 3 Program the filled temporary buffer into the already erased flash page
The above three steps are explained with details in a previous project on AVR SPM. In this particular project the data that is required to fill the temporary page buffer as discussed in the step: 2 is taken from the built-in EEPROM of the AVR microcontroller where a simple code has already been flashed into. The internal EEPROM of the AVR microcontroller has 512 bytes capacity. It can be easily read and write with the help of APIs available in the header file <avr/eeprom.h>. The following are the important APIs available in the header file which helps in accessing the EEPROM memory.
FUNCTION
DESCRIPTION
void eeprom_is_ready (void)
Returns 1 if EEPROM is ready for a new read/write operation, 0 if not
void eeprom_read_block (void *dst, const void *src, size_t  n )       
Returns a block of n bytes from EEPROM address src to SRAM dst
uint8_t eeprom_read_byte (const uint8_t *p)
Returns one byte from EEPROM address referred by the pointer p
uint32_t eeprom_read_dword (const uint32_t *p)
Read one 32-bit double from EEPROM address referred by the pointer p
float eeprom_read_float (const float *p)
Returns one float value from EEPROM referred by the pointer p
uint16_t eeprom_read_word (const uint16_t *p)
Read one 16-bit word from EEPROM address referred by the pointer p
void eeprom_update_block (const void *src, void *dst, size_t  n)
Update a block of n bytes to EEPROM address dst from src
void eeprom_update_byte (uint8_t *p, uint8_t  value)            
Update a byte value to EEPROM address referred by the pointer p
void eeprom_update_dword (uint32_t *p,uint32_t  value)            
Update a 32-bit double word value to EEPROM address referred by the pointer p
void eeprom_update_float (float *p, float value)
Update a float value to EEPROM address referred by the pointer p
void eeprom_update_word (uint16_t *p, uint16_t  value)            
Update a word value to EEPROM address referred by the pointer p
void eeprom_write_block (const void *src, void *dst, size_t  n)         
Write a block of n bytes to EEPROM address dst from src.
void eeprom_write_byte (uint8_t *p, uint8_t value)
Write a byte value to EEPROM address referred by the pointer p
void eeprom_write_dword (uint32_t *p, uint32_t  value)            
Write a 32-bit double word value to EEPROM address referred by the pointer p
void eeprom_write_float (float *p, float value)
Write a float value to EEPROM referred by the pointer p
void eeprom_write_word (uint16_t *p, uint16_t value)
Write a word value to EEPROM referred by the pointer p
Fig. 4: APIs to access EEPROM memory 
The data for filling the temporary buffer as discussed in the step: 2 is read from the built-in EEPROM memory of the AVR microcontroller using the library function;
uint8_t eeprom_read_byte (const uint8_t *p)
The above function can return the data byte which is stored in the EEPROM address referred by the pointer argument. The code is written in such a way that the pointer first points to the 0th location of the EEPROM and then increases the address as it reads each byte for storing in the temporary buffer. Thus the steps with which binary of a code are read from the EEPROM memory and flashing the same into the flash memory is represented pictorially in the following;
Step: 1 Erase the flash page which is about to write into
The first step is to erase the flash page which is about to be written with the new values. The API which helps in executing this step is;
Boot_page_erase (address)
This API can erase an entire page in the flash which the parameter addresses. In the code the address of the page erased is 256. The following image shows the status of the temporary page buffer and the flash memory at the step 1. The temporary page buffer is a buffer in which an entire page can be stored before it is flashed into a page in the flash memory.







Block Diagram of PageErase in SPM Function
Fig. 5: Block Diagram of PageErase in SPM Function
Step: 2 Store the values in a temporary buffer before write into a flash page
This is the second step in which one should store the required binary in a temporary buffer, before writing to any of the flash memory page. The API that can be used for this purpose is;
boot_page_fill             (address, data)
This API fills the Boot-Loader temporary page buffer byte by byte before flashing the data in the temporary page buffer into a page as such. The parameter data represents each byte in the buffer and the parameter address represents the page address + offset of the buffer location where the data byte need to be stored.The parameter data in the API boot_page_fill (address, data) is actually read from the first location of EEPROM memory with the help of an API which is available in the header file <avr/eeprom.h>.
uint8_t eeprom_read_byte (const uint8_t *p)

FUNCTION
DESCRIPTION
PARAMETER
uint8_t eeprom_read_byte (const uint8_t *p)
The function returns one data byte which is stored in the EEPROM address referred by the pointer p
The pointer refers to the EEPROM address from which the data byte need to be read

Block Diagram Loading Temporary Buffer for AVR's SPM
Fig. 6: Block Diagram Loading Temporary Buffer for AVR's SPM
Step: 3 Program the filled temporary buffer into the already erased flash page
This is the final step in which the filled temporary buffer is flashed using an API into already erased page of the flash memory. The API which helps in this step is;
 
boot_page_write (address)
Block Diagram of Page Write in flash Memory
Fig. 7: Block Diagram of Page Write in flash Memory
The code in this project which is written for the BLS can copy 300bytes from the EEPROM memory into the temporary buffer starting from the address 0x00. These bytes are then flashed into the flash memory page starting from the address 0x0000. After doing this the code from the BLS will make a jump to the address 0x0000 so that the re-written binary can be executed next. 
With this boot loader code, whatever program flashed into the EEPROM will get rewritten at the Application flash section of the AVR and get executed. A simple LED blinking test application can be written into the EEPROM memory starting to test the working.bFlash the code for the BLS first and then the LED application code to the EEPROM memory using the steps explained in the previous project on LED blinking from BLS of AVR.
When the led blinks, it means that the code has been loaded from one section of the EEPROM memory to the flash memory and is executing. With that the code in the BLS can load any application which is programmed into the EEPROM on reset and hence it acts like a Boot-Load  
LED Blinking using SPM Function of AVR Circuit on breadboard
Fig. 8: LED Blinking using SPM Function of AVR Circuit on breadboard

Circuit:
Circuit Diagram of How To Use SPM To load Application from EEPROM

Code:
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/boot.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h>
#include <avr/eeprom.h>
 
int main ( void )
{
uint16_t i;
uint8_t A [ 300 ];
uint8_t sreg;
uint32_t page = 0;
unsigned char *buf = A;
uint16_t w;
volatile int j = 2;
 
DDRD |= 0x80;
 
for ( i = 0; i < 3; i ++ )
{
PORTD &= 0x7F;
_delay_ms ( 500 );
PORTD |= 0x80;
_delay_ms ( 500 );
}
 
for ( i = 0; i < 300; i ++ )
A [ i ] = eeprom_read_byte ((const uint8_t *) i); 
 
while(1)
{
//==============================================================================//
if(j)
{
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait ();      // Wait until the memory is erased.
 
for (i=0; i<SPM_PAGESIZE; i+=2)
{
   // Set up little-endian word.
   w = *buf++;
   w += (*buf++) << 8;
 
   boot_page_fill (page + i, w);
}
boot_page_write (page);     // Store buffer in flash page.
boot_spm_busy_wait();       // Wait until the memory is written.
boot_rww_enable ();
SREG = sreg;
}
else
{
asm ( "jmp 0x0000" );
}
 
j--;
page = page + 128;
//==============================================================================//
}
 
}
 
Code 2:
#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>
 
int main ( void )
{
DDRD |= 0x80;
 
while(1)
{
PORTD &= 0x7F;
_delay_ms ( 2000 );
PORTD |= 0x80;
_delay_ms ( 2000 );
}
 
}
 

Không có nhận xét nào:

Đăng nhận xét

Bài đăng mới nhất

Hướng dẫn sử dụng Cân điện tử Fujihatsu FTC-01

Hướng dẫn sử dụng Cân điện tử Fujihatsu FTC-01 # candientu ,  # fujihatsu ,  # candientufujihatsu  #candientu,  # candientufujhatsu , #fuji...

Bài đăng phổ biến