uptime -- tells how long the system has been running

This commit is contained in:
Renaud 2020-12-05 08:13:29 +08:00
parent 3d6cd1bdc2
commit fd13d29f0c
7 changed files with 275 additions and 2 deletions

View File

@ -30,7 +30,8 @@ PROJECT = f030f4
#SRCS = startup.c init.c success.c
#SRCS = startup.c board.c success.c
#SRCS = startup.c usart1tx.c hello.c
SRCS = startup.c uplow.1.c uptime.1.c
#SRCS = startup.c uplow.1.c uptime.1.c
SRCS = startup.c uplow.2.c uptime.c printf.c putchar.c
OBJS = $(SRCS:.c=.o)
CPU = -mthumb -mcpu=cortex-m0
CFLAGS = $(CPU) -g -Wall -Wextra -Os

77
printf.c Normal file
View File

@ -0,0 +1,77 @@
/* printf.c -- format and print data */
/* Copyright (c) 2020 Renaud Fivet */
#include <stdarg.h>
#include <stdio.h>
#include "system.h" /* kputc(), kputs() */
static int kputu( unsigned u, unsigned d) {
char s[ 12] ; /* room for 11 octal digit + EOS */
char *p = &s[ sizeof s - 1] ; /* point to last byte */
*p = 0 ; /* null terminated string */
do {
unsigned r = u % d ;
u /= d ;
*--p = "0123456789ABCDEF"[ r] ;
} while( u) ;
return kputs( p) ;
}
static int kputi( int i) {
int flag = i < 0 ;
if( flag) {
i = -i ;
kputc( '-') ;
}
return flag + kputu( i, 10) ;
}
int printf( const char *fmt, ...) {
va_list ap ;
int cnt = 0 ;
int c ; /* current char in format string */
va_start( ap, fmt) ;
while( ( c = *fmt++) != 0)
if( c != '%') {
cnt += 1 ; kputc( c) ;
} else if( ( c = *fmt++) == 0) {
cnt += 1 ; kputc( '%') ;
break ;
} else
switch( c) {
case 'c':
cnt += 1 ; kputc( va_arg( ap, int /* char */)) ;
break ;
case 'o':
cnt += kputu( va_arg( ap, unsigned), 8) ;
break ;
case 'u':
cnt += kputu( va_arg( ap, unsigned), 10) ;
break ;
case 'x':
case 'X':
cnt += kputu( va_arg( ap, unsigned), 16) ;
break ;
case 'i':
case 'd':
cnt += kputi( va_arg( ap, int)) ;
break ;
case 's':
cnt += kputs( va_arg( ap, char *)) ;
break ;
default:
cnt += 1 ; kputc( '%') ;
/* fallthrough */
case '%':
cnt += 1 ; kputc( c) ;
}
va_end( ap) ;
return cnt ;
}
/* end of printf.c */

12
putchar.c Normal file
View File

@ -0,0 +1,12 @@
/* putchar.c -- write a character to stdout */
/* Copyright (c) 2020 Renaud Fivet */
#include <stdio.h>
#include "system.h" /* kputc() */
int putchar( int c) {
kputc( c) ;
return c ;
}
/* end of putchar.c */

12
system.h Normal file
View File

@ -0,0 +1,12 @@
/* system.h -- system services */
/* Copyright (c) 2020 Renaud Fivet */
extern volatile unsigned uptime ; /* seconds elapsed since boot */
int init( void) ; /* System initialization, called once at startup */
void kputc( unsigned char c) ; /* character output */
int kputs( const char s[]) ; /* string output */
void yield( void) ; /* give way */
/* end of system.h */

124
uplow.2.c Normal file
View File

@ -0,0 +1,124 @@
/* uplow.2.c -- uptime lower layer
** Copyright (c) 2020 Renaud Fivet
**
** implements system.h interface
** uptime = seconds elapsed since boot
** SysClck 8MHz HSI based, baudrate 9600, Busy wait transmission
** user LED toggled every second
** SysTick interrupt every second
*/
#include "system.h" /* implements system.h */
#define SYSTICK ((volatile long *) 0xE000E010)
#define SYSTICK_CSR SYSTICK[ 0]
#define SYSTICK_RVR SYSTICK[ 1]
#define SYSTICK_CVR SYSTICK[ 2]
#define CAT( a, b) a##b
#define HEXA( a) CAT( 0x, a)
#define RCC ((volatile long *) 0x40021000)
#define RCC_AHBENR RCC[ 5]
#define RCC_AHBENR_IOP( h) (1 << (17 + HEXA( h) - 0xA))
#define RCC_APB2ENR RCC[ 6]
#define RCC_APB2ENR_USART1EN 0x00004000 /* 14: USART1 clock enable */
#define GPIOA ((volatile long *) 0x48000000)
#define GPIOB ((volatile long *) 0x48000400)
#define GPIO( x) CAT( GPIO, x)
#define MODER 0
#define ODR 5
#define AFRH 9
#define USART1 ((volatile long *) 0x40013800)
#define CR1 0 /* Config */
#define BRR 3 /* Baudrate */
#define ISR 7 /* Interrupt and Status */
#define TDR 10 /* Transmit Data */
#define USART_CR1_TE 8 /* 3: Transmit Enable */
#define USART_CR1_RE 4 /* 2: Receive Enable */
#define USART_CR1_UE 1 /* 0: USART Enable */
#define USART_ISR_TXE (1 << 7) /* 7: Transmit Data Register Empty */
/* user LED ON when PA4 is high */
#define LED_IOP A
#define LED_PIN 4
#define LED_ON 1
void kputc( unsigned char c) { /* character output */
static unsigned char lastc ;
if( c == '\n' && lastc != '\r')
kputc( '\r') ;
/* Active wait while transmit register is full */
while( (USART1[ ISR] & USART_ISR_TXE) == 0) ;
USART1[ TDR] = c ;
lastc = c ;
}
int kputs( const char s[]) { /* string output */
int cnt = 0 ;
int c ;
while( (c = *s++) != 0) {
kputc( c) ;
cnt += 1 ;
}
return cnt ;
}
void yield( void) { /* give way */
__asm( "WFI") ; /* Wait for System Tick Interrupt */
}
volatile unsigned uptime ; /* seconds elapsed since boot */
#ifdef LED_ON
static void userLEDtoggle( void) {
GPIO( LED_IOP)[ ODR] ^= 1 << LED_PIN ; /* Toggle User LED */
}
#endif
void SysTick_Handler( void) {
uptime += 1 ;
#ifdef LED_ON
userLEDtoggle() ;
#endif
}
int init( void) {
/* By default SYSCLK == HSI [8MHZ] */
/* SYSTICK */
SYSTICK_RVR = 1000000 - 1 ; /* HBA / 8 */
SYSTICK_CVR = 0 ;
SYSTICK_CSR = 3 ; /* HBA / 8, Interrupt ON, Enable */
/* SysTick_Handler will execute every 1s from now on */
#ifdef LED_ON
/* User LED ON */
RCC_AHBENR |= RCC_AHBENR_IOP( LED_IOP) ; /* Enable IOPx periph */
GPIO( LED_IOP)[ MODER] |= 1 << (LED_PIN * 2) ; /* LED_IO Output [01],
** over default 00 */
/* OTYPER Push-Pull by default */
/* Pxn output default LOW at reset */
# if LED_ON
userLEDtoggle() ;
# endif
#endif
/* USART1 9600 8N1 */
RCC_AHBENR |= RCC_AHBENR_IOP( A) ; /* Enable GPIOA periph */
GPIOA[ MODER] |= 0x0A << (9 * 2) ; /* PA9-10 ALT 10, over default 00 */
GPIOA[ AFRH] |= 0x110 ; /* PA9-10 AF1 0001, over default 0000 */
RCC_APB2ENR |= RCC_APB2ENR_USART1EN ;
USART1[ BRR] = 8000000 / 9600 ; /* PCLK [8MHz] */
USART1[ CR1] |= USART_CR1_UE | USART_CR1_TE ; /* Enable USART & Tx */
return 0 ;
}
/* end of uplow.2.c */

View File

@ -1,4 +1,4 @@
/* uptime.1.c --tells how long the system has been running
/* uptime.1.c -- tells how long the system has been running
** Copyright (c) 2020 Renaud Fivet
**
** v1 displays the number of seconds elapsed since boot

47
uptime.c Normal file
View File

@ -0,0 +1,47 @@
/* uptime.c -- tells how long the system has been running */
/* Copyright (c) 2020 Renaud Fivet */
#include <stdio.h>
#include "system.h" /* uptime, yield() */
static void display( unsigned u, const char *s) {
if( u)
printf( " %d %s%s", u, s, &"s"[ u <= 1]) ;
}
int main( void) {
static unsigned last ;
for( ;;)
if( last != uptime) {
unsigned w, d, h, m ,s ;
last = uptime ;
d = h = m = 0 ;
s = last % 60 ;
w = last / 60 ;
if( w) {
m = w % 60 ;
w /= 60 ;
if( w) {
h = w % 24 ;
w /= 24 ;
if( w) {
d = w % 7 ;
w /= 7 ;
}
}
}
printf( "up") ;
display( w, "week") ;
display( d, "day") ;
display( h, "hour") ;
display( m, "minute") ;
display( s, "second") ;
printf( "\n") ;
} else
yield() ; /* Wait for System Tick Interrupt */
}
/* end of uptime.c */