timer: atomic reads
This commit is contained in:
parent
9f81afb844
commit
581cf5bcb8
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue