bool program_rbf()

in src/de10nano/de10nano_mgr.h [379:548]


  bool program_rbf(const char *rbf) {
    monitor mon;
    int rbf_fd;
    uint32_t count = 0;
    printf("DE10-Nano-Mgr: Programming FPGA from image %s\n", rbf);

    try {
      mon.init("Open RBF file");
      rbf_fd = open(rbf, (O_RDONLY | O_SYNC));
      mon.done(rbf_fd >= 0);

      // 1. Set the cdratio and cfgwdth bits of the ctrl register in the
      // FPGA manager registers (fpgamgrregs) to match the characteristics
      // of the configuration image. Tese settings are dependent on the
      // MSEL pins input.
      // 2. Set the nce bit of the ctrl register to 0 to enable HPS
      // configuration.
      // 3. Set the en bit of the ctrl register to 1 to give the FPGA
      // manager control of the configuration input signals.
      // 4. Set the nconfigpull bit of the ctrl register to 1 to pull
      // down the nCONFIG pin and put the FPGA portion of the device
      // into the reset phase.
      mon.init("Enable FPGA configuration");
      stat.read();
      if (stat.msel_is_invalid()) {
        printf("DE10-Nano-Mgr: msel %x is not a valid HPS configuration\n", stat.msel);
      } else {
        ctrl.read();
        ctrl.cdratio = msel_to_cdratio(stat.msel);
        ctrl.cfgwdth = msel_to_cfgwdth(stat.msel);
        ctrl.nce = 0;
        ctrl.en = 1;
        ctrl.nconfigpull = 1;
        ctrl.write();
      }
      mon.done(!stat.msel_is_invalid());

      // 5. Poll the mode bit of the stat register and wait until
      // the FPGA enters the reset phase.
      mon.init("Wait for FPGA to reset");
      do {
        stat.read();
      } while (mon(stat.mode != stat::FPGA_RESET_PHASE));
      mon.done();
      stat.print();

      // 6. Set the nconfigpull bit of the ctrl register to 0 to
      // release the FPGA from reset.
      mon.init("Release FPGA from reset");
      ctrl.nconfigpull = 0;
      ctrl.write();
      mon.done();

      // 7. Read the mode bit of the stat register and wait until
      // the FPGA enters the configuration phase.
      mon.init("Wait for configuration phase");
      do {
        stat.read();
      } while (mon(stat.mode != stat::FPGA_CONFIG_PHASE));
      mon.done();
      stat.print();

      // 8. Clear the interrupt bit of nSTATUS (ns) in the gpio interrupt
      // register (fpgamgrregs.mon.gpio_porta_eoi).
      mon.init("Clear nSTATUS interrupt bit");
      gpio_porta_eoi.clear();
      gpio_porta_eoi.ns = 1;
      gpio_porta_eoi.write();
      mon.done();

      // 9. Set the axicfgen bit of the ctrl register to 1 to enable
      // sending configuration data to the FPGA.
      mon.init("Enable configuration on AXI");
      ctrl.axicfgen = 1;
      ctrl.write();
      mon.done();

      // 10. Write the configuration image to the configuration data register
      // (data) in the FPGA manager module configuration data registers
      // (fpgamgrdata). You can also choose to use a DMA controller to
      // transfer the configuration image from a peripheral device to the
      // FPGA manager.
      ssize_t bytes;
      mon.init("Write configuration Image");
      do {
        data.value = 0;
        bytes = read(rbf_fd, &data.value, sizeof(data.value));
        if (bytes > 0) {
          if (!(count % (1<<16))) {
            printf("\rDE10-Nano-Mgr: %-32s : %u B", mon.msg, count);
            fflush(stdout);
          }
          data.write();
          count += bytes;
        }
      } while (bytes == 4);
      mon.done(count > 0);
      printf("DE10-Nano-Mgr: %-32s : written %u B\n", mon.msg, count);
      close(rbf_fd);

      // 11. Use the fpgamgrregs.mon.gpio_ext_porta registers to monitor
      // the CONF_DONE (cd) and nSTATUS (ns) bits.
      mon.init("Wait for CONF_DONE");
      do {
        gpio_ext_porta.read();
      } while (mon(gpio_ext_porta.cd != 1 && gpio_ext_porta.ns != 1));
      mon.done();
      stat.print();

      // 12. Set the axicfgen bit of the ctrl register to 0 to disable
      // configuration data on AXI slave.
      mon.init("Disable configuration on AXI");
      ctrl.axicfgen = 0;
      ctrl.write();
      mon.done();

      // 13. Clear any previous DONE status by writing a 1 to the dcntdone
      // bit of the DCLK status register (dclkstat) to clear the completed
      // status flag.
      mon.init("Clear DCLK DONE status");
      dclkstat.dcntdone = 1;
      dclkstat.write();
      mon.done();

      // 14. Send the DCLKs required by the FPGA to enter the
      // initialization phase.
      mon.init("Send DCLK for init phase");
      dclkcnt.cnt = 4;
      dclkcnt.write();
      mon.done();

      // 15. Poll the dcntdone bit of the DCLK status register (dclkstat)
      // until it changes to 1, which indicates that all the DCLKs have
      // been sent.
      mon.init("Wait for DCLK");
      do {
        dclkstat.read();
      } while (mon(dclkstat.dcntdone != 1));
      mon.done();

      // 16. Write a 1 to the dcntdone bit of the DCLK status register to
      // clear the completed status flag.
      mon.init("Clear DCLK status flag");
      dclkstat.dcntdone = 1;
      dclkstat.write();
      mon.done();

      // 17. Read the mode bit of the stat register to wait for the FPGA
      // to enter user mode.
      mon.init("Wait for FPGA user mode");
      do {
        stat.read();
      } while (mon(stat.mode != stat::FPGA_USER_MODE));
      mon.done();

      // 18. Set the en bit of the ctrl register to 0 to allow the
      // external pins to drive the configuration input signals.
      mon.init("Release control");
      ctrl.en = 0;
      ctrl.write();
      mon.done();
    }
    catch(int i) {
      close(rbf_fd);
      printf("DE10-Nano-Mgr: %-32s : written %u B\n", mon.msg, count);
      print();
    }

    return mon.status();
  }