Пример #1
0
int flashPageErase(flashpage_t page){

  /* Only write on pages in the user area */
  if (!(FLASH_IS_ADDRESS_USERSPACE(FLASH_ADDRESS_OF_PAGE(page))))
    return FLASH_RETURN_NO_PERMISSION;

  /* Unlock flash for write access */
  if(flashUnlock() == CH_FAILED)
    return FLASH_RETURN_NO_PERMISSION;

  /* Wait for any busy flags. */
  flashWaitWhileBusy();

  /* Start deletion of page. */
  FLASH->CR |= FLASH_CR_PER;
  FLASH->AR = FLASH_ADDRESS_OF_PAGE(page);
  FLASH->CR |= FLASH_CR_STRT;

  /* Wait until it's finished. */
  flashWaitWhileBusy();

  /* Page erase flag does not clear automatically. */
  FLASH->CR &= !FLASH_CR_PER;

  /* Lock flash again */
  flashLock();

  /* Check deleted page for errors */
  if(flashPageCheckErased(page) == FALSE)
    return FLASH_RETURN_BADFLASH;  /* Page is not empty despite the erase cycle! */

  /* Successfully deleted page */
  return FLASH_RETURN_SUCCESS;
}
Пример #2
0
int flashSectorErase(flashsector_t sector) {
	/* Unlock flash for write access */
	if (flashUnlock() == CH_FAILED)
		return FLASH_RETURN_NO_PERMISSION;

	/* Wait for any busy flags. */
	flashWaitWhileBusy();

	/* Setup parallelism before any program/erase */
	FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
	FLASH->CR |= FLASH_CR_PSIZE_VALUE;

	/* Start deletion of sector.
	 * SNB(3:1) is defined as:
	 * 0000 sector 0
	 * 0001 sector 1
	 * ...
	 * 1011 sector 11
	 * others not allowed */
	FLASH->CR &= ~(FLASH_CR_SNB_0 | FLASH_CR_SNB_1 | FLASH_CR_SNB_2 | FLASH_CR_SNB_3);
	if (sector & 0x1)
		FLASH->CR |= FLASH_CR_SNB_0;
	if (sector & 0x2)
		FLASH->CR |= FLASH_CR_SNB_1;
	if (sector & 0x4)
		FLASH->CR |= FLASH_CR_SNB_2;
	if (sector & 0x8)
		FLASH->CR |= FLASH_CR_SNB_3;
	FLASH->CR |= FLASH_CR_SER;
	FLASH->CR |= FLASH_CR_STRT;

	/* Wait until it's finished. */
	flashWaitWhileBusy();

	/* Sector erase flag does not clear automatically. */
	FLASH->CR &= ~FLASH_CR_SER;

	/* Lock flash again */
	flashLock()
	;

	/* Check deleted sector for errors */
	if (flashIsErased(flashSectorBegin(sector), flashSectorSize(sector)) == FALSE)
		return FLASH_RETURN_BAD_FLASH; /* Sector is not empty despite the erase cycle! */

	/* Successfully deleted sector */
	return FLASH_RETURN_SUCCESS;
}
Пример #3
0
void upgradeFwWriteSegments(uint8 *buf, uint8 len)
{
	uint8 i;

	flashUnlock();
	flashEnableWrite();

	for (i=0; i<len; i++)
	{
		*g_firmwareWritePtr = buf[i];
		while(flashWriteBusy());
		g_firmwareWritePtr++;
	}

	flashDisableWrite();
	while(flashBusy());
	flashLock();

	return ;
}
Пример #4
0
int flashPageWrite(flashpage_t page, const flashdata_t* buffer){
  volatile flashdata_t* const pageAddr =
                                     (flashdata_t*) FLASH_ADDRESS_OF_PAGE(page);

  /* Only write on pages in the user area */
  if (!(FLASH_IS_ADDRESS_USERSPACE(FLASH_ADDRESS_OF_PAGE(page))))
    return FLASH_RETURN_NO_PERMISSION;

  unsigned int pos;

  /* Unlock flash for write access */
  if(flashUnlock() == CH_FAILED)
    return FLASH_RETURN_NO_PERMISSION;

  flashWaitWhileBusy();

  for(pos = 0; pos < FLASH_PAGE_SIZE / sizeof(flashdata_t); pos++) {

    /* Enter flash programming mode. */
    FLASH->CR |= FLASH_CR_PG;

    /* Write half-word to flash. */
    pageAddr[pos] = buffer[pos];

    /* Wait for completion */
    flashWaitWhileBusy();

    /* Exit flash programming mode. */
    FLASH->CR &= ~FLASH_CR_PG;

    /* Check for flash error. */

    if (pageAddr[pos] != buffer[pos])
      return FLASH_RETURN_BADFLASH;
  }

  flashLock();

  return 0;
}
Пример #5
0
bool dfuUpdateByRequest(void) {
  /* were using the global pInformation struct from usb_lib here,
     see comment in maple_dfu.h around DFUEvent struct */
  dfuBusy = TRUE;

  u8 startState = dfuAppStatus.bState;
  dfuAppStatus.bStatus = OK;
  /* often leaner to nest if's then embed a switch/case */
  if (startState == dfuIDLE)  {
    /*  device running inside DFU mode */
    dfuBusy = TRUE; // signals the main loop to defer to the dfu write-loop

    if (pInformation->USBbRequest == DFU_DNLOAD) {

      if (pInformation->USBwLengths.w > 0) {
        userFirmwareLen = 0;
        dfuAppStatus.bState  = dfuDNLOAD_SYNC;

        if (pInformation->Current_AlternateSetting == 1) {
          userAppAddr = USER_CODE_FLASH;
          userFlash = TRUE;

          /* make sure the flash is setup properly, unlock it */
          setupFLASH();
          flashUnlock();

        } else {
          userAppAddr = USER_CODE_RAM;
          userFlash = FALSE;
        }
      } else {
        dfuAppStatus.bState  = dfuERROR;
        dfuAppStatus.bStatus = errNOTDONE;
      }
    } else if (pInformation->USBbRequest == DFU_UPLOAD) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
      dfuAppStatus.bStatus = OK;  /* are we really ok? we were just aborted */
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuIDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuDNLOAD_SYNC)         {
    /* device received block, waiting for DFU_GETSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      /* todo, add routine to wait for last block write to finish */
      if (userFlash) {
        if (code_copy_lock==WAIT) {
          code_copy_lock=BEGINNING;
          dfuAppStatus.bwPollTimeout0 = 0xFF; /* is this enough? */
          dfuAppStatus.bwPollTimeout1 = 0x01; /* is this enough? */
          dfuAppStatus.bState=dfuDNBUSY;

        } else if (code_copy_lock==BEGINNING) {
          dfuAppStatus.bState=dfuDNLOAD_SYNC;

        } else if (code_copy_lock==MIDDLE) {
          dfuAppStatus.bState=dfuDNLOAD_SYNC;

        } else if (code_copy_lock==END) {
          dfuAppStatus.bwPollTimeout0 = 0x00;
          code_copy_lock=WAIT;
          dfuAppStatus.bState=dfuDNLOAD_IDLE;
        }

      } else {
        dfuAppStatus.bState = dfuDNLOAD_IDLE;
        dfuCopyBufferToExec();
      }

    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuDNLOAD_SYNC;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuDNBUSY)              {
    /* if were actually done writing, goto sync, else stay busy */
    if (code_copy_lock == END) {
      dfuAppStatus.bwPollTimeout0 = 0x00;
      code_copy_lock=WAIT;
      dfuAppStatus.bState = dfuDNLOAD_IDLE;
    } else {
      dfuAppStatus.bState= dfuDNBUSY;
    }

  } else if (startState == dfuDNLOAD_IDLE)         {
    /* device is expecting dfu_dnload requests */
    if (pInformation->USBbRequest == DFU_DNLOAD) {
      if (pInformation->USBwLengths.w > 0) {
        dfuAppStatus.bState  = dfuDNLOAD_SYNC;
      } else {
        /* todo, support "disagreement" if device expects more data than this */
        dfuAppStatus.bState  = dfuMANIFEST_SYNC;

        /* relock the flash */
        flashLock();
      }
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuIDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuMANIFEST_SYNC)       {
    /* device has received last block, waiting DFU_GETSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
      dfuAppStatus.bStatus = OK;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuMANIFEST_SYNC;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else if (startState == dfuMANIFEST)            {
    /* device is in manifestation phase */

    /* should never receive request while in manifest! */
    dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
    dfuAppStatus.bStatus = OK;

  } else if (startState == dfuMANIFEST_WAIT_RESET) {
    /* device has programmed new firmware but needs external
       usb reset or power on reset to run the new code */

    /* consider timing out and self-resetting */
    dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

  } else if (startState == dfuUPLOAD_IDLE)         {
    /* device expecting further dfu_upload requests */

    if (pInformation->USBbRequest == DFU_UPLOAD) {
      /* todo, add routine to wait for last block write to finish */
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    } else if (pInformation->USBbRequest == DFU_ABORT) {
      dfuAppStatus.bState  = dfuIDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuUPLOAD_IDLE;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }


  } else if (startState == dfuERROR)               {
    /* status is in error, awaiting DFU_CLRSTATUS request */

    if (pInformation->USBbRequest == DFU_GETSTATUS) {
      /* todo, add routine to wait for last block write to finish */
      dfuAppStatus.bState  = dfuERROR;
    } else if (pInformation->USBbRequest == DFU_GETSTATE) {
      dfuAppStatus.bState  = dfuERROR;
    } else if (pInformation->USBbRequest == DFU_CLRSTATUS) {
      /* todo handle any cleanup we need here */
      dfuAppStatus.bState  = dfuIDLE;
      dfuAppStatus.bStatus = OK;
    } else {
      dfuAppStatus.bState  = dfuERROR;
      dfuAppStatus.bStatus = errSTALLEDPKT;
    }

  } else {
    /* some kind of error... */
    dfuAppStatus.bState  = dfuERROR;
    dfuAppStatus.bStatus = errSTALLEDPKT;
  }

  if (dfuAppStatus.bStatus == OK) {
    return TRUE;
  } else {
    return FALSE;
  }
}
Пример #6
0
bool dfuUpdateByRequest(void) {
    /* were using the global pInformation struct from usb_lib here,
       see comment in maple_dfu.h around DFUEvent struct */
    dfuBusy = TRUE;

    u8 startState = dfuAppStatus.bState;
    dfuAppStatus.bStatus = OK;
    /* often leaner to nest if's then embed a switch/case */
    if (startState == dfuIDLE)  {
        /*  device running inside DFU mode */
        dfuBusy = TRUE; // signals the main loop to defer to the dfu write-loop

        if (pInformation->USBbRequest == DFU_DNLOAD) {

            if (pInformation->USBwLengths.w > 0) {
                userFirmwareLen = 0;
                dfuAppStatus.bState  = dfuDNLOAD_SYNC;

                if (pInformation->Current_AlternateSetting == 1) {
                    userAppAddr = USER_CODE_FLASH;
                    userFlash = TRUE;

                    /* make sure the flash is setup properly, unlock it */
                    setupFLASH();
                    flashUnlock();

                } else {
                    userAppAddr = USER_CODE_RAM;
                    userFlash = FALSE;
                }
            } else {
                dfuAppStatus.bState  = dfuERROR;
                dfuAppStatus.bStatus = errNOTDONE;
            }
        } else if (pInformation->USBbRequest == DFU_UPLOAD) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
            /* record length of first block for calculating target
               address from wValue in consecutive blocks */
            uploadBlockLen = pInformation->USBwLengths.w;
            thisBlockLen = uploadBlockLen; /* for this first block as well */
            /* calculate where the data should be copied from */
            userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
            if (pInformation->Current_AlternateSetting == 1) {
                userAppAddr = USER_CODE_FLASH;
                userAppEnd = FLASH_END;
            } else {
                userAppAddr = USER_CODE_RAM;
                userAppEnd = RAM_END;
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
            dfuAppStatus.bStatus = OK;  /* are we really ok? we were just aborted */
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuIDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuDNLOAD_SYNC)         {
        /* device received block, waiting for DFU_GETSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            /* todo, add routine to wait for last block write to finish */
            if (userFlash) {
                if (code_copy_lock == WAIT) {
                    code_copy_lock = BEGINNING;
                    dfuAppStatus.bwPollTimeout0 = 0x20; /* 32 ms */
                    dfuAppStatus.bwPollTimeout1 = 0x00;
                    dfuAppStatus.bState = dfuDNBUSY;

                } else if (code_copy_lock == BEGINNING) {
                    dfuAppStatus.bState = dfuDNLOAD_SYNC;

                } else if (code_copy_lock == MIDDLE) {
                    dfuAppStatus.bState = dfuDNLOAD_SYNC;

                } else if (code_copy_lock == END) {
                    dfuAppStatus.bwPollTimeout0 = 0x00;
                    code_copy_lock = WAIT;
                    dfuAppStatus.bState = dfuDNLOAD_IDLE;
                }

            } else {
                dfuAppStatus.bState = dfuDNLOAD_IDLE;
                dfuCopyBufferToExec();
            }

        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuDNLOAD_SYNC;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuDNBUSY)              {
        /* if were actually done writing, goto sync, else stay busy */
        if (code_copy_lock == END) {
            dfuAppStatus.bwPollTimeout0 = 0x00;
            code_copy_lock = WAIT;
            dfuAppStatus.bState = dfuDNLOAD_IDLE;
        } else {
            dfuAppStatus.bState = dfuDNBUSY;
        }

    } else if (startState == dfuDNLOAD_IDLE)         {
        /* device is expecting dfu_dnload requests */
        if (pInformation->USBbRequest == DFU_DNLOAD) {
            if (pInformation->USBwLengths.w > 0) {
                dfuAppStatus.bState  = dfuDNLOAD_SYNC;
            } else {
                /* todo, support "disagreement" if device expects more data than this */
                dfuAppStatus.bState  = dfuMANIFEST_SYNC;

                /* relock the flash */
                flashLock();
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuIDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuMANIFEST_SYNC)       {
        /* device has received last block, waiting DFU_GETSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
            dfuAppStatus.bStatus = OK;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuMANIFEST_SYNC;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else if (startState == dfuMANIFEST)            {
        /* device is in manifestation phase */

        /* should never receive request while in manifest! */
        dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;
        dfuAppStatus.bStatus = OK;

    } else if (startState == dfuMANIFEST_WAIT_RESET) {
        /* device has programmed new firmware but needs external
           usb reset or power on reset to run the new code */

        /* consider timing out and self-resetting */
        dfuAppStatus.bState  = dfuMANIFEST_WAIT_RESET;

    } else if (startState == dfuUPLOAD_IDLE)         {
        /* device expecting further dfu_upload requests */

        if (pInformation->USBbRequest == DFU_UPLOAD) {
            if (pInformation->USBwLengths.w > 0) {
                /* check that this is not the last possible block */
                userFirmwareLen = uploadBlockLen * pInformation->USBwValue;
                if (userAppAddr + userFirmwareLen + uploadBlockLen <= userAppEnd) {
                    thisBlockLen = uploadBlockLen;
                    dfuAppStatus.bState  = dfuUPLOAD_IDLE;
                } else {
                    /* if above comparison was just equal, thisBlockLen becomes zero
                    next time when USBWValue has been increased by one */
                    thisBlockLen = userAppEnd - userAppAddr - userFirmwareLen;
                    /* check for overflow due to USBwValue out of range */
                    if (thisBlockLen >= pInformation->USBwLengths.w) {
                        thisBlockLen = 0;
                    }
                    dfuAppStatus.bState  = dfuIDLE;
                }
            } else {
                dfuAppStatus.bState  = dfuERROR;
                dfuAppStatus.bStatus = errNOTDONE;
            }
        } else if (pInformation->USBbRequest == DFU_ABORT) {
            dfuAppStatus.bState  = dfuIDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATUS) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuUPLOAD_IDLE;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }


    } else if (startState == dfuERROR)               {
        /* status is in error, awaiting DFU_CLRSTATUS request */

        if (pInformation->USBbRequest == DFU_GETSTATUS) {
            /* todo, add routine to wait for last block write to finish */
            dfuAppStatus.bState  = dfuERROR;
        } else if (pInformation->USBbRequest == DFU_GETSTATE) {
            dfuAppStatus.bState  = dfuERROR;
        } else if (pInformation->USBbRequest == DFU_CLRSTATUS) {
            /* todo handle any cleanup we need here */
            dfuAppStatus.bState  = dfuIDLE;
            dfuAppStatus.bStatus = OK;
        } else {
            dfuAppStatus.bState  = dfuERROR;
            dfuAppStatus.bStatus = errSTALLEDPKT;
        }

    } else {
        /* some kind of error... */
        dfuAppStatus.bState  = dfuERROR;
        dfuAppStatus.bStatus = errSTALLEDPKT;
    }

    if (dfuAppStatus.bStatus == OK) {
        return TRUE;
    } else {
        return FALSE;
    }
}
Пример #7
0
int flashWrite(flashaddr_t address, const char* buffer, size_t size) {
	/* Unlock flash for write access */
	if (flashUnlock() == CH_FAILED)
		return FLASH_RETURN_NO_PERMISSION;

	/* Wait for any busy flags */
	flashWaitWhileBusy();

	/* Setup parallelism before any program/erase */
	FLASH->CR &= ~FLASH_CR_PSIZE_MASK;
	FLASH->CR |= FLASH_CR_PSIZE_VALUE;

	/* Check if the flash address is correctly aligned */
	size_t alignOffset = address % sizeof(flashdata_t);
//	print("flash alignOffset=%d\r\n", alignOffset);
	if (alignOffset != 0) {
		/* Not aligned, thus we have to read the data in flash already present
		 * and update them with buffer's data */

		/* Align the flash address correctly */
		flashaddr_t alignedFlashAddress = address - alignOffset;

		/* Read already present data */
		flashdata_t tmp = *(volatile flashdata_t*) alignedFlashAddress;

		/* Compute how much bytes one must update in the data read */
		size_t chunkSize = sizeof(flashdata_t) - alignOffset;
		if (chunkSize > size)
			chunkSize = size; // this happens when both address and address + size are not aligned

		/* Update the read data with buffer's data */
		memcpy((char*) &tmp + alignOffset, buffer, chunkSize);

		/* Write the new data in flash */
		flashWriteData(alignedFlashAddress, tmp);

		/* Advance */
		address += chunkSize;
		buffer += chunkSize;
		size -= chunkSize;
	}

	/* Now, address is correctly aligned. One can copy data directly from
	 * buffer's data to flash memory until the size of the data remaining to be
	 * copied requires special treatment. */
	while (size >= sizeof(flashdata_t)) {
//		print("flash write size=%d\r\n", size);
		flashWriteData(address, *(const flashdata_t*) buffer);
		address += sizeof(flashdata_t);
		buffer += sizeof(flashdata_t);
		size -= sizeof(flashdata_t);
	}

	/* Now, address is correctly aligned, but the remaining data are to
	 * small to fill a entier flashdata_t. Thus, one must read data already
	 * in flash and update them with buffer's data before writing an entire
	 * flashdata_t to flash memory. */
	if (size > 0) {
		flashdata_t tmp = *(volatile flashdata_t*) address;
		memcpy(&tmp, buffer, size);
		flashWriteData(address, tmp);
	}

	/* Lock flash again */
	flashLock()
	;

	return FLASH_RETURN_SUCCESS;
}