OpenNuvoton / NUC970_Linux_Kernel

Linux Kernel Source Code for NUC970 Series Microprocessor
Other
68 stars 69 forks source link

The minimum resolution of Linux is about 10ms #68

Closed junwushi closed 3 years ago

junwushi commented 3 years ago

void get_time_stamp(char *timestamp) {

char buf[64] = { 0 };
struct timeval tv;
struct tm tm;
size_t len = 28;

memset(&tv, 0, sizeof(tv));
memset(&tm, 0, sizeof(tm));
gettimeofday(&tv, NULL);
localtime_r(&tv.tv_sec, &tm);
strftime(buf, len, "%Y-%m-%d %H:%M:%S", &tm);
len = strlen(buf);
sprintf(buf + len, ".%ld", tv.tv_usec);
sprintf(timestamp, "%s", buf);

}

result: 2021-06-26 07:05:17.930000:---->Received Wlan Packet No.: 1 size:86 caplen:86 2021-06-26 07:05:17.930000:ETH Payload: 2021-06-26 07:05:17.930000:Ehternet II: 2021-06-26 07:05:17.950000:------->got a signal 2021-06-26 07:05:17.950000: fe 80 00 00 00 00 00 00 52 57 9c ff fe aa 06 ba 2021-06-26 07:05:17.950000: fe 80 00 00 00 00 00 00 d4 08 67 ff fe cf b1 a5 2021-06-26 07:05:17.950000:fe80::5257:9cff:feaa:6ba is not belong this network 2021-06-26 07:05:17.950000: 33 33 ff aa 06 ba 00 ff 9b 15 13 16 86 dd 2021-06-26 07:05:17.950000:Frame type: 0x86dd 2021-06-26 07:05:17.950000:Source:00:ff:9b:15:13:16 2021-06-26 07:05:17.950000:Destination:33:33:ff:aa:06:ba

how can impove the resolution of struct timeval ‘s tv_usec。

i want change tick define in the time.c from #define TICKS_PER_SEC 100 to #define TICKS_PER_SEC 1000 Is it possible? Is there any bad influence?

junwushi commented 3 years ago

can open CONFIG_HZ option in kernel?

yachen commented 3 years ago

Hi, Maybe enable high resolution timer? Setting a higher HZ on a 300MHz CPU system might not be a very good option. The scheduler executed too frequent and the overhead can actually slow down the system.

junwushi commented 3 years ago

Thank you for your suggestion. I'll use etimer0 for timing. I want to know whether the operation of reading the value of etimer is thread safe. If I try to lock, it will nest with another lock in the function calling getticks, which will easily lead to deadlock. See function below.

static volatile int efd = -1; const char devetimer[] = "/dev/etimer0"; //timeout=1000 1ms =1000000 1s int init_etimer(int timeout) { int tm; if (timeout == 0) tm = 1000; else tm = timeout; ETIMER_LOCK ; efd = open(&devetimer[0], O_RDWR); if (efd < 0) { ETIMER_UNLOCK ; //LOGERR("open etimer %d error\n", 0); return -1; } //switch clock 12MHz ioctl(efd, ETMR_IOC_CLKHXT, NULL); //Periodic demo ioctl(efd, ETMR_IOC_PERIODIC, &tm); ETIMER_UNLOCK ; return efd; }

uint64_t getticks(void) { static unsigned int tick_h = 0U; static unsigned int tick_l = 0U; unsigned int tick; uint64_t retticks; ETIMER_LOCK ; if (efd < 0) { ETIMER_UNLOCK ; return 0; } read(efd, &tick, sizeof(tick)); ; if (tick < tick_l) { tick_h++; } tick_l = tick; retticks = (((uint64_t) tick_h << 24) | tick_l); ETIMER_UNLOCK ; return retticks; } void uninit_etimer(void) { ETIMER_LOCK ; if (efd < 0) { ETIMER_UNLOCK ; return; } ioctl(efd, ETMR_IOC_STOP, NULL); close(efd); efd = -1; ETIMER_UNLOCK ; }

yachen commented 3 years ago

Hi, There's already a spinlock with in the driver's read function. You don't need add an application level lock for protection.

static ssize_t etimer_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    unsigned long flag;
    struct nuc970_etimer *t = (struct nuc970_etimer *)filp->private_data;
    int ret = 0;

    spin_lock_irqsave(&t->lock, flag);
junwushi commented 3 years ago

After I remove the lock, I run my program, and then Ctrl + C exits several times. I confirm that each exit will execute uninit eimer function, do this many times, and then run the program will find that the etimer device can not be opened, the error show "init etimer fail."。 There is no exact reason to be found now.

yachen commented 3 years ago

Hi, What's the error code?

junwushi commented 3 years ago

[root 02:17 ~]# cat /dev/etimer0 cat: can't open '/dev/etimer0': Device or resource busy [root 02:17 ~]#

junwushi commented 3 years ago

I add debugging information to the driver. When I execute the following two statements ioctl(efd, ETMR IOC STOP, NULL); close(efd); Etimer_release in kernel function has not been called. Why?

junwushi commented 3 years ago

1.add debug message in driver static int etimer_release(struct inode inode, struct file filp) { struct nuc970_etimer t = (struct nuc970_etimer )filp->private_data; int ch = t->ch; unsigned long flag; printk("etimer%d closed1.\n",ch);

stop_timer(t);
**printk("etimer%d closed2.\n",ch);**

// free irq
free_irq(etmr[ch]->irq, etmr[ch]);
// disable clk
clk_disable(etmr[ch]->clk);
clk_disable(etmr[ch]->eclk);
clk_put(etmr[ch]->clk);
clk_put(etmr[ch]->eclk);
**printk("etimer%d closed3.\n",ch);**

spin_lock_irqsave(&etmr[ch]->lock, flag);
etmr[ch]->occupied = 0;
spin_unlock_irqrestore(&etmr[ch]->lock, flag);
filp->private_data = NULL;
**printk("etimer%d closed4.\n",ch);**
return(0);

}

2.program running once, it is working well. Starting router: OK [ 29.980000] etimer0 opened.

Welcome to FTGateway FTGateway login: [ 30.010000] ttyS3: 1 input overrun(s) root Password: [root 07:54 ~]# killall router [root 07:54 ~]# [ 42.680000] etimer0 closed1. [ 42.680000] etimer0 closed2. [ 42.690000] etimer0 closed3. [ 42.690000] etimer0 closed4.

3.program running seconds, failing:

[root 07:54 ~]# router -b460800

FT-RF Router V1.18 Runn[ 47.630000] etimer0 opened. ing at: libpcap version 1.10.0 (with TPACKET_V3) RF baudrate:460800 RF device:ttyS5 WAN device:tap0 BAT Voltage:4194mv AC Voltage:5689mv Packet interval(0-20000us):0 Packet EOF number(0xc0)(0-10):2 2021-07-02 07:54:40.840 :etimer open it 3. udhcpc: started, v1.25.1 udhcpc: sending discover udhcpc: sending select for 192.168.0.93 udhcpc: lease of 192.168.0.93 obtained, lease time 691200 2021-07-02 07:54:41.590 :libnet_init tap0 fail:libnet_check_iface() ioctl: No such device waiting 5 seconds try again. ^C 2021-07-02 07:54:48.080 :etimer close it 3. 4.---->"print by user application ,but no kernal closed message output " "