/*!
  \file
  \brief ターゲット側の書き込みプログラム

  \author Satofumi KAMIMURA

  $Id: flash.c 1106 2009-07-01 22:50:20Z satofumi $
*/

#include "flash.h"


struct st_flm {
  struct { unsigned char BYTE; } FLMCR1;
};
#define LOOP(X) for(i = X; i > 0; i--) /* Wait Loop */


int flash_data(unsigned long addr, const char *data)
{
  volatile char *address = (char *)addr;
  volatile char *flmcr = (char *)FLMCR1_ADDR;
  volatile int i = 0;                /* use LOOP() */
  char rewrite[32];
  char verify;
  int n, m, j;

  if (addr > 0x0001ffff) {
    flmcr += 1;
  }

  FLM.FLMCR1.BYTE |= 0x40;        /* FLMR1 SWE=1 */
  LOOP(WAIT_10u);

  for (j = 0; j < 32; ++j) {
    rewrite[j] = data[j];
  }

  n = 1;
  do {
    for (j = 0; j < 32; ++j) {        /* data byte write */
      *(address + j) = rewrite[j];
    }

    WDT_RSTCSR_WORD = WDT_RESET;
    WDT_TCSR_WORD = WDT_573u;        /* set WDT */

    *flmcr = 0x50;                /* set FLMCR1(2) PSU1(2)=1 */
    LOOP(WAIT_50u);

    *flmcr = 0x51;                /* set FLMCR1(2) P1(2)=1 */
    LOOP(WAIT_200u);

    *flmcr = 0x50;                /* set FLMCR1(2) P1(2)=0 */
    LOOP(WAIT_10u);

    *flmcr = 0x40;                /* set FLMCR1(2) PSU1(2)=0 */
    LOOP(WAIT_10u);

    WDT_TCSR_WORD = WDT_STOP;        /* stop WDT */
    *flmcr = 0x44;                /* set FLMCR1(2) PV1(2)=1 */
    LOOP(WAIT_4u);

    m = 0;
    for (j = 0; j < 32; j++) {
      *(address + j) = 0xff;
      rewrite[j] = 0xff;
      LOOP(WAIT_2u);
      verify = *(address + j);
      if (data[j] != verify) {
        m = 1;
      }
      rewrite[j] = ~(data[j] ^ verify) | data[j];
    }

    *flmcr = 0x40;                /* set FLMCR1(2) PV1(2)=0 */
    LOOP(WAIT_4u);

  } while ((m != 0) && (n++ < WRITE_TIMES));

  FLM.FLMCR1.BYTE = 0x00;        /* FLMR1 SWE=0 */
  if (m != 0) {
    return -1;
  }
  return 0;
}
