OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_cpu.c] - Diff between revs 35 and 39

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 35 Rev 39
Line 215... Line 215...
  return cycles.uint64;
  return cycles.uint64;
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Simple delay function (not very precise) using busy wait.
 * Simple delay function using busy wait.
 
 *
 
 * @warning This function requires the cycle CSR(s). Hence, the Zicsr extension is mandatory.
 *
 *
 * @param[in] time_ms Time in ms to wait.
 * @param[in] time_ms Time in ms to wait.
 **************************************************************************/
 **************************************************************************/
void neorv32_cpu_delay_ms(uint32_t time_ms) {
void neorv32_cpu_delay_ms(uint32_t time_ms) {
 
 
  uint32_t clock_speed = SYSINFO_CLK >> 10; // fake divide by 1000
  uint64_t time_resume = neorv32_cpu_get_cycle();
  clock_speed = clock_speed >> 5; // divide by loop execution time (~30 cycles)
 
  uint32_t cnt = clock_speed * time_ms;
  uint32_t clock = SYSINFO_CLK; // clock ticks per second
 
  clock = clock / 1000; // clock ticks per ms
  // one iteration = ~30 cycles
 
  while (cnt) {
  uint64_t wait_cycles = ((uint64_t)clock) * ((uint64_t)time_ms);
    asm volatile("nop");
  time_resume += wait_cycles;
    asm volatile("nop");
 
    asm volatile("nop");
  while(1) {
    asm volatile("nop");
    if (neorv32_cpu_get_cycle() >= time_resume) {
    cnt--;
      break;
 
    }
  }
  }
}
}
 
 
 
 
/**********************************************************************//**
/**********************************************************************//**
 * Switch from privilege mode MACHINE to privilege mode USER.
 * Switch from privilege mode MACHINE to privilege mode USER.
 *
 *
 * @note This function requires the U extension to be implemented.
 * @warning This function requires the U extension to be implemented.
 * @note Maybe you should do a fence.i after this.
 
 **************************************************************************/
 **************************************************************************/
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
void __attribute__((naked)) neorv32_cpu_goto_user_mode(void) {
 
 
  // make sure to use NO registers in here! -> naked
  // make sure to use NO registers in here! -> naked
 
 
  asm volatile ("csrw mepc, ra           \n\t" // move return address to mepc so we can return using "mret". also, we can use ra as general purpose register in here
  asm volatile ("csrw mepc, ra           \n\t" // move return address to mepc so we can return using "mret". also, we can now use ra as general purpose register in here
                "li ra, %[input_imm]     \n\t" // bit mask to clear the two MPP bits
                "li ra, %[input_imm]     \n\t" // bit mask to clear the two MPP bits
                "csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode
                "csrrc zero, mstatus, ra \n\t" // clear MPP bits -> MPP=u-mode
                "mret                    \n\t" // return and switch to user mode
                "mret                    \n\t" // return and switch to user mode
                :  : [input_imm] "i" ((1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L)));
                :  : [input_imm] "i" ((1<<CPU_MSTATUS_MPP_H) | (1<<CPU_MSTATUS_MPP_L)));
}
}
 
 
 No newline at end of file
 No newline at end of file
 
 
 
/**********************************************************************//**
 
 * Atomic compare-and-swap operation (for implemeneting semaphores and mutexes).
 
 *
 
 * @warning This function requires the A (atomic) CPU extension.
 
 *
 
 * @param[in] addr Address of memory location.
 
 * @param[in] expected Expected value (for comparison).
 
 * @param[in] desired Desired value (new value).
 
 * @return Returns 0 on success, 1 on failure.
 
 **************************************************************************/
 
int __attribute__ ((noinline)) neorv32_cpu_atomic_cas(uint32_t addr, uint32_t expected, uint32_t desired) {
 
#ifdef __riscv_atomic
 
 
 
  register uint32_t addr_reg = addr;
 
  register uint32_t des_reg = desired;
 
  register uint32_t tmp_reg;
 
 
 
  // load original value + reservation (lock)
 
  asm volatile ("lr.w %[result], (%[input])" : [result] "=r" (tmp_reg) : [input] "r" (addr_reg));
 
 
 
  if (tmp_reg != expected) {
 
    asm volatile ("lw x0, 0(%[input])" : : [input] "r" (addr_reg)); // clear reservation lock
 
    return 1;
 
  }
 
 
 
  // store-conditional
 
  asm volatile ("sc.w %[result], %[input_i], (%[input_j])" : [result] "=r" (tmp_reg) : [input_i] "r" (des_reg), [input_j] "r" (addr_reg));
 
 
 
  if (tmp_reg) {
 
    return 1;
 
  }
 
 
 
  return 0;
 
#else
 
  return 1; // A extension not implemented -Y always fail
 
#endif
 
}
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.