diff --git a/miosix/_tools/testsuite/testsuite.cpp b/miosix/_tools/testsuite/testsuite.cpp
index cbaba8afad373345a1e43276cf8fa36514964adb..baff1d61148351132b41513f3a9c82b74aa38608 100644
--- a/miosix/_tools/testsuite/testsuite.cpp
+++ b/miosix/_tools/testsuite/testsuite.cpp
@@ -797,7 +797,7 @@ static void test_2()
 tests:
 Thread::sleep()
 Thread::sleepUntil()
-getTick()
+getTime()
 also tests creation of multiple instances of the same thread
 */
 
@@ -808,12 +808,11 @@ static void t3_p1(void *argv)
     {
         if(Thread::testTerminate()) break;
         //Test that Thread::sleep sleeps the desired number of ticks
-        long long x1=getTick(); //getTick returns # passed quantums
+        long long x1=getTime(); //getTime returns passed time in ns
         Thread::sleep(SLEEP_TIME);
-        long long x2=getTick();
-        //if(llabs(((SLEEP_TIME*TICK_FREQ)/1000)-(getTick()-x))>5)
-        if (llabs((x2-x1)*preemptionPeriodNs/1000000-SLEEP_TIME)>5) //Max tolerated error is 5ms
-            fail("Thread::sleep() or getTick()");
+        long long x2=getTime();
+        if(llabs((x2-x1)/1000000-SLEEP_TIME)>5) //Max tolerated error is 5ms
+            fail("Thread::sleep() or getTime()");
     }
 }
 
@@ -882,19 +881,19 @@ static void test_3()
     if(t3_deleted==false) fail("multiple instances (4)");
     //Testing Thread::sleepUntil()
     long long tick;
-    //const int period=static_cast<int>(TICK_FREQ*0.01); //10ms
+        
     const int period=10000000;//10ms
     {
         InterruptDisableLock lock; //Making these two operations atomic.
-        tick=getTick()*preemptionPeriodNs;
+        tick=getTime();
         tick+=period;
     }
     for(int i=0;i<4;i++)
     {
-        //tick is in number of quantums passed while sleepUntil requires ms
+        //tick is in number of ns passed, wakeup time should not differ by > 1ms
         Thread::nanoSleepUntil(tick);
-        long long t2 = getTick();
-        if(tick!=t2*preemptionPeriodNs) fail("Thread::sleepUntil()");
+        long long t2 = getTime();
+        if((t2-tick)/1000000>0) fail("Thread::sleepUntil()");
         tick+=period;
     }
     pass();
@@ -934,7 +933,7 @@ static void t4_p1(void *argv)
 static void t4_p2(void *argv)
 {
     const int period=static_cast<int>(TICK_FREQ*0.03);
-    long long tick=getTick();
+    long long tick=getTime();
     for(int i=0;i<10;i++)
     {
         long long prevTick=tick;
@@ -942,7 +941,7 @@ static void t4_p2(void *argv)
         Thread::setPriority(Priority(tick)); //Change deadline
         Thread::sleepUntil(prevTick); //Make sure the task is run periodically
         delayMs(14);
-        if(getTick()>tick) fail("Deadline missed (A)\n");
+        if(getTime()>tick) fail("Deadline missed (A)\n");
     }
 }
 #endif //SCHED_TYPE_EDF
@@ -961,7 +960,7 @@ static void test_4()
     //Check IRQgetPriority
     if(p->IRQgetPriority()!=0) fail("IRQgetPriority");
     //Check that tick is not incremented and t4_v1 is not updated
-    long long tick=getTick();
+    long long tick=getTime();
     t4_v1=false;
     for(int i=0;i<4;i++)
     {
@@ -983,7 +982,7 @@ static void test_4()
 
     fastDisableInterrupts();//
     //Check that tick is not incremented and t4_v1 is not updated
-    tick=getTick();
+    tick=getTime();
     t4_v1=false;
     for(int i=0;i<4;i++)
     {
@@ -3064,11 +3063,11 @@ void t20_t2(void* arg)
     t20_v1=0;
     eq->post(t20_f1);
     eq->post(t20_f1);
-    unsigned long long t1=getTick();
+    unsigned long long t1=getTime();
     eq->post(bind(t20_f2,10,4)); //This should block
-    unsigned long long t2=getTick();
+    unsigned long long t2=getTime();
     //The other thread sleep for 50ms before calling run()
-    if((t2-t1)<static_cast<unsigned long long>(TICK_FREQ*0.04))
+    if((t2-t1)/1000000 < 40)
         fail("Not blocked");
     Thread::sleep(10);
     if(t20_v1!=14) fail("Not called");
diff --git a/miosix/kernel/kernel.cpp b/miosix/kernel/kernel.cpp
index e1b0e5dc31e05ea2bfed6daf8f4eea4c61c9d438..8b88bfc93b0381232977b3eafacd4aec1e926ece 100644
--- a/miosix/kernel/kernel.cpp
+++ b/miosix/kernel/kernel.cpp
@@ -247,7 +247,7 @@ bool isKernelRunning()
     return (kernel_running==0) && kernel_started;
 }
 
-long long getTick()
+long long getTime()
 {
     return ContextSwitchTimer::instance().getCurrentTick();
 }
diff --git a/miosix/kernel/kernel.h b/miosix/kernel/kernel.h
index da9d602f93570231eb790b7c4beec5010048bdd8..c19440be86ccbe24918caaa68f1e6a689983b6f6 100644
--- a/miosix/kernel/kernel.h
+++ b/miosix/kernel/kernel.h
@@ -404,11 +404,11 @@ void startKernel();
 bool isKernelRunning();
 
 /**
- * Returns the current kernel tick.<br>Can be called also with interrupts
- * disabled and/or kernel paused.
- * \return current kernel tick
+ * Returns the time passed in nanoseconds since the context switch started.<br>
+ * Can be called also with interrupts disabled and/or kernel paused.
+ * \return current time in nanoseconds
  */
-long long getTick();
+long long getTime();
 
 //Forwrd declaration
 struct SleepData;
@@ -527,9 +527,8 @@ public:
      * \code
      * void periodicThread()
      * {
-     *     //Run every 90 milliseconds
-     *     const int period=static_cast<int>(TICK_FREQ*0.09);
-     *     long long tick=getTick();
+     *     const int period=90; //Run every 90 milliseconds
+     *     long long tick=getTime()/1000000; //convert ns to ms
      *     for(;;)
      *     {
      *         //Do work
diff --git a/miosix/kernel/sync.cpp b/miosix/kernel/sync.cpp
index 4f076a741b3d5be416fdb704fac8c25480effbca..733e7202a884ef4151db9501689f2b9182e8b1ce 100644
--- a/miosix/kernel/sync.cpp
+++ b/miosix/kernel/sync.cpp
@@ -478,14 +478,14 @@ void Timer::start()
 {
     first=false;
     running=true;
-    start_tick=getTick();
+    start_tick=getTime();
 }
 
 void Timer::stop()
 {
     if(running==false) return;
     running=false;
-    tick_count+=getTick()-start_tick;
+    tick_count+=getTime()-start_tick;
     start_tick=0;
 }
 
diff --git a/miosix/stdlib_integration/libc_integration.cpp b/miosix/stdlib_integration/libc_integration.cpp
index 7a99231aba8526676adfe6c366e8573b8a48cea9..200042386d0853e1e46500354311edb24515bf84 100644
--- a/miosix/stdlib_integration/libc_integration.cpp
+++ b/miosix/stdlib_integration/libc_integration.cpp
@@ -904,55 +904,38 @@ int getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
 #define CLOCK_MONOTONIC 4
 #endif
 
-/// Conversion factor from ticks to nanoseconds
-/// TICK_FREQ in Miosix is either 1000 or (on older chips) 200, so a simple
-/// multiplication/division factor does not cause rounding errors
-static constexpr long tickNsFactor=1000000000/miosix::TICK_FREQ;
+static constexpr int nsPerSec = 1000000000;
 
 /**
  * Convert from timespec to the Miosix representation of time
  * \param tp input timespec, must not be nullptr and be a valid pointer
- * \return Miosix ticks
+ * \return Miosix nanoseconds
  */
 inline long long timespec2ll(const struct timespec *tp)
 {
     //NOTE: the cast is required to prevent overflow with older versions
     //of the Miosix compiler where tv_sec is int and not long long
-    return static_cast<long long>(tp->tv_sec)*miosix::TICK_FREQ
-           + tp->tv_nsec/tickNsFactor;
+    //TODO: optimize
+    return static_cast<long long>(tp->tv_sec) * nsPerSec + tp->tv_nsec;
 }
 
 /**
- * Convert from he Miosix representation of time to a timespec
- * \param tick input Miosix ticks
+ * Convert from the Miosix representation of time to a timespec
+ * \param ns input Miosix nanoseconds
  * \param tp output timespec, must not be nullptr and be a valid pointer
  */
-inline void ll2timespec(long long tick, struct timespec *tp)
+inline void ll2timespec(long long ns, struct timespec *tp)
 {
-    #ifdef __ARM_EABI__
-    // Despite there being a single intrinsic, __aeabi_ldivmod, that computes
-    // both the result of the / and % operator, GCC 9.2.0 isn't smart enough and
-    // calls the intrinsic twice. This asm implementation saves ~115 cycles
-    // by calling it once. Sadly, I had to use asm as the calling conventions
-    // of the intrinsic appear to be nonstandard.
-    // NOTE: actually a and b, by being 64 bit numbers, occupy register pairs
-    register long long a asm("r0") = tick;
-    register long long b asm("r2") = miosix::TICK_FREQ;
-    // NOTE: clobbering lr to mark function not leaf due to the bl
-    asm volatile("bl	__aeabi_ldivmod" : "+r"(a), "+r"(b) :: "lr");
-    tp->tv_sec = a;
-    tp->tv_nsec = static_cast<long>(b) * tickNsFactor;
-    #else //__ARM_EABI__
-    tp->tv_sec = tick / miosix::TICK_FREQ;
-    tp->tv_nsec = static_cast<long>(tick % miosix::TICK_FREQ) * tickNsFactor;
-    #endif //__ARM_EABI__
+    //TODO: optimize
+    tp->tv_sec = ns / nsPerSec;
+    tp->tv_nsec = static_cast<long>(ns % nsPerSec);
 }
 
 int clock_gettime(clockid_t clock_id, struct timespec *tp)
 {
     if(tp==nullptr) return -1;
     //TODO: support CLOCK_REALTIME
-    ll2timespec(miosix::getTick(),tp);
+    ll2timespec(miosix::getTime(),tp);
     return 0;
 }
 
@@ -966,7 +949,7 @@ int clock_getres(clockid_t clock_id, struct timespec *res)
 {
     if(res==nullptr) return -1;
     res->tv_sec=0;
-    res->tv_nsec=tickNsFactor;
+    res->tv_nsec=1; //TODO: get resolution from hardware timer
     return 0;
 }
 
@@ -975,9 +958,9 @@ int clock_nanosleep(clockid_t clock_id, int flags,
 {
     if(req==nullptr) return -1;
     //TODO: support CLOCK_REALTIME
-    long long timeTick=timespec2ll(req);
-    if(flags!=TIMER_ABSTIME) timeTick+=miosix::getTick();
-    miosix::Thread::sleepUntil(timeTick);
+    long long timeNs=timespec2ll(req);
+    if(flags!=TIMER_ABSTIME) timeNs+=miosix::getTime();
+    miosix::Thread::nanoSleepUntil(timeNs);
     return 0;
 }