We rapidly use DMA controllers, channels 3 and 4. Sometimes transfer in HalFlashWrite is stopped and we can detect that HAL_DMA_CHECK_IRQ and then we repeat procedure.
But sometimes HAL_DMA_CHECK_IRQ return 1 despite the facts that last 4 byte are not written. So we change this function:
void HalFlashWrite(uint16 addr, uint8 *buf, uint16 cnt)
{
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
halDMADesc_t *ch = HAL_NV_DMA_GET_DESC();
uint8 numTry = 0;
uint8 i = 0;
for ( numTry = 0; numTry < HAL_FLASH_WRITE_TRY; numTry++ )
{
// Clear DMA trigger event
HAL_DMA_SET_SOURCE(ch, &dummySrc);
HAL_DMA_SET_DEST(ch, &dummyDst);
HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
HAL_DMA_SET_LEN(ch, (1));
HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_BLOCK);
HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_NONE);
HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_0);
HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
// The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
HAL_DMA_ARM_CH(HAL_NV_DMA_CH);
for ( i = 0; i < 15; i++)
{
asm("NOP");
}
HAL_DMA_MAN_TRIGGER( HAL_NV_DMA_CH );
while ( !HAL_DMA_CHECK_IRQ( HAL_NV_DMA_CH ));
// Setting DMA transfer
HAL_DMA_SET_SOURCE(ch, buf);
HAL_DMA_SET_DEST(ch, &FWDATA);
HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
HAL_DMA_SET_LEN(ch, (cnt * HAL_FLASH_WORD_SIZE));
HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE);
HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH);
HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1);
HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
// The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
FADDRL = (uint8)addr;
FADDRH = (uint8)(addr >> 8);
HAL_DMA_ARM_CH(HAL_NV_DMA_CH);
while( !(HalAdcCheckVdd(VDD_MIN_NV)) );
#ifdef WATCHDOG
WatchDogClear();
#endif
while (FCTL & 0x80); // Wait until flash controler is busy
FCTL |= 0x02; // Trigger the DMA writes.
while (FCTL & 0x80); // Wait until flash controler is busy
// Check flash controller abort status bit. This bit is set when a write operation or page erase
// is aborted. An operation is aborted when the page accessed is locked. The abort bit is cleared
// when a write or page erase is started.
if( FCTL & 0x20 )
{
// Attempt to erase locked page - false state, restart device.
SystemReset();
}
//if (!HAL_DMA_CH_ARMED( HAL_NV_DMA_CH ))
//{
if( HAL_DMA_CHECK_IRQ( HAL_NV_DMA_CH ))
{
uint8 tmp[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
for ( numTry = 0; numTry < HAL_FLASH_WRITE_TRY; numTry++ )
{
HalFlashRead( ((uint32)addr * HAL_FLASH_WORD_SIZE) / HAL_FLASH_PAGE_SIZE, (((uint32)addr * HAL_FLASH_WORD_SIZE) % HAL_FLASH_PAGE_SIZE) + (cnt - 1) * HAL_FLASH_WORD_SIZE , tmp, HAL_FLASH_WORD_SIZE);
uint8 j = 0;
for (j = 0; j < HAL_FLASH_WORD_SIZE; j++ )
{
if( *(buf + (cnt - 1) * HAL_FLASH_WORD_SIZE + j ) != tmp[j] ) break;
}
if ( j == HAL_FLASH_WORD_SIZE )
{
break;
}
else
{
// Clear DMA trigger event
HAL_DMA_SET_SOURCE(ch, &dummySrc);
HAL_DMA_SET_DEST(ch, &dummyDst);
HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
HAL_DMA_SET_LEN(ch, (1));
HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_BLOCK);
HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_NONE);
HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_0);
HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
// The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
HAL_DMA_ARM_CH(HAL_NV_DMA_CH);
for ( i = 0; i < 15; i++)
{
asm("NOP");
}
HAL_DMA_MAN_TRIGGER( HAL_NV_DMA_CH );
while ( !HAL_DMA_CHECK_IRQ( HAL_NV_DMA_CH ));
// Setting DMA transfer
HAL_DMA_SET_SOURCE(ch, ( buf + (cnt - 1) * HAL_FLASH_WORD_SIZE ) );
HAL_DMA_SET_DEST(ch, &FWDATA);
HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN);
HAL_DMA_SET_LEN(ch, (1 * HAL_FLASH_WORD_SIZE));
HAL_DMA_SET_WORD_SIZE(ch, HAL_DMA_WORDSIZE_BYTE);
HAL_DMA_SET_TRIG_MODE(ch, HAL_DMA_TMODE_SINGLE);
HAL_DMA_SET_TRIG_SRC(ch, HAL_DMA_TRIG_FLASH);
HAL_DMA_SET_SRC_INC(ch, HAL_DMA_SRCINC_1);
HAL_DMA_SET_DST_INC(ch, HAL_DMA_DSTINC_0);
// The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ(ch, HAL_DMA_IRQMASK_DISABLE);
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS);
HAL_DMA_SET_PRIORITY(ch, HAL_DMA_PRI_HIGH);
HAL_DMA_CLEAR_IRQ(HAL_NV_DMA_CH);
FADDRL = (uint8)( addr + cnt -1 );
FADDRH = (uint8)(( addr + cnt -1 ) >> 8);
HAL_DMA_ARM_CH(HAL_NV_DMA_CH);
while( !(HalAdcCheckVdd(VDD_MIN_NV)) );
#ifdef WATCHDOG
WatchDogClear();
#endif
while (FCTL & 0x80); // Wait until flash controler is busy
FCTL |= 0x02; // Trigger the DMA writes.
while (FCTL & 0x80); // Wait until flash controler is busy
// Check flash controller abort status bit. This bit is set when a write operation or page erase
// is aborted. An operation is aborted when the page accessed is locked. The abort bit is cleared
// when a write or page erase is started.
if( FCTL & 0x20 )
{
// Attempt to erase locked page - false state, restart device.
SystemReset();
}
}
}
break;
}
//}
}
#endif
}