/**
  * @brief  Reads a block of data from the OneNAND memory using synchronous mode.
  * @param  pBuffer: pointer to the buffer that receives the data read from the 
  *         OneNAND memory.
  * @param  ReadAddr: OneNAND memory internal address to read from.
  * @param  NumHalfwordToRead: number of half-words to read.
  * @retval None
  */
void OneNAND_SynchronousRead(uint16_t* pBuffer, OneNAND_ADDRESS Address, uint32_t NumHalfwordToRead)
{
  uint16_t index = 0;
  uint16_t status = 0;

  /* Set the asynchronous read mode */
  OneNAND_WRITE(BANK1_ONENAND1_ADDR + OneNAND_REG_SYSTEMCONFIGURATION, 0xB4C0);
  

  /* Load data from the read address to the DATA RAM 1 setor 1 */
  *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_STARTADDRESS1) = Address.Block; /* NAND Flash block address*/
  *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_STARTADDRESINT8_T) = (uint16_t)(Address.Page << 2);
  *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_STARTBUFFER) = OneNAND_DATA_RAM_1_0_REG;
  *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_INTERRUPT) = 0x0000;
  *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_COMMAND) = OneNAND_CMD_LOAD; /* Command */

  /* Wait till the command is completed */
  status = *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_INTERRUPT);

  while((status & 0x8000) != 0x8000)
  {
    status = *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_INTERRUPT);
  }

  /* Read Controller status */
  status = *(__IO uint16_t *)(BANK1_ONENAND1_ADDR + OneNAND_REG_CONTROLSTATUS);

  /* Read data */
  for(; NumHalfwordToRead != 0x00; NumHalfwordToRead--) /* While there is data to read */
  {
   *pBuffer++ = *(__IO uint16_t *)((BANK1_ONENAND1_ADDR + OneNAND_DATA_RAM_1_0_ADD + 2*index));
    index++;
  }
}
/**
  * @brief  Reads OneNAND memory's Manufacturer and Device Code.
  * @param  OneNAND_ID: pointer to a OneNAND_IDTypeDef structure which will hold
  *         the Manufacturer and Device Code.  
  * @retval None
  */
void OneNAND_ReadID(OneNAND_IDTypeDef* OneNAND_ID)
{
  /* Read ID command */
  OneNAND_WRITE(Bank1_NOR1_ADDR + OneNAND_REG_COMMAND, OneNAND_CMD_READ_ID);

  /* Read ID data */
  OneNAND_ID->Manufacturer_ID = *(__IO uint16_t *)(Bank1_NOR1_ADDR + OneNAND_REG_MANUFACTERID);
  OneNAND_ID->Device_ID = *(__IO uint16_t *)(Bank1_NOR1_ADDR + OneNAND_REG_DEVICEID);
}
/**
  * @brief  Reads a block of data from the OneNAND memory.
  * @param  pBuffer : pointer to the buffer that receives the data read from the 
  *         OneNAND memory.
  * @param  ReadAddr : OneNAND memory internal address to read from.
  * @param  NumHalfwordToRead : number of half-words to read.
  * @retval None
  */
void OneNAND_SynchronousRead(uint16_t* pBuffer, uint32_t ReadAddr, uint32_t NumHalfwordToRead)
{
  uint16_t datatmp = 0x0;
  datatmp = *(__IO uint16_t *)(Bank1_NOR1_ADDR + OneNAND_REG_SYSTEMCONFIGURATION); 
  /* Set the asynchronous read mode */
  OneNAND_WRITE(Bank1_NOR1_ADDR + OneNAND_REG_SYSTEMCONFIGURATION, (datatmp|0x8000));

  /* Read data */
  for(; NumHalfwordToRead != 0x00; NumHalfwordToRead--) /* while there is data to read */
  {
    /* Read a Halfword from the memory */
    *pBuffer++ = *(__IO uint16_t *)((Bank1_NOR1_ADDR + ReadAddr));
    ReadAddr = ReadAddr + 2; 
  }  
}
/**
  * @brief  Resets the OneNAND memory.
  * @param  None
  * @retval None
  */
void OneNAND_Reset(void)
{
  OneNAND_WRITE(ONENAND_BOOTPARTITION_ADDR, OneNAND_CMD_RESET);
}