📄 nf_loader.c
字号:
#endif
//! Init to make it possible the resumes of a loading by dfc transfert
//!
//! @param none
//! @return none
//!
void nfloader_init_resume_module( void )
{
// Prepare NFC for the next DFC flow
Nfc_action( NFC_ACT_STOP, 0 ); // Ensures NFC is idle
// Configure NFC/DFC transfer mode.
Nfc_mode_manual();
Nfc_clear_it_all(); // Clear all its.
}
//! Resume the loading of a NF page by dfc transfert
//!
//! @param none
//! @return none
//!
void nfloader_resume_module( void )
{
if( Is_nfc_running() ) return;
if(0 == s_mod_hdl.nb_pages)
{
s_mod_hdl.i_frag++;
// Load device_number, page_addr and nb_pages
Nfloader_load_hdl();
}
Mcu_set_sfr_page_nfc();
Nfc_action( NFC_ACT_DEV_SELECT, s_mod_hdl.device_number );
// NOTE : for the firmware zone, the offset may be != 0 for the first sector
// loading. For the next sectors, the offset is 0 => s_mod_hdl.offset = 0;
nfc_open_page_read( s_mod_hdl.page_addr, s_mod_hdl.offset );
s_mod_hdl.offset = 0;
Nfc_action( NFC_ACT_READ, 0 );
s_mod_hdl.page_addr++;
s_mod_hdl.nb_pages--;
}
//! Read version of codec
//!
//! @param buffer to store version
//! @return none
//!
void nfloader_read_version( U8 _MEM_TYPE_SLOW_ *buffer )
{
U16 u16_i;
U8 u8_i;
Mcu_set_sfr_page_nfc();
Nfc_action( NFC_ACT_DEV_SELECT, s_mod_hdl.device_number );
nfc_open_page_read( s_mod_hdl.page_addr, s_mod_hdl.offset );
for( u16_i=0x100+18+1; u16_i!=0 ; u16_i-- )
{ // +100h offset version ; +18 not read text version ; +1 Dummy read
ACC= Nfc_rd_data_fetch_next();
}
for( u8_i=6; u8_i!=0 ; u8_i-- )
{ // read "x.x.xx"
*buffer = Nfc_rd_data_fetch_next();
buffer++;
}
*buffer = 0;
}
//! Compute the physic address of the logical address 0 in the current module
//!
//! @param none
//! @return none
//!
void nfloader_compute_physic_addr_0( void )
{
s_mod_hdl.nb_frag = s_module.nb_frag; // Information just for debug information
s_mod_hdl.i_frag = 0;
s_mod_hdl.offset = 0;
// Compute device_number, page_addr and nb_pages in s_mod_hdl.offset
Nfloader_load_hdl();
s_mod_hdl.page_addr += (U32) s_module.start_page;
}
//! Compute the physic address of the logical address in the current module
//! In the worst case (NF512), the logical address is limited to 2^16 page addr * 512 => 33MB
//!
//! @param U32 log_addr : logical address on the module data section
//! @return status PASS or FAIL
//!
U8 nfloader_compute_physic_addr( U32 log_addr )
{
_MEM_TYPE_FAST_ Fragment _MEM_TYPE_SLOW_* ptr_frag;
_MEM_TYPE_FAST_ U32 fast_log_addr;
fast_log_addr = log_addr;
// Determinate the logical page from the logical address
#define U16_LOGICAL_PAGE LSW(s_mod_hdl.page_addr) // -> 2^16 page addr max
MSW(s_mod_hdl.page_addr) = 0;
U16_LOGICAL_PAGE = (fast_log_addr >> NF_SHIFT_PAGE_BYTE); // More efficient than division by NF_NB_BYTE_PER_PAGE
// Determinate the fragment that contains this logical page
s_mod_hdl.i_frag = 0;
ptr_frag = &s_module.frag[0];
while( U16_LOGICAL_PAGE >= ptr_frag->nb_pages )
{
U16_LOGICAL_PAGE -= ptr_frag->nb_pages;
if( MAX_NB_FRAGMENTS == ++s_mod_hdl.i_frag )
{ return FAIL; }
else
{ ptr_frag++; }
}
// Secondly, compute the page address and the offset from the logical page and the fragment
s_mod_hdl.offset = fast_log_addr % (U32) NF_NB_BYTE_PER_PAGE;
// Value of the parameter "fast_log_addr" no more useful. Thus "fast_log_addr" is used below as temporary variable.
#define VAR_TEMP_32 fast_log_addr
LSW(VAR_TEMP_32) = ptr_frag->nb_pages - U16_LOGICAL_PAGE;
// More than 256 pages to read before reaching the end of the current fragment i.e. 128KB with NF512.
// In any customer application, a single read might not exceed 128KB.
// So, s_mod_hdl.nb_pages = 0xFF if LSW(fast_log_addr) > 0x00FF.
if( LSB1(VAR_TEMP_32) != 0x00 ) { s_mod_hdl.nb_pages = 0xFF; }
else { s_mod_hdl.nb_pages = LSB0(VAR_TEMP_32); }
VAR_TEMP_32 = ptr_frag->block_addr << NF_SHIFT_BLOCK_PAGE;
if( 0 == s_mod_hdl.i_frag )
{ VAR_TEMP_32 += (U32) s_module.start_page; }
s_mod_hdl.page_addr += VAR_TEMP_32;
s_mod_hdl.device_number = ptr_frag->device_number;
s_mod_hdl.nb_frag = s_module.nb_frag; // Information just for debug information
return PASS;
}
//! Get the unaligned bytes
//! Be careful: "s_mod_hdl.offset" is only incremented in "nfloader_get_data_and_fetch_next_one()"
//!
//! @param void
//! @return U16 nb of bytes unaligned
//!
#if (defined BOARD_REFD1)
U16 nfloader_get_unaligned_bytes( void )
{
return NF_NB_BYTE_PER_PAGE-s_mod_hdl.offset;
}
#endif
//! Open the next NF page at offset 0 for reading
//!
//! @param none
//! @return none
//!
#if (defined BOARD_REFD1)
void nfloader_open_next_page( void )
{
Mcu_set_sfr_page_nfc();
if( 0 == --s_mod_hdl.nb_pages )
{
s_mod_hdl.i_frag++;
// Load device_number, page_addr and nb_pages
Nfloader_load_hdl();
}
else
{
s_mod_hdl.offset = 0;
s_mod_hdl.page_addr++;
}
nfloader_open_page_for_reading_via_register();
}
#endif
//! Get the data at the current position in NF
//! and increment this position to prepare the next read
//!
//! @param none
//! @return U8 the data byte read
//!
U8 nfloader_get_data_and_fetch_next_one( void )
{
// Test if the previous fetch is wrong because of the end of NF page
if( NF_NB_BYTE_PER_PAGE == s_mod_hdl.offset++ )
{
s_mod_hdl.offset = 0;
if( 0 == --s_mod_hdl.nb_pages )
{
s_mod_hdl.i_frag++;
// Load device_number, page_addr and nb_pages
Nfloader_load_hdl();
}
else
{ s_mod_hdl.page_addr++; }
nfloader_open_page_for_reading_via_register();
s_mod_hdl.offset = 1;
}
// Return the current data and fetch the next one
return( Nfc_rd_data_fetch_next() );
}
//! Open a NF page for reading via register
//!
//! @param none
//! @return none
//!
void nfloader_open_page_for_reading_via_register( void )
{
Nfc_action(NFC_ACT_DEV_SELECT, s_mod_hdl.device_number);
nfc_open_page_read(s_mod_hdl.page_addr, s_mod_hdl.offset);
ACC = Nfc_rd_data_fetch_next(); // Dummy read required when manual reads
}
#if (FUNC_UPDATE == ENABLE)
# if (UPDATE_DO_FW_COPY == ENABLE)
//! Check FW and FW copy zone
//! @return status
//! TRUE -> the CRC is OK
//! FALSE -> the CRC is bad. Then s_zone_page_addr[] tab is modified
//!
Bool nfloader_ckeck_fw_crc( void )
{
U8 zone;
U8 u8_i;
U8 bank_save;
U32 u32_page_addr;
// Not necessary to check CRC if there is no copy of the FW, because it will not possible to copy it if bad!
if (UNFOUND_PATTERN == s_zone_page_addr[ZONE_FIRMWARE_COPY] )
{
// Will copie ZONE_FIRMWARE (which is considered as good) in update task if not updating
return FALSE;
}
else
{
if (PASS == nfloader_init_load_module(0,ZONE_FIRMWARE))
{
if (MAPNF_FW_OPT_DFC_CRC & s_module.option)
{
// Save current Bank
bank_save = g_current_bank;
u32_page_addr = s_zone_page_addr[ZONE_FIRMWARE_COPY];
//for ZONE_FIRMWARE and ZONE_FIRMWARE_COPY
for (zone=0; zone<2;zone++)
{
for (u8_i=1; u8_i<MAX_MODULE_PER_ZONE; u8_i++) // start with the first bank (bank 1)
{
// does not run Bank_load() function if the bank does not exist!
if (PASS == nfloader_init_load_module(u8_i,ZONE_FIRMWARE))
{
g_current_bank = u8_i;
Bank_load(); // Load bank and uncipher it if necessary
if (FALSE == nfloader_check_bank_crc())
{
// The copy routine copy ZONE_FIRMWARE in new one, so swap it if ZONE_FIRMWARE is bad
// to copy the actual ZONE_FIRMWARE_COPY into ZONE_FIRMWARE
s_zone_page_addr[ZONE_FIRMWARE] = u32_page_addr;
s_zone_page_addr[ZONE_FIRMWARE_COPY] = UNFOUND_PATTERN;
// Restore previous Bank
g_current_bank = bank_save;
Bank_load();
// Will copie ZONE_FIRMWARE (which is considered as good) in update task
return FALSE;
}
}
}
if(ZONE_FIRMWARE==zone)
{
u32_page_addr = s_zone_page_addr[ZONE_FIRMWARE];
s_zone_page_addr[ZONE_FIRMWARE] = s_zone_page_addr[ZONE_FIRMWARE_COPY];}
}
}
#warning Bad CRC in FW zone not tested yet!
// Restore saved value if all is right
s_zone_page_addr[ZONE_FIRMWARE] = u32_page_addr;
// Restore previous Bank
g_current_bank = bank_save;
Bank_load();
}
}
return TRUE;
}
//! Calcul the CRC of module in RAM
//! @return status
//! TRUE -> the CRC is OK
//! FALSE -> the CRC is bad
//!
Bool nfloader_check_bank_crc( void )
{
U16 u16_add_xram = 0; // start calcul at the beginning of cdata
Mcu_set_sfr_page_dfc();
Dfc_reset();
Dfc_enable();
Dfc_crc_enable();
Dfc_crc16_init( u16_add_xram );
Dfc_set_adr_cram( u16_add_xram ); // Init interface DFC of C51 XRAM
Dfc_prog_ch_0( DFC_ID_C51_RAM ); // Init source
Dfc_prog_ch_0( DFC_ID_NULL_DEV ); // Init Dest
Dfc_prog_ch_0( 0 ); // packet = 1 Byte
Dfc_prog_ch_0( ((U16)(s_module.true_size + BANK_START_ADDRESS))>>8 ); // + BANK_START_ADDRESS cause to the crc include the startup code!
Dfc_prog_ch_0( ((U16)(s_module.true_size + BANK_START_ADDRESS))&0xFF );
while( Is_dfc_ch_0_busy() ); // Wait end of CRC compute (= end of transfer)
Dfc_crc16_read( u16_add_xram );
return (u16_add_xram == (U16) s_module.CRC);
}
# endif //#if (UPDATE_DO_FW_COPY == ENABLE)
# if (UPDATE_DO_CODEC_COPY == ENABLE)
//! Check COdec and COdec copy zone
//! @return status
//! TRUE -> the CRC is OK
//! FALSE -> the CRC is bad. Then s_zone_page_addr[] tab is modified
//!
Bool nfloader_check_codec_crc( void )
{
U8 u8_i;
U32 u32_page_addr;
if (UNFOUND_PATTERN == s_zone_page_addr[ZONE_CODEC_COPY] )
{
// Will copie ZONE_CODEC (which is considered as good) in update task if not updating
return FALSE;
}
else
{
nfup_get_zone_info(ZONE_CODEC); // Fill in g_zone_info
for(u8_i=0;u8_i<g_zone_info.u8_nb_module;u8_i++)
{
codec_load(g_zone_info.module[u8_i].u8_type);
if (!nfloader_is_codec_crc_is_good((U16)g_zone_info.module[u8_i].u32_crc))
{
s_zone_page_addr[ZONE_CODEC] = s_zone_page_addr[ZONE_CODEC_COPY];
s_zone_page_addr[ZONE_CODEC_COPY] = UNFOUND_PATTERN;
// Reset id in order to force to reload codec
s_curr_zone_id = 0xFF;
// Reset loading pointer of audio proc
Aup_enable();
Aup_disable();
return FALSE;
}
}
u32_page_addr = s_zone_page_addr[ZONE_CODEC];
s_zone_page_addr[ZONE_CODEC] = s_zone_page_addr[ZONE_CODEC_COPY];
nfup_get_zone_info(ZONE_CODEC); // Fill in g_zone_info
for(u8_i=0;u8_i<g_zone_info.u8_nb_module;u8_i++)
{
codec_load(g_zone_info.module[u8_i].u8_type);
if (!nfloader_is_codec_crc_is_good((U16)g_zone_info.module[u8_i].u32_crc))
{
s_zone_page_addr[ZONE_CODEC] = u32_page_addr;
s_zone_page_addr[ZONE_CODEC_COPY] = UNFOUND_PATTERN;
// Reset id in order to force to reload codec
s_curr_zone_id = 0xFF;
// Reset loading pointer of audio proc
Aup_enable();
Aup_disable();
return FALSE;
}
}
s_zone_page_addr[ZONE_CODEC] = u32_page_addr;
}
// Reset id in order to force to reload codec
s_curr_zone_id = 0xFF;
// Reset loading pointer of audio proc
Aup_enable();
Aup_disable();
return TRUE;
}
//! Compare DFC CRC and CRC passed by parameter
//! @return status
//! TRUE -> the CRC is OK
//! FALSE -> the CRC is bad
//!
Bool nfloader_is_codec_crc_is_good( U16 u16_crc )
{
U16 u16_add_xram;
Dfc_crc16_read( u16_add_xram );
return (u16_add_xram == u16_crc);
}
# endif // #if (UPDATE_DO_CODEC_COPY == ENABLE)
#endif //#if (FUNC_UPDATE == ENABLE)
#endif // #ifdef _nf_loader_c_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -