Use libgcc.a for integer division as Cortex-M0 has no support for it.

This commit is contained in:
Renaud 2020-12-03 11:15:47 +08:00
parent d92085923a
commit d5b4417571
3 changed files with 152 additions and 2 deletions

View File

@ -28,11 +28,15 @@ PROJECT = f030f4
#SRCS = cstartup.c
#SRCS = startup.c init.c success.c
#SRCS = startup.c board.c success.c
SRCS = startup.c usart1tx.c hello.c
#SRCS = startup.c usart1tx.c hello.c
SRCS = startup.c uplow.1.c uptime.1.c
OBJS = $(SRCS:.c=.o)
CPU = -mthumb -mcpu=cortex-m0
CFLAGS = $(CPU) -g -Wall -Wextra -Os
LD_SCRIPT = $(PROJECT).ld
LIBDIR = $(GCCDIR)/lib/gcc/arm-none-eabi/9.3.1/thumb/v6-m/nofp
LIB_PATHS = -L$(LIBDIR)
LIBS = -lgcc
### Build rules
@ -46,7 +50,7 @@ clean:
$(PROJECT).elf: $(OBJS)
@echo $@
$(LD) -T$(LD_SCRIPT) -Map=$(PROJECT).map -cref -o $@ $(OBJS)
$(LD) -T$(LD_SCRIPT) $(LIB_PATHS) -Map=$(PROJECT).map -cref -o $@ $^ $(LIBS)
$(SIZE) $@
$(OBJDUMP) -hS $@ > $(PROJECT).lst

113
uplow.1.c Normal file
View File

@ -0,0 +1,113 @@
/* uplow.1.c -- uptime lower layer
** Copyright (c) 2020 Renaud Fivet
**
** uptime = seconds elapsed since boot
** SysClck 8MHz HSI based, baudrate 9600, Busy wait transmission
** user LED toggled every second
** SysTick interrupt every second
*/
#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) {
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 puts( const char *s) {
while( *s)
kputc( *s++) ;
kputc( '\n') ;
return 0 ;
}
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.1.c */

33
uptime.1.c Normal file
View File

@ -0,0 +1,33 @@
/* 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
*/
#include <stdio.h>
extern volatile unsigned uptime ;
extern void kputc( unsigned char c) ;
void kputu( unsigned u) {
unsigned r = u % 10 ;
u /= 10 ;
if( u)
kputu( u) ;
kputc( '0' + r) ;
}
int main( void) {
static unsigned last ;
for( ;;)
if( last != uptime) {
last = uptime ;
kputu( last) ;
puts( " sec") ;
} else
__asm( "WFI") ; /* Wait for System Tick Interrupt */
}
/* end of uptime.1.c */