我在(Atmega16a)中调用函数时在引导加载程序应用程序中遇到问题,他运行良好的引导加载程序但将此目标更改为 ATmega128 函数 bootloaderDriver 无法加载到程序内存中
这是什么问题 我在 Atmega16 中设置引导加载程序大小为 256 字,而 Atmega128 为 512 字 ATmega16 中的字节地址是 0x3E00 和 ATmega128 中的 0x1FC00
#ifndef APP_H
#define APP_H
#define CALL_POINT (0)
#define ROOM_POINT (1)
#define DISPLAY_POINT (2)
#define SAVE_POINT (3)
#define DEVICE_TYPE (DISPLAY_POINT)
#define __FLASH_RECOVER (0)
#define F_CPU 11059200UL
//#include <xc.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <avr/pgmspace.h>
#include <avr/io.h>
#include <math.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdio.h>
#include <avr/boot.h>
#include "macros.h"
#include "types.h"
#if DEVICE_TYPE == CALL_POINT
#include "../../../../Nurse System/Nurse Call Point/SW/Call Point V1/CallPoint.X/inc/boardinfo.h"
#elif DEVICE_TYPE == ROOM_POINT
#include "../../../../Nurse System/Nurse Room/SW/Room Sw V1/NurseRoom.X/inc/boardinfo.h"
#elif DEVICE_TYPE == DISPLAY_POINT
#include "../../../../Nurse System/Nurse Display/SW/Display Sw V1/NurseDisplay.X/inc/boardinfo.h"
#elif DEVICE_TYPE == SAVE_POINT
#include "../../../../Nurse System/Nurse Master/SW/Master SW V1/NurseMaster.X/inc/boardinfo.h"
#endif
#ifdef __HAS_ELPM__
typedef unsigned long MyAddressType;
#else
typedef unsigned int MyAddressType;
#endif
static const uint8_t FlashboardInfoBackup[SPM_PAGESIZE] __attribute__((section(".varaddress"))) = {0};
static const uint8_t FlashboardInfo[SPM_PAGESIZE] __attribute__((section(".varaddress"))) = {0};
#define MIN_ADDREES (0)
#if defined(__AVR_ATmega128A__) || defined (__AVR_ATmega128__)
#define BOOTSECTORSIZE 0x400 // 512 word * 2 = 1024 Byte
#elif defined(__AVR_ATmega16__)|| defined(__AVR_ATmega16A__)
#define BOOTSECTORSIZE 0x200 // 256 word * 2 = 512 Byte
#endif
#define ADR_FLASH_BUFFER (MyAddressType)(FlashboardInfoBackup) // get page address from byte
#define MAX_ADDRESS FLASHEND-BOOTSECTORSIZE
#define FLASH_BUFFER_FULL_ID 0xAA
#define APP_START asm("JMP 0x0000")
#if __FLASH_RECOVER
typedef struct {
uint16_t pageNumber; /*0x0000*/
uint8_t status; /*0x0002*/
} stFlashBackup_t;
stFlashBackup_t EEMEM FlashBackup = {0};
#endif
static inline uint8_t _FlashAddressCheck(MyAddressType flashAdr);
static inline void WriteBufToFlash(MyAddressType flashStartAdr);
static inline void ReadModifyStoredTempPageBuf(MyAddressType flashAddr, uint8_t data);
#if __FLASH_RECOVER
static inline void RecoverFlash();
#endif
static inline uint8_t WriteFlashPage(MyAddressType flashStartAdr, uint8_t *dataPage);
static inline uint8_t WriteFlashByte(MyAddressType flashAddr, uint8_t data);
static inline uint8_t ReadFlashPage(MyAddressType flashStartAdr, uint8_t *dataPage);
static inline uint8_t ReadFlashByte(MyAddressType flashStartAdr);
static inline uint8_t ReadFlashByte(MyAddressType flashStartAdr);
static inline uint8_t _FlashAddressCheck(MyAddressType flashAdr) {
#if __FLASH_RECOVER
if (
(flashAdr >= MIN_ADDREES) && /*address large than or equals start application address*/
(flashAdr <= MAX_ADDRESS) && /*address less than or equals end application address*/
(flashAdr != ADR_FLASH_BUFFER) &&/*address != Page 0 (information of the recovery mode*/
!(flashAdr & (SPM_PAGESIZE - 1))) { /*address fill into page */
return (1);
} else {
return (0);
}
#else
if (
(flashAdr >= MIN_ADDREES) && /*address large than or equals start application address*/
(flashAdr <= MAX_ADDRESS) && /*address less than or equals end application address*/
!(flashAdr & (SPM_PAGESIZE - 1))) { /*address fill into page */
return (1);
} else {
return (0);
}
#endif
}
static inline void WriteBufToFlash(MyAddressType flashStartAdr)__attribute__((unused));
static inline void WriteBufToFlash(MyAddressType flashStartAdr) {
#ifdef __HAS_RAMPZ__ /*AVR uses the RAMPZ to access constant data above the 64K-byte boundary
https://imagecraft.com/help/ICCV8AVR/iccavr/6-programmingavr/accessing_memory_outside_of_the_64k_range.htm
*/
flashStartAdr = (uint8_t) (flashStartAdr >> 16);
#endif
boot_page_erase(flashStartAdr); /*erase page*/
boot_spm_busy_wait(); /*wait for flash erase operation completed*/
boot_page_write(flashStartAdr); /*store data Into Flash*/
boot_spm_busy_wait(); /*wait for flash write operation completed*/
boot_rww_enable(); /*enable read while write */
}
static inline void ReadModifyStoredTempPageBuf(MyAddressType flashAddr, uint8_t data) {
/*
*
< Z-register
-------------------------------------
| PCPAGE : Page address in the flash
| PCWORD : address with in page
*/
uint16_t byteWrite; /*R21,R2*/
uint8_t oddByte; /*odd address indicator 0 when even and 1 when address is odd*/
uint16_t pcWord; /* program counter word count in page The content of PCWORD in the Z-register is used to address the data in the temporary buffer*/
MyAddressType pageAdr; /*first address of the Page `*/
oddByte = (uint8_t) (flashAddr & 1); /* 0bxxxxxxx1 is defined odd number and 0bxxxxxxx0 is even numbers (0bxxxxxxx1 &00000001) = 1 and (0bxxxxxxx0 & 0x00000001 = 0) */
/*
< @note SPM_PAGESIZE = number of byte in page
* for example system has 32 word 0 to 31 words = (0 to 31*2 Bytes)
* to get address of the word from address of the byte
* to get address word of current byte address (byte address & 62)
*/
pcWord = ((uint16_t) flashAddr & (SPM_PAGESIZE - 2)); /*start byte address in word*/
/* < page is 8 Byte size
* the last byte address is 7 for any address is & ~7 ((remove is first 3 bit is zero))
* 00 to 07 is 00 start address of the page page 0
* 08 to 15 is 08 start page 1
* 16 to 23 is 16 start page 2
* 24 to 31 is 24 start page 3
*/
/*
< @note SPM_PAGESIZE = number of byte in page
* for example system has 64 byte per page = (0 to 63 Bytes)
* to get page address is 0 or 1 or 2 or ......... of the current byte adderss
* get last address byte (~63) and & with this value
*/
pageAdr = flashAddr & (~(SPM_PAGESIZE - 1)); // get page address from byte address into page
for (uint16_t index = 0; (index < SPM_PAGESIZE); index += 2) { /*Increment by 2 because the index indicate two byte (word (Instruction))*/
if (index == pcWord) { /*index reach current address access in the page*/
/* <
* flash address & ~1 fill same address odd with even
* 0 1 word 1 (byte 0 stored in LSB in address (word count) 1 and byte 1 stored in MSB in the same address)
* 2 3 word 2 (byte 0 stored in LSB in address (word count) 2 and byte 1 stored in MSB in the same address)
* 4 5 word 3 (byte 0 stored in LSB in address (word count) 3 and byte 1 stored in MSB in the same address)
* 6 7 word 4 (byte 0 stored in LSB in address (word count) 4 and byte 1 stored in MSB in the same address)
* from table LSB strored in even and MSB stored into odd
*/
if (oddByte) { /*current address is odd address*/
/* current index is 6 and current address is 7
* get data from even address of the current Odd address (7&~1) = 6 7 is current odd address , 6 even address result
* and set this data in LSB and stored current data in MSB
*/
/*
* get even address data and or with current data
*/
byteWrite = (pgm_read_word(index + pageAdr) & 0x00FF) | ((uint16_t) (data << 8));
} else {
/* current index is 6 and current address is 6
* get data from odd address of the current even number and stored into MSB and stored
* current address in LSB
*/
byteWrite = (pgm_read_word(index + pageAdr) & 0xFF00) | ((uint16_t) (data));
// bootFillPage(byteWrite, index); // Write even byte in temporary buffer
}
} else { /*current index not equals current word count */
/*store other data of the page into temp buffer*/
byteWrite = pgm_read_word(index + pageAdr);
}
boot_page_fill(index, byteWrite);
}
}
#if __FLASH_RECOVER
static inline void RecoverFlash() {
uint16_t index;
if (FlashBackup.status == FLASH_BUFFER_FULL_ID) { /*check recover page contians data or not*/
for (index = 0; index < SPM_PAGESIZE; index += 2) { // Writes to Flash write buffer
boot_page_fill(index, pgm_read_word(ADR_FLASH_BUFFER + index)); /*write Page 0 in temp page buffer*/
}
WriteBufToFlash((MyAddressType) (FlashBackup.pageNumber * SPM_PAGESIZE)); /*write data into fill buffer to recover*/
FlashBackup.status = 0;
eeprom_busy_wait(); /*wait free eeprom*/
return;
}
return;
}
#endif
static inline uint8_t WriteFlashPage(MyAddressType flashStartAdr, uint8_t *dataPage) {
uint16_t index;
uint8_t eepromInterruptSettings;
if (_FlashAddressCheck(flashStartAdr)) { /*check the address valid or not*/
eepromInterruptSettings = EECR & (_BV(EERIE)); /*save Interrupt state of the eeprom*/
EECR &= ~_BV(EERIE); /*Disable EEPROM Interrupt*/
eeprom_busy_wait(); /*wait eeprom is ready*/
#if __FLASH_RECOVER /*before write data save cureent page write to Page 0 (recovery Buffer)*/
FlashBackup.status = 0; /*reset recovery mode (recovery buffer is empty)*/
eeprom_busy_wait(); /*status write into eeprom wait for write operation is done*/
for (index = 0; index < SPM_PAGESIZE; index += 2) { /*Fills Flash write buffer*/
boot_page_fill(index, (uint16_t) dataPage[index]+((uint16_t) dataPage[index + 1] << 8)); /*fill even and odd byte or fill odd and even byte in word address*/
}
WriteBufToFlash(ADR_FLASH_BUFFER); // Writes to Flash recovery buffer
FlashBackup.pageNumber = (uint16_t) (flashStartAdr / SPM_PAGESIZE); /*page number from current address and page size*/
FlashBackup.status = FLASH_BUFFER_FULL_ID; // Indicates that Flash recovery buffer
eeprom_busy_wait(); /*wait eeprom is ready because the FlashBackup stored in eeprom*/
#endif
/*save Page into buffer*/
for (index = 0; index < SPM_PAGESIZE; index += 2) { // Fills Flash write buffer
boot_page_fill(index, (uint16_t) dataPage[index]+((uint16_t) dataPage[index + 1] << 8)); /*fill even and odd byte or fill odd and even byte in word address*/
}
WriteBufToFlash(flashStartAdr); // Writes Page to Flash
#if __FLASH_RECOVER
FlashBackup.status = 0; /* indicate that Flash buffer does not contain data for writing*/
eeprom_busy_wait(); /*wait eeprom is ready because the FlashBackup stored in eeprom*/
#endif
EECR |= eepromInterruptSettings; // Restore EEPROM interrupt state
return (1); /*write page operation is done*/
}
return (0); /*address valid and no write page*/
}
static inline uint8_t WriteFlashByte(MyAddressType flashAddr, uint8_t data) {
MyAddressType pageAdr;
uint8_t eepromInterruptSettings;
uint8_t state;
state = SREG;
cli();
if (_FlashAddressCheck(flashAddr & ~(SPM_PAGESIZE - 1))) { /*start address of the Page of the current address */
eepromInterruptSettings = EECR & (1 << EERIE); /* save EEPROM interrupt state*/
EECR &= ~(1 << EERIE); /* Disable EEPROM interrupt */
eeprom_busy_wait(); /*wait for eeprom is ready to stored recovery state*/
pageAdr = flashAddr & (~(SPM_PAGESIZE - 1)); /* start address of the Page of the current address*/
#if __FLASH_RECOVER
FlashBackup.status = 0; /* Indicate Recovery buffer is empty*/
eeprom_busy_wait(); /*wait for eeprom is ready to stored recovery state*/
ReadModifyStoredTempPageBuf(flashAddr, data); /*Fills Flash write buffer*/
WriteBufToFlash(ADR_FLASH_BUFFER); /* Writes to Flash recovery buffer*/
FlashBackup.pageNumber = (unsigned int) (pageAdr / SPM_PAGESIZE); /*get Page number*/
FlashBackup.status = FLASH_BUFFER_FULL_ID; /*Indicates that Flash recovery buffer is Full*/
eeprom_busy_wait(); /*wait for eeprom is ready to stored recovery state and page number*/
#endif
ReadModifyStoredTempPageBuf(flashAddr, data); /* Fills Flash write buffer*/
WriteBufToFlash(pageAdr); /* Writes to Flash with word address*/
#if __FLASH_RECOVER
FlashBackup.status = 0; // Indicates that Flash recovery buffer
eeprom_busy_wait(); /*wait for eeprom is ready to stored recovery state */
#endif
EECR |= eepromInterruptSettings; // Restore EEPROM interrupt state
SREG = state;
return (1); /* return 1 if address valid for writing*/
}
return (0); /*return 0 if address not valid for writing*/
}
static inline uint8_t ReadFlashByte(MyAddressType flashStartAdr) {
return (uint8_t) (pgm_read_byte(flashStartAdr)); /*return data stored into flash address*/
}
static inline uint8_t ReadFlashPage(MyAddressType flashStartAdr, uint8_t *dataPage) {
uint16_t index;
if (!(flashStartAdr & (SPM_PAGESIZE - 1))) { /* input address is a page address*/
for (index = 0; index < SPM_PAGESIZE; index++) {
dataPage[index] = ReadFlashByte(flashStartAdr + index); /*get data from address and stored into buffer*/
}
return 1; /* return 1 if valid page address*/
} else {
return 0; /* return 0 if not valid page address*/
}
}
static inline void bootloaderDriver() {
/*check the state of the Ram */
volatile boardinfo_t *BoardInfo;
uint8_t buf[SPM_PAGESIZE];
for (uint8_t i = 0; i < SPM_PAGESIZE; i++) {
buf[i] = 0x00;
}
BoardInfo = (boardinfo_t *) (BoardInfoAddress);
uint8_t *BoradInfoBytes = (uint8_t *) BoardInfo;
if (BoardInfo->State == 1) {
for (uint8_t i = 0; i< sizeof (boardinfo_t); i++) {
buf[i] = BoradInfoBytes[i + 1];
}
WriteFlashPage((MyAddressType) (FlashboardInfo), buf);
BoardInfo->State = 0;
}
#if __FLASH_RECOVER
RecoverFlash();
#endif
for (uint8_t i = 0; i< sizeof (boardinfo_t) + 1; i++) {
BoradInfoBytes[i + 1] = pgm_read_byte(FlashboardInfo + i);
}
APP_START;
}
#endif /* APP_H */
主要功能是
#include "../inc/app.h"
__attribute__((naked)) __attribute__((section(".ctors"))) void boot(void) {
asm volatile("clr r1");
pgm_read_byte(&FlashboardInfoBackup[0]); /*init the backup to 0*/
while (1) {
bootloaderDriver();
}
}