timer: atomic reads
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 13 May 2013 15:18:30 +0000 (17:18 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 13 May 2013 15:18:30 +0000 (17:18 +0200)
milkymist/timer/__init__.py
software/bios/boot.c
software/bios/main.c
software/include/base/timer.h [deleted file]
software/libbase/Makefile
software/libbase/board.c
software/libbase/timer.c [deleted file]
software/libnet/microudp.c
software/videomixer/time.c

index 32bfb55adbf9292df938b67f5e8dfeb79a2f72de..81c36f1cc9f65b1420b544795570d8ac7c7d8f01 100644 (file)
@@ -5,9 +5,11 @@ from migen.bank.eventmanager import *
 
 class Timer(Module, AutoCSR):
        def __init__(self, width=32):
-               self._en = CSRStorage()
-               self._value = CSRStorage(width, write_from_dev=True)
+               self._load = CSRStorage(width)
                self._reload = CSRStorage(width)
+               self._en = CSRStorage()
+               self._update_value = CSR()
+               self._value = CSRStatus(width)
                
                self.submodules.ev = EventManager()
                self.ev.zero = EventSourceProcess()
@@ -15,12 +17,18 @@ class Timer(Module, AutoCSR):
 
                ###
 
-               self.comb += [
-                       If(self._value.storage == 0,
-                               self._value.dat_w.eq(self._reload.storage)
+               value = Signal(width)
+               self.sync += [
+                       If(self._en.storage,
+                               If(value == 0,
+                                       # set reload to 0 to disable reloading
+                                       value.eq(self._reload.storage)
+                               ).Else(
+                                       value.eq(value - 1)
+                               )
                        ).Else(
-                               self._value.dat_w.eq(self._value.storage - 1)
+                               value.eq(self._load.storage)
                        ),
-                       self._value.we.eq(self._en.storage),
-                       self.ev.zero.trigger.eq(self._value.storage != 0)
+                       If(self._update_value.re, self._value.status.eq(value))
                ]
+               self.comb += self.ev.zero.trigger.eq(value != 0)
index 93d2f27950091dcc15a6874da2f96ab4e38c1e50..3cffcef8c404fe609488720e84ed5a59849ebdd1 100644 (file)
@@ -7,9 +7,9 @@
 #include <sfl.h>
 #include <string.h>
 #include <irq.h>
-#include <timer.h>
 
 #include <hw/mem.h>
+#include <hw/csr.h>
 
 #include <net/microudp.h>
 #include <net/tftp.h>
@@ -33,12 +33,13 @@ static int check_ack(void)
        int recognized;
        static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK;
 
-       timer_enable(0);
-       timer_set_reload(0);
-       timer_set_counter(get_system_frequency()/4);
-       timer_enable(1);
+       timer0_en_write(0);
+       timer0_reload_write(0);
+       timer0_load_write(identifier_frequency_read()/4);
+       timer0_en_write(1);
+       timer0_update_value_write(1);
        recognized = 0;
-       while(timer_get()) {
+       while(timer0_value_read()) {
                if(uart_read_nonblock()) {
                        char c;
                        c = uart_read();
@@ -53,6 +54,7 @@ static int check_ack(void)
                                        recognized = 0;
                        }
                }
+               timer0_update_value_write(1);
        }
        return 0;
 }
index 146882b37e75c71fbaf647c621fc2c4c5be46e6f..ffdb9e3cd77ad01fe74a6af9c9218079d93f1757 100644 (file)
@@ -8,8 +8,8 @@
 #include <irq.h>
 #include <version.h>
 #include <crc.h>
-#include <timer.h>
 
+#include <hw/csr.h>
 #include <hw/mem.h>
 #include <net/microudp.h>
 
@@ -459,11 +459,12 @@ static int test_user_abort(void)
        printf("Q/ESC: abort boot\n");
        printf("F7:    boot from serial\n");
        printf("F8:    boot from network\n");
-       timer_enable(0);
-       timer_set_reload(0);
-       timer_set_counter(get_system_frequency()*2);
-       timer_enable(1);
-       while(timer_get()) {
+       timer0_en_write(0);
+       timer0_reload_write(0);
+       timer0_load_write(identifier_frequency_read()*2);
+       timer0_en_write(1);
+       timer0_update_value_write(1);
+       while(timer0_value_read()) {
                if(readchar_nonblock()) {
                        c = readchar();
                        if((c == 'Q')||(c == '\e')) {
@@ -479,6 +480,7 @@ static int test_user_abort(void)
                                return 0;
                        }
                }
+               timer0_update_value_write(1);
        }
        return 1;
 }
diff --git a/software/include/base/timer.h b/software/include/base/timer.h
deleted file mode 100644 (file)
index e33e26f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __TIMER_H
-#define __TIMER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-unsigned int get_system_frequency(void);
-void timer_enable(int en);
-unsigned int timer_get(void);
-void timer_set_counter(unsigned int value);
-void timer_set_reload(unsigned int value);
-void busy_wait(unsigned int ms);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __TIMER_H */
index 6988f7ae2bac9cf50fc4a38fb86e3c8bb5fb9e61..1a80ed19d304e114bcae788f36cb65a84960543f 100644 (file)
@@ -1,7 +1,7 @@
 M2DIR=../..
 include $(M2DIR)/software/common.mak
 
-OBJECTS=setjmp.o libc.o errno.o crc16.o crc32.o console.o timer.o system.o board.o uart.o vsnprintf.o strtod.o qsort.o
+OBJECTS=setjmp.o libc.o errno.o crc16.o crc32.o console.o system.o board.o uart.o vsnprintf.o strtod.o qsort.o
 
 all: libbase.a
 
index c0d9e24d1a06fd8d9786dc3b19c0bc83240f45b3..48764a538b67ce00e98ca695c20167c8f9213212 100644 (file)
@@ -3,7 +3,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <version.h>
-#include <timer.h>
 #include <board.h>
 
 static const struct board_desc boards[1] = {
@@ -88,7 +87,7 @@ void board_init(void)
        }
        rev = get_pcb_revision();
        get_soc_version_formatted(soc_version);
-       printf("Detected SoC %s at %dMHz on %s (PCB revision %d)\n", soc_version, get_system_frequency()/1000000,
+       printf("Detected SoC %s at %dMHz on %s (PCB revision %d)\n", soc_version, identifier_frequency_read()/1000000,
               brd_desc->name, rev);
        if(strcmp(soc_version, VERSION) != 0)
                printf("SoC and BIOS versions do not match!\n");
diff --git a/software/libbase/timer.c b/software/libbase/timer.c
deleted file mode 100644 (file)
index d143b65..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#include <hw/csr.h>
-
-#include "timer.h"
-
-unsigned int get_system_frequency(void)
-{
-       return identifier_frequency_read();
-}
-
-void timer_enable(int en)
-{
-       timer0_en_write(en);
-}
-
-unsigned int timer_get(void)
-{
-       return timer0_value_read();
-}
-
-void timer_set_counter(unsigned int value)
-{
-       timer0_value_write(value);
-}
-
-void timer_set_reload(unsigned int value)
-{
-       timer0_reload_write(value);
-}
-
-void busy_wait(unsigned int ds)
-{
-       timer_enable(0);
-       timer_set_reload(0);
-       timer_set_counter(get_system_frequency()/10*ds);
-       timer_enable(1);
-       while(timer_get());
-}
index 55257d83d700d704e943667681e9b327f9fef16b..8c6d62541e77e8c23d512f8a54bd2fd643781a6f 100644 (file)
@@ -1,7 +1,6 @@
 #include <stdio.h>
 #include <system.h>
 #include <crc.h>
-#include <timer.h>
 #include <hw/csr.h>
 #include <hw/flags.h>
 #include <hw/mem.h>
@@ -388,6 +387,16 @@ void microudp_service(void)
        }
 }
 
+static void busy_wait(unsigned int ds)
+{
+       timer0_en_write(0);
+       timer0_reload_write(0);
+       timer0_load_write(identifier_frequency_read()/10*ds);
+       timer0_en_write(1);
+       timer0_update_value_write(1);
+       while(timer0_value_read()) timer0_update_value_write(1);
+}
+
 void ethreset(void)
 {
        minimac_phy_reset_write(0);
index 4f53219cddca530bef705ec13cfa6edc75c0d15d..1f2c3aa96b37010389fb7ab8da0c445f4fb28f34 100644 (file)
@@ -4,7 +4,12 @@
 
 void time_init(void)
 {
-       timer0_reload_write(2*identifier_frequency_read());
+       int t;
+
+       timer0_en_write(0);
+       t = 2*identifier_frequency_read();
+       timer0_reload_write(t);
+       timer0_load_write(t);
        timer0_en_write(1);
 }
 
@@ -12,7 +17,8 @@ int elapsed(int *last_event, int period)
 {
        int t, dt;
 
-       t = timer0_reload_read() - timer0_value_read(); // TODO: atomic read
+       timer0_update_value_write(1);
+       t = timer0_reload_read() - timer0_value_read();
        dt = t - *last_event;
        if(dt < 0)
                dt += timer0_reload_read();