/* EEPROM service functions in order to manage the EEPROM according to the SRD document */ #define __EEPROM_PROTOTYPE__ /* files include */ /* include standard header */ #include /* memset */ #include "NODE1.h" #include "Eprm.h" #include "pmload.h" #include "MM_MISC.h" /* Static variables */ static unsigned int saj_FCSTable[FCS_TABLE_SIZE]; static EepromHeaderType sw_EepromHeader; static unsigned int SAve_prio; static unsigned long EEPROM_page_Buffer[DM_EEPROMPAGESIZE]; /* to avoid malloc */ // the following are initialized to PACS-specific values; HIFI will have to call // function init_eprm_write_interr_prio() to set these variables to its own // correct values; // variables interrupt_a, _b, _c, hold the numbers identifying the interrupts that // must be disabled during writing; HIgh_prio holds the value that must be given to // the priority of this task during writing static int interrupt_a = 5; static int interrupt_b = 6; static int interrupt_c = 7; static unsigned int HIgh_prio = 4; /* Extern function prototype */ extern void DPU_wait (unsigned int); /*------------- static function prototype ---------------*/ /* conpute the Frame Check sequence on the segments */ static unsigned int DmEepromComputeFCS ( MemoryCellType *pd_Buffer, unsigned int j_StartWords, unsigned int j_NumberOfWords ); void ComputeFCSTable( void ); static unsigned int ComputeFCS ( unsigned char d_Byte, unsigned int j_PartialFcs ); /*-------------- function declaration -------------*/ /******************************************************************** * * ComputeFCSTable - descrizione breve * * function description (TBW) * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ void ComputeFCSTable ( void ) { /* create FCS table */ unsigned long BitStream, PolyGenerator, StreamTmp, CyclicCode; unsigned int i; /* standard polynomial for FCS computation X^16 + X^12 + X^5 + 1 */ PolyGenerator = ((0x00011021) << 7); for( BitStream=0; BitStream < 256; BitStream++) { CyclicCode = (BitStream << 16); for( i=0; i<8;i++) { StreamTmp = ((0x00800000 >> i) & (CyclicCode)); if (StreamTmp != 0) CyclicCode ^= (PolyGenerator >> i); } /* memorize the CyclicCode */ saj_FCSTable[BitStream] = CyclicCode; } }/* end procedure */ /******************************************************************** * * ComputeFCS - descrizione breve * * function description (TBW) * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned int ComputeFCS ( unsigned char d_Byte, unsigned int j_PartialFcs ) { /* local var */ unsigned int j_TmpFcs; /*compute FCS on byte 2 */ j_TmpFcs = d_Byte; j_TmpFcs ^= (j_PartialFcs >> 8); j_PartialFcs = (FCS_FILTER & ((j_PartialFcs << 8) ^ saj_FCSTable[j_TmpFcs])); return j_PartialFcs; }/* end procedure */ /******************************************************************** * * DmEepromComputeFCS - Computes the Frame Check sequence for the * EEPROM data memory segment * * function description * the function computes the Frame check sequence over a * EEPROM segment. The FCS is computed by setting 0 in the * two bytes including the EEPROM FCS. * * ARGUMENTS * Input Parameters * *pd_Buffer buffer containig the words for * the FCS computation * j_StartWords starting address in EEPROM memory * j_NumberOfWords Numbers of words for FCS computation * * Output Parameters * N/A * Global Variables * N/A * * RETURNS: computed Frame Check sequence * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned int DmEepromComputeFCS ( MemoryCellType *pd_DmBuffer, unsigned int j_StartWords, unsigned int j_NumberOfWords ) { /*local var */ unsigned int j_Fcs, j_Index; MemoryCellType sw_Buffer; for (j_Index = j_StartWords, j_Fcs = FCS_PRESET_VALUE; j_Index < j_NumberOfWords; j_Index++, pd_DmBuffer++) { *((unsigned long *)&sw_Buffer) = *((unsigned long *)pd_DmBuffer); *((unsigned long *)&sw_Buffer) = *((unsigned long *)pd_DmBuffer); /* compute FCS on byte 4 */ j_Fcs = ComputeFCS(sw_Buffer.d_Byte4,j_Fcs); /* compute FCS on Byte 3*/ j_Fcs = ComputeFCS(sw_Buffer.d_Byte3,j_Fcs); if ((j_Index - j_StartWords) == WORD_WITH_DMEEPROM_FCS) { /*compute FCS on byte 2 */ j_Fcs = ComputeFCS(0x00,j_Fcs); /*compute FCS on Byte 1*/ j_Fcs = ComputeFCS(0x00,j_Fcs); } else { /*compute FCS on byte 2 */ j_Fcs = ComputeFCS(sw_Buffer.d_Byte2,j_Fcs); /*compute FCS on Byte 1*/ j_Fcs = ComputeFCS(sw_Buffer.d_Byte1,j_Fcs); } } return j_Fcs; } /******************************************************************** * * EepromWriteSegment - It writes an EEPROM segment including header * * * Description * It writes an EEPROM segment including header. * WARNING: the segment area has to be cleared before * writing the segment * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromWriteSegment(EepromHeaderType *pw_EepromHeader, unsigned long *pm_buffer, unsigned int j_NumberOfSegment) { /* local var */ unsigned char d_Byte; unsigned int j_Index, j_Block, j_IndexCrc, j_Fcs; // EepromHeaderType *pw_DmEepromHeader; unsigned long *pm_EepromHeaderTmp, *pm_BufferTmp; unsigned long *pm_PageAddress, *pm_PageAdrTmp; /* extract the EEPROM address */ pm_PageAddress = (unsigned long *)(DM_EEPROM_START_ADDRESS + j_NumberOfSegment * DM_EEPROM_PAGE_SIZE); pm_PageAdrTmp = pm_PageAddress; /* check that the area is free */ /* for (j_Index=0; j_Index < DM_EEPROM_PAGE_SIZE; j_Index++) { if ((*pm_PageAdrTmp) != DM_EEPROM_FREE_VALUE) if ((*pm_PageAdrTmp) != DM_EEPROM_FREE_VALUE) return DM_EEPROM_ERROR_SEGMENT_NOT_FREE; pm_PageAdrTmp++; } */ /* write the data in 256 block word */ pm_BufferTmp = pm_buffer; pm_PageAdrTmp = pm_PageAddress; pm_EepromHeaderTmp = (unsigned long *)pw_EepromHeader; /* reset crc inside the segment */ pw_EepromHeader->FcsWord.j_FcsEepromDmSeg = 0; for (j_Block = 0; j_Block < NUM_OF_EEPROM_BLOCKS; j_Block++) { KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); DataProtection((unsigned long)pm_PageAddress); for (j_Index = 0; j_Index< EEPROM_BLOCK_SIZE; j_Index++) { if ((j_Index < DM_HEADER_SIZE) && (j_Block == 0)) { if (j_Index != WORD_WITH_DMEEPROM_FCS) { /*write header */ *(pm_PageAdrTmp) = *(pm_EepromHeaderTmp); } pm_PageAdrTmp++; pm_EepromHeaderTmp++; } else { *(pm_PageAdrTmp) = *(pm_buffer); pm_PageAdrTmp++; pm_buffer++; } } KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId,SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); } pm_buffer = pm_BufferTmp; pm_PageAdrTmp = pm_PageAddress; pm_EepromHeaderTmp = (unsigned long *)pw_EepromHeader; /* check the Eeprom */ j_Fcs = 0xFFFF; for (j_Index = 0; j_Index< DM_EEPROM_PAGE_SIZE; j_Index++) { if (j_Index < DM_HEADER_SIZE) { if (j_Index != WORD_WITH_DMEEPROM_FCS) { if ((*pm_PageAdrTmp) != (*pm_EepromHeaderTmp)) if ((*pm_PageAdrTmp) != (*pm_EepromHeaderTmp)) return DM_EEPROM_ERROR_WRITE_FAILED; } for (j_IndexCrc=4; j_IndexCrc > 0; j_IndexCrc--) { d_Byte = (unsigned char)((*pm_EepromHeaderTmp) >> ((j_IndexCrc -1) * 8)) & (0x000000FF); j_Fcs = ComputeFCS(d_Byte,j_Fcs); } pm_PageAdrTmp++; pm_EepromHeaderTmp++; } else { if ((*pm_PageAdrTmp) != (*pm_buffer)) if ((*pm_PageAdrTmp) != (*pm_buffer)) return DM_EEPROM_ERROR_WRITE_FAILED; for (j_IndexCrc=4; j_IndexCrc > 0; j_IndexCrc--) { d_Byte = (unsigned char)((*pm_buffer) >> ((j_IndexCrc-1) * 8)) & (0x000000FF); j_Fcs = ComputeFCS(d_Byte,j_Fcs); } pm_PageAdrTmp++; pm_buffer++; } } KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); pm_EepromHeaderTmp = (unsigned long *)pw_EepromHeader; pw_EepromHeader->FcsWord.j_FcsEepromDmSeg = j_Fcs; /* write word 5 in the EEPROM */ DataProtection((unsigned long)pm_PageAddress); *(pm_PageAddress + 5) = *(pm_EepromHeaderTmp + 5); KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); return EEPROM_WRITE_SUCCESS; } /******************************************************************** * * WriteEepromHeader - the function set the Eeprom Header * * Description * This is a service function for the Eeprom header writing * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ EepromHeaderType *WriteEepromHeader ( unsigned int j_IndexCurrSeg, unsigned int j_TotNumofSeg, unsigned char d_AswStartAddrFlags, unsigned char d_BootOpt, unsigned char d_LoadDmToPmOpt, unsigned char d_Reserved, unsigned long m_AswStartAddr, unsigned long m_PmSegStartAddr, unsigned long m_PmSegLength, unsigned long m_NextEepromSeg, unsigned int j_j_FcsEepromDmSeg, unsigned int j_FcsPmSeg, unsigned int j_FcsTot ) { sw_EepromHeader.SegWord.j_IndexCurrSeg = j_IndexCurrSeg; sw_EepromHeader.SegWord.j_TotNumOfSeg = j_TotNumofSeg; sw_EepromHeader.OptWord.d_AswStartAddrFlags = d_AswStartAddrFlags; sw_EepromHeader.OptWord.d_BootOpt = d_BootOpt; sw_EepromHeader.OptWord.d_LoadDmToPmOpt = d_LoadDmToPmOpt; sw_EepromHeader.OptWord.d_Reserved = d_Reserved; sw_EepromHeader.AswStartAddr= m_AswStartAddr; sw_EepromHeader.PmWord.m_PmSegStartAddr = m_PmSegStartAddr; sw_EepromHeader.PmWord.m_PmSegLength = m_PmSegLength; sw_EepromHeader.NextEepromSeg = m_NextEepromSeg; sw_EepromHeader.FcsWord.j_FcsEepromDmSeg = j_j_FcsEepromDmSeg; sw_EepromHeader.FcsWord.j_FcsPmSeg = j_FcsPmSeg; sw_EepromHeader.FcsProg.j_FcsTot = j_FcsTot; sw_EepromHeader.FcsProg.j_Reserved = 0; return &sw_EepromHeader; } /******************************************************************** * * EepromWriteCell - the function set the Eeprom Header * * Description * This is a service function for the Eeprom header writing * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromWriteCell(unsigned long m_Address, unsigned long m_Data) { /* local var */ unsigned long m_BasePageAddress; EepromHeaderType *pw_DmEepromHeader; unsigned int fcs_result; /* check if the address is included in the EEPROM space */ if ((m_Address < DM_EEPROM_START_ADDRESS) && (m_Address > DM_EEPROM_END_ADDRESS)) return DM_EEPROM_ERROR_BAD_ADDRESS; /* base page extraction */ m_BasePageAddress = m_Address & 0x8FFFFC00; /* write data in EEPROM */ KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); DataProtection(m_Address); *(unsigned long *)m_Address = m_Data; KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); if (*(unsigned long *)m_Address != m_Data) return DM_EEPROM_WRITE_FAILED; /* assign header in DM */ pw_DmEepromHeader = (EepromHeaderType *)m_BasePageAddress; fcs_result = DmEepromComputeFCS((MemoryCellType *)m_BasePageAddress,0, DM_EEPROM_PAGE_SIZE); /* compute the check sum on the segment */ KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); DataProtection(m_Address); pw_DmEepromHeader->FcsWord.j_FcsEepromDmSeg= fcs_result; KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); return DM_EEPROM_WRITE_SUCCESS; }/*end procedure */ /******************************************************************** * * EepromReadCell - the function set the Eeprom Header * * Description * This is a service function for the Eeprom header writing * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromReadCell(unsigned long m_Address, unsigned long *pm_Data) { /* check if the address is included in the EEPROM space */ if ((m_Address < DM_EEPROM_START_ADDRESS) || (m_Address > DM_EEPROM_END_ADDRESS)) return DM_EEPROM_ERROR_BAD_ADDRESS; *pm_Data = *((unsigned long *)m_Address); return DM_EEPROM_READ_SUCCESS; } /******************************************************************** * * EepromClearCell - the function set the Eeprom Header * * Description * This is a service function for the Eeprom header writing * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromClearCell(unsigned long m_Address) { return EepromWriteCell(m_Address,0); } /******************************************************************** * * EepromDeleteSegment - the function set the Eeprom Header * * Description * This is a service function for the Eeprom header writing * * ARGUMENTS * Input Parameters * N/A * Output Parameters * N/A * Global Variables * description * description * * RETURNS: N/A * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromDeleteSegment(unsigned int j_NumberOfSegment) { /* local var */ unsigned int j_Index, j_Block; unsigned long m_Address, m_AddressTest; /* check that the segment is in EEPROM */ if (j_NumberOfSegment >= DM_EEPROM_NUMBER_OF_PAGES) return DM_EEPROM_ERROR_SEGMENT_OVERFLOW; /* compute the address */ m_AddressTest = m_Address = j_NumberOfSegment * DM_EEPROM_PAGE_SIZE + DM_EEPROM_START_ADDRESS; for (j_Block = 0; j_Block < NUM_OF_EEPROM_BLOCKS; j_Block++) { KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); DataProtection(m_Address); for (j_Index = 0; j_Index< EEPROM_BLOCK_SIZE; j_Index++) { *((unsigned long *)m_Address) = 0x00000000; m_Address++; } KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); } /* verifing the memory reset */ for (j_Index = 0; j_Index< DM_EEPROM_PAGE_SIZE; j_Index++,m_AddressTest++) { if ((*(unsigned long *)m_AddressTest) != 0x00000000) return DM_EEPROM_ERROR_NOT_CLEARED; } return DM_EEPROM_DELETION_SUCCESS; } /******************************************************************** * * EepromDisableProtect - disable the Eeprom protection * * Description * The function disables the Eeprom protection and it * allow the Eeprom memory access * * ARGUMENTS * Input Parameters * d_Bank specify the Eeprom bank to disable * Output Parameters * N/A * Global Variables * N/A * * RETURNS: * * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromDisableProtBank(unsigned char d_Bank) { /* var local */ unsigned long m_EepromOffset; unsigned long m_EepromAddress; /* set the eeprom protection */ if (d_Bank == DM_EEPROM_BANK_1) m_EepromOffset = 0; else { if (d_Bank == DM_EEPROM_BANK_2) m_EepromOffset = 0x20000; else return DM_EEPROM_ERROR_BANK_OVERFLOW; } m_EepromAddress = DM_EEPROM_BASE_ADDRESS + m_EepromOffset; KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); /* sequence to disable the Eeprom data protection */ *(unsigned long *)(m_EepromAddress + 0x5555) = 0xAAAAAAAA; *(unsigned long *)(m_EepromAddress + 0x2AAA) = 0x55555555; *(unsigned long *)(m_EepromAddress + 0x5555) = 0x80808080; *(unsigned long *)(m_EepromAddress + 0x5555) = 0xAAAAAAAA; *(unsigned long *)(m_EepromAddress + 0x2AAA) = 0x55555555; *(unsigned long *)(m_EepromAddress + 0x5555) = 0x20202020; /* wait the EEPROM copy */ KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); DPU_wait(EEPROM_WAIT_TIME); return DM_EEPROM_ERROR_SUCCESS; } /******************************************************************** * * EepromEnableProtect - Enable the Eeprom protection * * Description * The function Enable the Eeprom protection. It allows to * protect the Eeprom access. For enabling the protection * the function has to receive a memory address cell for * writing a dummy value after the protection sequence. * WARNING: IS RECOMMENDED TO SELECT AN UNUSED DUMMY MEMORY CELL * * * ARGUMENTS * Input Parameters * d_Bank Specify the memory bank * Output Parameters * N/A * Global Variables * N/A * * RETURNS: * error condition * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char EepromEnableProtBank(unsigned char d_Bank, unsigned int j_DummyOffsetCell ) { /* set the eeprom protection */ /* var local */ unsigned long m_EepromOffset; unsigned long m_EepromAddress; unsigned long m_DataRead; unsigned char d_Error; /* set the eeprom protection */ if (d_Bank == DM_EEPROM_BANK_1) m_EepromOffset = 0; else { if (d_Bank == DM_EEPROM_BANK_2) m_EepromOffset = 0x20000; else return DM_EEPROM_ERROR_BANK_OVERFLOW; } m_EepromAddress = DM_EEPROM_BASE_ADDRESS + m_EepromOffset; if (EepromReadCell((j_DummyOffsetCell + m_EepromAddress), &m_DataRead) != 0) return d_Error; KS_TaskSetPrio(KS_TaskId, HIgh_prio); KS_ISRDisable(interrupt_a); KS_ISRDisable(interrupt_b); KS_ISRDisable(interrupt_c); /* sequence to disable the Eeprom data protection */ *(unsigned long *)(m_EepromAddress + 0x5555) = 0xAAAAAAAA; *(unsigned long *)(m_EepromAddress + 0x2AAA) = 0x55555555; *(unsigned long *)(m_EepromAddress + 0x5555) = 0xA0A0A0A0; *(unsigned long *)(m_EepromAddress + j_DummyOffsetCell) = m_DataRead; KS_ISREnable(interrupt_a); KS_ISREnable(interrupt_b); KS_ISREnable(interrupt_c); KS_TaskSetPrio(KS_TaskId, SAve_prio); /* wait the EEPROM copy */ DPU_wait(EEPROM_WAIT_TIME); return DM_EEPROM_ERROR_SUCCESS; } /******************************************************************** * * CopyProgramInEEPROM - the function copies the Program stored in * program memory in EEPROM * * Description * the functions peerforms the copy of the program stored in Pm * inside the EEPROM starting from specified page address. The functions * will include the interrupt vector automatically. The user has to * specify the application program start address. * * ARGUMENTS * Input Parameters * m_PmStartAddress Program memory start address (usually 0x4000) * m_PmEndAddress Program memory end address * m_FlagPartition Partition Flag 1 * pj_PageToAvoid Pointer to a table with the page to be skipped * j_FcsPmTotal Fcs of the whole Program uploaded in program memory * * Output Parameters * N/A * Global Variables * * RETURNS: * error condition * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned char CopyProgramInEEPROM( unsigned long m_PmStartAddress, unsigned long m_PmEndAddress, unsigned long m_FlagPartition, unsigned int *pj_PageToAvoid, unsigned int j_FcsPmTotal) { /* var local */ unsigned long *pm_Buffer; unsigned long *pm_BufferTmp; unsigned long m_PmAddress, m_PmAddressTmp,m_NextEepromSeg; EepromHeaderType *pw_DmEepromHeader; unsigned int j_EepromInitPage, j_EepromNumOfPages, j_EepromLastPage, j_EepromCurrentPage, j_ComputePmPage, j_IndexCurrentPage = 0, j_IndexNextPage, j_IndexPageAdr, limit, test_var, stop = 0; unsigned int dividend, divisor, currentPagetoavoid, j_FcsPmSeg; SAve_prio = KS_TaskPrio; // current priority of this task pm_Buffer = EEPROM_page_Buffer; /* compute the EEPROM number of segment end-start+1 is the number of PM words 3/2 is the factor to take into account different word size PM/DM EEPROM_PAGE_SIZE - HEADER_SIZE is the number of available words */ dividend = (unsigned int)(m_PmEndAddress - m_PmStartAddress + 1)*3; divisor = (unsigned int)(DM_EEPROMPAGESIZE)*2; j_EepromNumOfPages = IFSI_DIV(dividend, divisor); if (IFSI_MOD(dividend, divisor) != 0) j_EepromNumOfPages++; pj_PageToAvoid++; /* First page is conventionally 0 */ if (m_FlagPartition == 1) { j_EepromInitPage = 0; j_EepromLastPage = j_EepromNumOfPages; currentPagetoavoid = *pj_PageToAvoid - 1; j_IndexPageAdr = 0; /* points to page to write; if no page is corrupted j_IndexPageAdr is equal to j_EepromCurrentPage */ } else { j_EepromInitPage = DM_EEPROM_LAST_PAGE; j_EepromLastPage = j_EepromInitPage - j_EepromNumOfPages; currentPagetoavoid = DM_EEPROM_LAST_PAGE - (*pj_PageToAvoid - 1); j_IndexPageAdr = DM_EEPROM_LAST_PAGE; /* points to page to write; if no page is corrupted j_IndexPageAdr is equal to j_EepromCurrentPage */ } /* increase one page for the Interrupt vector */ j_EepromNumOfPages++; /* For partition 1 there is the following cycle for (j_EepromCurrentPage = j_EepromInitPage; j_EepromCurrentPage <= j_EepromLastPage; j_EepromCurrentPage++) while for second partition the code is for (j_EepromCurrentPage = j_EepromInitPage; j_EepromCurrentPage >= j_EepromLastPage; j_EepromCurrentPage--) it is not possible to use one single statement for the two cases, so we use a do cycle. Here the cycle is initialized */ j_EepromCurrentPage = j_EepromInitPage; do { memset(EEPROM_page_Buffer,0,DM_EEPROMPAGESIZE); j_IndexNextPage = 1; /* initial offset to next good page */ j_IndexCurrentPage++; /* The first page is different from the others. In case page i is corrupted, it is avoided at all, but if the first page is corrupted we need to write at least the header, otherwise the partition is fully lost. Of course we have to hope that the first 15 (7+8 see below) words of the page are still writable */ if (j_EepromCurrentPage == j_EepromInitPage) { m_PmAddressTmp = 0; m_PmAddress = 0; if (currentPagetoavoid == j_EepromInitPage) /* first page is corrupted */ { j_EepromNumOfPages++; /* We need to count */ do { pj_PageToAvoid++; if (m_FlagPartition == 1) { currentPagetoavoid = *pj_PageToAvoid - 1; test_var = j_IndexPageAdr + j_IndexNextPage; } else { currentPagetoavoid = DM_EEPROM_LAST_PAGE - (*pj_PageToAvoid - 1); test_var = j_IndexPageAdr - j_IndexNextPage; } if (test_var != currentPagetoavoid) break; j_IndexNextPage++; } while (1); if (m_FlagPartition == 1) j_IndexPageAdr += j_IndexNextPage; else j_IndexPageAdr -= j_IndexNextPage; m_NextEepromSeg = j_IndexPageAdr * DM_EEPROM_PAGE_SIZE + DM_EEPROM_START_ADDRESS; j_FcsPmSeg = PackPMWordsinEepromPage(m_PmEndAddress, &m_PmAddress, 0xC); /* 8*1.5 */ pw_DmEepromHeader = WriteEepromHeader(1,j_EepromNumOfPages, ON,1,0,0,0, 0, 8, m_NextEepromSeg, 0, j_FcsPmSeg, j_FcsPmTotal); if (EepromWriteSegment(pw_DmEepromHeader,pm_Buffer,j_EepromInitPage) != 0) { return DM_EEPROM_ERROR_COPY_FAILED; } limit = 0x174; /* (PM_INTERRUPT_VECTORS_TABLE-8)*1.5 */ j_ComputePmPage = PM_INTERRUPT_VECTORS_TABLE-8; m_PmAddressTmp = 8; j_IndexNextPage = 1; /* reset initial offset */ j_IndexCurrentPage++; } else /* First page is not corrupted */ { limit = 0x180; /* PM_INTERRUPT_VECTORS_TABLE*1.5 */ j_ComputePmPage = PM_INTERRUPT_VECTORS_TABLE; } if (m_FlagPartition == 1) test_var = j_IndexPageAdr + j_IndexNextPage; else test_var = j_IndexPageAdr - j_IndexNextPage; while (test_var == currentPagetoavoid) { j_IndexNextPage++; pj_PageToAvoid++; if (m_FlagPartition == 1) { currentPagetoavoid = *pj_PageToAvoid - 1; test_var = j_IndexPageAdr + j_IndexNextPage; } else { currentPagetoavoid = DM_EEPROM_LAST_PAGE - (*pj_PageToAvoid - 1); test_var = j_IndexPageAdr - j_IndexNextPage; } } m_NextEepromSeg = test_var * DM_EEPROM_PAGE_SIZE + DM_EEPROM_START_ADDRESS; pm_BufferTmp = pm_Buffer; /* copy the pm data in the buffer and computes the checksum*/ j_FcsPmSeg = PackPMWordsinEepromPage(m_PmEndAddress, &m_PmAddress, limit); m_PmAddress = m_PmStartAddress; } else /* not first page */ { /* save start address in PM */ m_PmAddressTmp = m_PmAddress; if (m_FlagPartition == 1) test_var = j_IndexPageAdr + j_IndexNextPage; else test_var = j_IndexPageAdr - j_IndexNextPage; while (test_var == currentPagetoavoid) { j_IndexNextPage++; pj_PageToAvoid++; if (m_FlagPartition == 1) { currentPagetoavoid = *pj_PageToAvoid - 1; test_var = j_IndexPageAdr + j_IndexNextPage; } else { currentPagetoavoid = DM_EEPROM_LAST_PAGE - (*pj_PageToAvoid - 1); test_var = j_IndexPageAdr - j_IndexNextPage; } } /* compute next Eeprom */ if (j_EepromLastPage == j_EepromCurrentPage) m_NextEepromSeg = DM_EEPROM_END_SEGMENTS; else m_NextEepromSeg = test_var * DM_EEPROM_PAGE_SIZE + DM_EEPROM_START_ADDRESS; pm_BufferTmp = pm_Buffer; /* copy the pm data in the buffer and computes the checksum*/ j_FcsPmSeg = PackPMWordsinEepromPage(m_PmEndAddress, &m_PmAddress, DM_EEPROMPAGESIZE); j_ComputePmPage = m_PmAddress - m_PmAddressTmp; } /* End of if on first page */ limit = j_IndexPageAdr; /* Here limit is used as storing variable */ if (m_FlagPartition == 1) { j_IndexPageAdr += j_IndexNextPage; j_EepromCurrentPage++; if (j_EepromCurrentPage > j_EepromLastPage) stop = 1; } else { j_IndexPageAdr -= j_IndexNextPage; j_EepromCurrentPage--; if (j_EepromCurrentPage < j_EepromLastPage) stop = 1; } /* write the header */ pw_DmEepromHeader= WriteEepromHeader(j_IndexCurrentPage, j_EepromNumOfPages,ON,1,0,0, 0, m_PmAddressTmp, j_ComputePmPage, m_NextEepromSeg, 0, j_FcsPmSeg, j_FcsPmTotal); /* memorize the segment in EEPROM */ if (EepromWriteSegment(pw_DmEepromHeader,pm_Buffer,limit) != 0) return DM_EEPROM_ERROR_COPY_FAILED; } while (stop == 0);/* End of cycle on j_EepromCurrentPage */ return DM_EEPROM_ERROR_COPY_SUCCESS; } /******************************************************************** * * ComputeFcsOverall - the function computes the Fcs on the programm * memory overall * * Description * The function computes the FCS on the uploaded Program * in Program memory * * * ARGUMENTS * Input Parameters * j_InitPage Init Page of Program (Program Mem page size is 1024byte) * j_LastPage Last Page of the Program * * Output Parameters * N/A * Global Variables * description * description * * RETURNS: * Overall FCS computed * * SEE ALSO: * * INTERNAL * This section will not appear in the generated manual entry. * */ unsigned int ComputeFcsOverall( unsigned long m_PmStartAddress, unsigned long m_PmEndAddress) { /* var local */ unsigned long m_PmAddress; unsigned long m_MsWord, m_LsWord; unsigned int j_Index, j_IndexByte, j_FcsPmTotal; unsigned char ad_Byte[6]; unsigned int j_EepromInitPage, j_EepromNumOfPages, j_EepromLastPage, j_EepromCurrentPage, j_EepromPageSize; /* one at the end for rounding */ j_EepromNumOfPages = ((m_PmEndAddress - m_PmStartAddress)*6)/ (4*(DM_EEPROM_PAGE_SIZE - DM_HEADER_SIZE)); if ( ((m_PmEndAddress - m_PmStartAddress)*6) > (4*(DM_EEPROM_PAGE_SIZE - DM_HEADER_SIZE)*j_EepromNumOfPages)) j_EepromNumOfPages++; /* increase one page for the Interrupt vector */ j_EepromNumOfPages++; j_EepromInitPage = 0; j_EepromLastPage = j_EepromNumOfPages - 1 + j_EepromInitPage; j_EepromCurrentPage = j_EepromInitPage; j_EepromPageSize = (DM_EEPROM_PAGE_SIZE - DM_HEADER_SIZE); /* set the FCS value */ j_FcsPmTotal = FCS_PRESET_VALUE; for (j_EepromCurrentPage = j_EepromInitPage; j_EepromCurrentPage <= j_EepromLastPage; j_EepromCurrentPage++) { if (j_EepromCurrentPage == j_EepromInitPage) m_PmAddress = 0; j_Index = 0; while (j_Index < j_EepromPageSize) { m_MsWord = PmRead32Bits(m_PmAddress); m_LsWord = PmRead16Bits(m_PmAddress); /* store the byte in the array */ for (j_IndexByte = 2; j_IndexByte < 6; j_IndexByte++) ad_Byte[j_IndexByte] = (m_MsWord >> (j_IndexByte -2)*8) & 0x000000FF; for (j_IndexByte = 0; j_IndexByte < 2; j_IndexByte++) ad_Byte[j_IndexByte] = (m_LsWord >> j_IndexByte*8) & 0x000000FF; /* compute fcs*/ for (j_IndexByte = 0; j_IndexByte < 6; j_IndexByte++) j_FcsPmTotal = 0x0000FFFF & ComputeFCS(ad_Byte[5 - j_IndexByte],j_FcsPmTotal); //if (m_PmAddress%2 == 0) if (is_even(m_PmAddress)) j_Index++; else j_Index += 2; /* increments the address */ m_PmAddress++; if ((j_EepromCurrentPage == j_EepromInitPage) && (m_PmAddress >= PM_INTERRUPT_VECTORS_TABLE)) { j_Index = j_EepromPageSize; /* compute the PM address */ m_PmAddress = m_PmStartAddress; } else { if (m_PmAddress > m_PmEndAddress) { j_Index = j_EepromPageSize; } } }/* end while */ }/* end for */ return j_FcsPmTotal; } //-------------- init_eprm_write_interr_prio ----------------------------------- // sets the value of some top level variables relating interrupts to be // enabled/disabled and the value to which the priority of the task must be set // during writing void init_eprm_write_interr_prio (int int_a, int int_b, int int_c, int high_prio) { interrupt_a = int_a; interrupt_b = int_b; interrupt_c = int_c; HIgh_prio = high_prio; return; } unsigned int PackPMWordsinEepromPage( unsigned long m_PmEndAddress, unsigned long * p_PmAddress, unsigned int limit) { /* var local */ unsigned long m_MsWord, m_LsWord; unsigned int j_IndexByte; unsigned char ad_Byte[6]; unsigned int j_Index = 0; unsigned int j_FcsPmSeg = FCS_PRESET_VALUE; while (j_Index < limit) { m_MsWord = PmRead32Bits(*p_PmAddress); m_LsWord = PmRead16Bits(*p_PmAddress); /* store the byte in the array */ for (j_IndexByte = 2; j_IndexByte < 6; j_IndexByte++) ad_Byte[j_IndexByte] = (m_MsWord >> (j_IndexByte -2)*8) & 0x000000FF; for (j_IndexByte = 0; j_IndexByte < 2; j_IndexByte++) ad_Byte[j_IndexByte] = (m_LsWord >> j_IndexByte*8) & 0x000000FF; /* compute fcs*/ for (j_IndexByte = 0; j_IndexByte < 6; j_IndexByte++) j_FcsPmSeg = ComputeFCS(ad_Byte[5 - j_IndexByte],j_FcsPmSeg); if (is_even(*p_PmAddress)) { EEPROM_page_Buffer[j_Index++] = m_MsWord; EEPROM_page_Buffer[j_Index] = (m_LsWord & 0x0000FFFF); } else { EEPROM_page_Buffer[j_Index++] |= (m_LsWord << 16); EEPROM_page_Buffer[j_Index++] = m_MsWord; } /* increments the address */ (*p_PmAddress)++; /* Here the very last page is artificially closed */ if (*p_PmAddress > m_PmEndAddress) j_Index = DM_EEPROMPAGESIZE; } /* End of while on j_Index */ return j_FcsPmSeg; }