mirror of
https://github.com/kelvinlawson/atomthreads.git
synced 2026-01-11 10:16:37 +01:00
Added support for Cortex-M0
Added board nucleo-f072rb
This commit is contained in:
@@ -197,32 +197,32 @@ $(build_dir)/%.elf $(build_dir)/%.map: $(build_dir)/%.o $(build_objs) $(LDSCRIPT
|
||||
$(if $(Q), @echo " (ELF) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(build_objs) $(build_dir)/$(*).o $(LDLIBS) -o $@
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.S
|
||||
$(build_dir)/%.o: $(src_dir)/%.S Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (AS) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -D__ASSEMBLY__ -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(src_dir)/%.c
|
||||
$(build_dir)/%.o: $(src_dir)/%.c Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(board_dir)/%.c
|
||||
$(build_dir)/%.o: $(board_dir)/%.c Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(common_dir)/%.c
|
||||
$(build_dir)/%.o: $(common_dir)/%.c Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(kernel_dir)/%.c
|
||||
$(build_dir)/%.o: $(kernel_dir)/%.c Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
$(build_dir)/%.o: $(tests_dir)/%.c
|
||||
$(build_dir)/%.o: $(tests_dir)/%.c Makefile
|
||||
$(Q)mkdir -p `dirname $@`
|
||||
$(if $(Q), @echo " (CC) $(subst $(build_dir)/,,$@)")
|
||||
$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -I`dirname $<` -c $< -o $@
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# ARM Cortex-M Port
|
||||
|
||||
## Summary and Prerequisites
|
||||
This port should run on any Cortex-M3/4/4F (but not on M0, sorry). It uses
|
||||
This port should run on any Cortex-M0/3/4/4F (M0+ not tested). It uses
|
||||
RedHat's [newlib](https://sourceware.org/newlib/) and [libopencm3]
|
||||
(https://github.com/libopencm3/libopencm3). You will also need an ARM compiler
|
||||
toolchain. If you want to flash or debug your target, [openocd](http://openocd.org)
|
||||
|
||||
@@ -29,11 +29,24 @@
|
||||
|
||||
.syntax unified
|
||||
|
||||
#undef THUMB_2
|
||||
#undef WITH_FPU
|
||||
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
#define THUMB_2
|
||||
#endif
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
#define WITH_FPU
|
||||
#endif
|
||||
|
||||
.extern CTX_SW_NFO
|
||||
.extern _stack
|
||||
.extern vector_table
|
||||
|
||||
.equ FPU_USED, 0x00000010
|
||||
.equ FPU_USED, 0x00000010
|
||||
.equ SCB_ICSR, 0xE000ED04
|
||||
.equ PENDSVCLR, 0x08000000
|
||||
|
||||
.text
|
||||
|
||||
@@ -46,7 +59,7 @@ archFirstThreadRestore:
|
||||
* Disable interrupts. They should be disabled anyways, but just
|
||||
* to make sure...
|
||||
*/
|
||||
mov r1, #1
|
||||
movs r1, #1
|
||||
msr PRIMASK, r1
|
||||
|
||||
/**
|
||||
@@ -63,38 +76,101 @@ archFirstThreadRestore:
|
||||
str r0, [r1, #4]
|
||||
|
||||
/* Get thread stack pointer from tcb. Conveniently the first element */
|
||||
ldr r2, [r0, #0]
|
||||
ldr r1, [r0, #0]
|
||||
msr PSP, r1
|
||||
|
||||
/* Discard dummy thread stack frame */
|
||||
add r2, r2, #36
|
||||
|
||||
/**
|
||||
* New threads can't have used the FPU, so no need to check for
|
||||
* FPU stack frame here
|
||||
* Set bit #1 in CONTROL. Causes switch to PSP, so we can work directly
|
||||
* with SP now and use pop/push.
|
||||
*/
|
||||
movs r1, #2
|
||||
mrs r2, CONTROL
|
||||
orrs r2, r2, r1
|
||||
msr CONTROL, r2
|
||||
|
||||
/**
|
||||
* Initialise thread's register context from its stack frame. Since this
|
||||
* function gets called only once at system start up, execution time is
|
||||
* not critical. We can get away with using only Thumb-1 instructions that
|
||||
* will work on all Cortex-M devices.
|
||||
*
|
||||
* Initial stack looks like this:
|
||||
* xPSR
|
||||
* PC
|
||||
* lr
|
||||
* r12
|
||||
* r3
|
||||
* r2
|
||||
* r1
|
||||
* r0
|
||||
* exc_ret <- ignored here
|
||||
* r11
|
||||
* r10
|
||||
* r9
|
||||
* r8
|
||||
* r7
|
||||
* r6
|
||||
* r5
|
||||
* r4 <- thread's saved_sp points here
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load exception stack frame to registers r3-r10. xPSR ends up in r10,
|
||||
* pc in r9
|
||||
*
|
||||
* Move SP to position of r8 and restore high registers by loading
|
||||
* them to r4-r7 before moving them to r8-r11
|
||||
*/
|
||||
ldmia r2!, {r3-r10}
|
||||
add SP, #16
|
||||
pop {r4-r7}
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
mov r11, r7
|
||||
|
||||
/* initialise xPSR and store store adjusted stack pointer in PSP */
|
||||
msr APSR_nzcvq, r10
|
||||
msr PSP, r2
|
||||
/* move SP back to top of stack and load r4-r7 */
|
||||
sub SP, #32
|
||||
pop {r4-r7}
|
||||
|
||||
/* set bit #1 in CONTROL. Causes switch to PSP */
|
||||
mrs r1, CONTROL
|
||||
orr r1, r1, #2
|
||||
msr CONTROL, r1
|
||||
/*load r12, lr, pc and xpsr to r0-r3 and restore r12 and lr */
|
||||
add SP, #36
|
||||
pop {r0-r3}
|
||||
mov r12, r0
|
||||
mov lr, r1
|
||||
|
||||
/**
|
||||
* r2 contains the PC and r3 APSR, SP is now at the bottom of the stack. We
|
||||
* can't initialise APSR now because we will have to do a movs later when
|
||||
* enabling interrupts, so r3 must not be touched. We also need an extra
|
||||
* register holding the value that will be moved to PRIMASK. To do this,
|
||||
* we build a new stack containing only the initial values of r2, r3
|
||||
* and pc. In the end this will be directly popped into the registers,
|
||||
* finishing the thread restore and branching to the thread's entry point.
|
||||
*/
|
||||
|
||||
/* Save PC value */
|
||||
push {r2}
|
||||
|
||||
/* Move values for r2 and r3 to lie directly below value for pc */
|
||||
sub SP, #20
|
||||
pop {r1-r2}
|
||||
add SP, #12
|
||||
push {r1-r2}
|
||||
|
||||
/* Load values for r0 and r1 from stack */
|
||||
sub SP, #20
|
||||
pop {r0-r1}
|
||||
|
||||
/* Move SP to start of our new r2,r3,pc mini stack */
|
||||
add SP, #12
|
||||
|
||||
/* Restore xPSR and enable interrupts */
|
||||
movs r2, #0
|
||||
msr APSR_nzcvq, r3
|
||||
msr PRIMASK, r2
|
||||
|
||||
/* enable interrupts */
|
||||
mov r1, #0
|
||||
msr PRIMASK, r1
|
||||
|
||||
/* branch to thread entry point */
|
||||
bx r9
|
||||
/* Pop r2,r3,pc from stack, thereby jumping to thread entry point */
|
||||
pop {r2,r3,pc}
|
||||
nop
|
||||
|
||||
.size archFirstThreadRestore, . - archFirstThreadRestore
|
||||
.endfunc
|
||||
|
||||
@@ -107,13 +183,47 @@ pend_sv_handler:
|
||||
* Disable interrupts. No need to check if they were enabled because,
|
||||
* well, we're an interrupt handler. Duh...
|
||||
*/
|
||||
mov r0, #1
|
||||
movs r0, #1
|
||||
msr PRIMASK, r0
|
||||
|
||||
/* Get running thread's stack pointer*/
|
||||
/**
|
||||
* Clear PendSv pending bit. There seems to exist a hardware race condition
|
||||
* in the NVIC that can prevent automatic clearing of the PENDSVSET. See
|
||||
* http://embeddedgurus.com/state-space/2011/09/whats-the-state-of-your-cortex/
|
||||
*/
|
||||
ldr r0, = SCB_ICSR
|
||||
ldr r1, = PENDSVCLR
|
||||
str r1, [r0, #0]
|
||||
|
||||
/**
|
||||
* Check if running and next thread are really different.
|
||||
* From here on we have
|
||||
* r0 = &ctx_switch_info
|
||||
* r1 = ctx_switch_info.running_tcb
|
||||
* r2 = ctx_switch_info.next_tcb
|
||||
*
|
||||
* If r1 == r2 we can skip the context switch. This may theoretically
|
||||
* happen if the running thread gets scheduled out and in again by
|
||||
* multiple nested or tail-chained ISRs before the PendSv handler
|
||||
* gets called.
|
||||
*/
|
||||
ldr r0, = CTX_SW_NFO
|
||||
ldr r1, [r0, #0]
|
||||
ldr r2, [r0, #4]
|
||||
cmp r1, r2
|
||||
beq no_switch
|
||||
|
||||
/**
|
||||
* Copy running thread's process stack pointer to r3 and use it to push
|
||||
* */
|
||||
mrs r3, PSP
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
#if defined(THUMB_2)
|
||||
/**
|
||||
* Save old thread's context on Cortex-M[34]
|
||||
*/
|
||||
|
||||
#if defined(WITH_FPU)
|
||||
/* Check if FPU was used by thread and store registers if necessary */
|
||||
tst lr, FPU_USED
|
||||
it eq
|
||||
@@ -124,31 +234,68 @@ pend_sv_handler:
|
||||
* fault handler to store the FPU registers if another thread
|
||||
* tries using it
|
||||
*/
|
||||
#endif
|
||||
#endif // WITH_FPU
|
||||
|
||||
/* Push running thread's remaining registers on stack */
|
||||
stmdb r3!, {r4-r11, lr}
|
||||
|
||||
/* Fetch running thread's TCB and store its current stack pointer */
|
||||
ldr r2, = CTX_SW_NFO
|
||||
ldr r1, [r2, #0]
|
||||
#else // !THUMB2
|
||||
|
||||
/**
|
||||
* Save old thread's register context on Cortex-M0.
|
||||
* Push running thread's remaining registers on stack.
|
||||
* Thumb-1 can only use stm on low registers, so we
|
||||
* have to do this in two steps.
|
||||
*/
|
||||
|
||||
/* Reserve space for r8-r11 + exc_return before storing r4-r7 */
|
||||
subs r3, r3, #36
|
||||
stmia r3!, {r4-r7}
|
||||
|
||||
/**
|
||||
* Move r8-r11 to low registers and use store multiple with automatic
|
||||
* post-increment to push them on the stack
|
||||
*/
|
||||
mov r4, r8
|
||||
mov r5, r9
|
||||
mov r6, r10
|
||||
mov r7, r11
|
||||
stmia r3!, {r4-r7}
|
||||
|
||||
/**
|
||||
* Move lr (contains the exc_return code) to low registers and store it
|
||||
* on the stack.
|
||||
*/
|
||||
mov r4, lr
|
||||
str r4, [r3, #0]
|
||||
|
||||
/* Re-adjust r3 to point at top of stack */
|
||||
subs r3, r3, #32
|
||||
#endif // !THUMB_2
|
||||
/**
|
||||
* Address of running TCB still in r1. Store threads current stack top
|
||||
* into its sp_save_ptr, which is the struct's first element
|
||||
*/
|
||||
str r3, [r1, #0]
|
||||
|
||||
/**
|
||||
* Fetch pointer to next thread's tcb from ctx_switch_info.next_tcb and
|
||||
* use it to update ctx_switch_info.running_tcb.
|
||||
* ctx_switch_info.next_tcb is going to become ctx_switch_info.running_tcb,
|
||||
* so we update the pointer.
|
||||
*/
|
||||
ldr r1, [r2, #4]
|
||||
str r1, [r2, #0]
|
||||
str r2, [r0, #0]
|
||||
|
||||
/**
|
||||
* Fetch next thread's stack pointer from its TCB and restore
|
||||
* Fetch next thread's stack pointer from its TCB's sp_save_ptr and restore
|
||||
* the thread's register context.
|
||||
*/
|
||||
ldr r3, [r1, #0]
|
||||
ldr r3, [r2, #0]
|
||||
|
||||
#if defined(THUMB_2)
|
||||
|
||||
/* Cortex-M[34], restore thread's task stack frame */
|
||||
ldmia r3!, {r4-r11, lr}
|
||||
|
||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
||||
#if defined(WITH_FPU)
|
||||
/**
|
||||
* Check if FPU was used by new thread and restore registers if necessary.
|
||||
*/
|
||||
@@ -160,13 +307,43 @@ pend_sv_handler:
|
||||
* TODO: only restore FPU registers if FPU was used by another thread
|
||||
* between this thread being scheduled out and now.
|
||||
*/
|
||||
#endif
|
||||
#endif // WITH_FPU
|
||||
#else // !THUMB_2
|
||||
|
||||
/* Restore process stack pointer */
|
||||
/**
|
||||
* Thread restore for Cortex-M0
|
||||
* Restore thread's task stack frame. Because thumb 1 only supports
|
||||
* load multiple on low register, we have to do it in two steps and
|
||||
* adjust the stack pointer manually.
|
||||
*/
|
||||
|
||||
/* Restore high registers */
|
||||
adds r3, r3, #16
|
||||
ldmia r3!, {r4-r7}
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
mov r11, r7
|
||||
|
||||
/* Restore lr */
|
||||
ldr r4, [r3, #0]
|
||||
mov lr, r4
|
||||
subs r3, r3, #32
|
||||
|
||||
/**
|
||||
* Restore r4-r7 and adjust r3 to point at the top of the exception
|
||||
* stack frame.
|
||||
*/
|
||||
ldmia r3!, {r4-r7}
|
||||
adds r3, r3, #20
|
||||
#endif // !THUMB_2
|
||||
|
||||
/* Set process stack pointer to new thread's stack*/
|
||||
msr PSP, r3
|
||||
|
||||
no_switch:
|
||||
/* Re-enable interrupts */
|
||||
mov r0, #0
|
||||
movs r0, #0
|
||||
msr PRIMASK, r0
|
||||
|
||||
/* Return to new thread */
|
||||
|
||||
@@ -45,7 +45,7 @@ struct isr_stack {
|
||||
uint32_t lr;
|
||||
uint32_t pc;
|
||||
uint32_t psr;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
struct isr_fpu_stack {
|
||||
uint32_t s0;
|
||||
@@ -65,7 +65,7 @@ struct isr_fpu_stack {
|
||||
uint32_t s14;
|
||||
uint32_t s15;
|
||||
uint32_t fpscr;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* remaining context saved by task switch ISR
|
||||
@@ -79,8 +79,8 @@ struct task_stack {
|
||||
uint32_t r9;
|
||||
uint32_t r10;
|
||||
uint32_t r11;
|
||||
uint32_t lr;
|
||||
};
|
||||
uint32_t exc_ret;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct task_fpu_stack {
|
||||
uint32_t s16;
|
||||
@@ -99,7 +99,7 @@ struct task_fpu_stack {
|
||||
uint32_t s29;
|
||||
uint32_t s30;
|
||||
uint32_t s31;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Info needed by pend_sv_handler used for delayed task switching.
|
||||
@@ -112,6 +112,6 @@ struct task_fpu_stack {
|
||||
struct task_switch_info {
|
||||
volatile struct atom_tcb *running_tcb;
|
||||
volatile struct atom_tcb *next_tcb;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
#endif /* __ATOMPORT_PRIVATE_H_ */
|
||||
|
||||
@@ -165,28 +165,28 @@ void archThreadContextInit(ATOM_TCB *tcb_ptr, void *stack_top,
|
||||
isr_ctx->pc = (uint32_t) thread_shell;
|
||||
|
||||
/* initialise unused registers to silly value */
|
||||
isr_ctx->lr = 0xDEADBEEF;
|
||||
isr_ctx->r12 = 0xDEADBEEF;
|
||||
isr_ctx->r3 = 0xDEADBEEF;
|
||||
isr_ctx->r2 = 0xDEADBEEF;
|
||||
isr_ctx->r1 = 0xDEADBEEF;
|
||||
isr_ctx->r0 = 0xDEADBEEF;
|
||||
isr_ctx->lr = 0xEEEEEEEE;
|
||||
isr_ctx->r12 = 0xCCCCCCCC;
|
||||
isr_ctx->r3 = 0x33333333;
|
||||
isr_ctx->r2 = 0x22222222;
|
||||
isr_ctx->r1 = 0x11111111;
|
||||
isr_ctx->r0 = 0x00000000;
|
||||
|
||||
/**
|
||||
* We use this special EXC_RETURN code to switch from main stack to our
|
||||
* thread stack on exception return
|
||||
*/
|
||||
tsk_ctx->lr = 0xFFFFFFFD;
|
||||
tsk_ctx->exc_ret = 0xFFFFFFFD;
|
||||
|
||||
/* initialise unused registers to silly value */
|
||||
tsk_ctx->r11 = 0xDEADBEEF;
|
||||
tsk_ctx->r10 = 0xDEADBEEF;
|
||||
tsk_ctx->r9 = 0xDEADBEEF;
|
||||
tsk_ctx->r8 = 0xDEADBEEF;
|
||||
tsk_ctx->r7 = 0xDEADBEEF;
|
||||
tsk_ctx->r6 = 0xDEADBEEF;
|
||||
tsk_ctx->r5 = 0xDEADBEEF;
|
||||
tsk_ctx->r4 = 0xDEADBEEF;
|
||||
tsk_ctx->r11 = 0xBBBBBBBB;
|
||||
tsk_ctx->r10 = 0xAAAAAAAA;
|
||||
tsk_ctx->r9 = 0x99999999;
|
||||
tsk_ctx->r8 = 0x88888888;
|
||||
tsk_ctx->r7 = 0x77777777;
|
||||
tsk_ctx->r6 = 0x66666666;
|
||||
tsk_ctx->r5 = 0x55555555;
|
||||
tsk_ctx->r4 = 0x44444444;
|
||||
|
||||
/**
|
||||
* Stack frames have been initialised, save it to the TCB. Also set
|
||||
|
||||
15
ports/cortex-m/boards/nucleo-f072rb/Makefile
Normal file
15
ports/cortex-m/boards/nucleo-f072rb/Makefile
Normal file
@@ -0,0 +1,15 @@
|
||||
TARGET := stm32f072rb
|
||||
LIBNAME = opencm3_stm32f0
|
||||
DEFS = -DSTM32F0
|
||||
DEFS += -DSTD_CON=USART2
|
||||
DEFS += -DMST_SIZE=0x400
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ARCH_FLAGS = -mthumb -mcpu=cortex-m0
|
||||
|
||||
OOCD ?= openocd
|
||||
OOCD_INTERFACE ?= stlink-v2-1
|
||||
OOCD_BOARD ?= st_nucleo_f0
|
||||
|
||||
objs += board_setup.o
|
||||
objs += stubs.o stm32_con.o
|
||||
127
ports/cortex-m/boards/nucleo-f072rb/board_setup.c
Normal file
127
ports/cortex-m/boards/nucleo-f072rb/board_setup.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Tido Klaassen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. No personal names or organizations' names associated with the
|
||||
* Atomthreads project may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libopencm3/stm32/rcc.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/stm32/usart.h>
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
#include <libopencm3/cm3/cortex.h>
|
||||
|
||||
#include "atomport.h"
|
||||
|
||||
/**
|
||||
* Set up USART2.
|
||||
* This one is connected via the virtual serial port on the Nucleo Board
|
||||
*/
|
||||
static void usart_setup(uint32_t baud)
|
||||
{
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
rcc_periph_clock_enable(RCC_USART2);
|
||||
|
||||
usart_disable(USART2);
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
|
||||
gpio_set_af(GPIOA, GPIO_AF1, GPIO2 | GPIO3);
|
||||
|
||||
usart_set_baudrate(USART2, baud);
|
||||
usart_set_databits(USART2, 8);
|
||||
usart_set_parity(USART2, USART_PARITY_NONE);
|
||||
usart_set_stopbits(USART2, USART_CR2_STOP_1_0BIT);
|
||||
usart_set_mode(USART2, USART_MODE_TX_RX);
|
||||
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
|
||||
|
||||
usart_enable(USART2);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialise and start SysTick counter. This will trigger the
|
||||
* sys_tick_handler() periodically once interrupts have been enabled
|
||||
* by archFirstThreadRestore()
|
||||
*/
|
||||
static void systick_setup(void)
|
||||
{
|
||||
systick_set_frequency(SYSTEM_TICKS_PER_SEC, 48000000);
|
||||
|
||||
systick_interrupt_enable();
|
||||
|
||||
systick_counter_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the core clock to something other than the internal 16MHz PIOSC.
|
||||
* Make sure that you use the same clock frequency in systick_setup().
|
||||
*/
|
||||
static void clock_setup(void)
|
||||
{
|
||||
/* set core clock to 72MHz, generated from external 8MHz crystal */
|
||||
rcc_clock_setup_in_hsi_out_48mhz();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up user LED and provide function for toggling it. This is for
|
||||
* use by the test suit programs
|
||||
*/
|
||||
static void test_led_setup(void)
|
||||
{
|
||||
/* LED is connected to GPIO5 on port A */
|
||||
rcc_periph_clock_enable(RCC_GPIOA);
|
||||
|
||||
gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO5);
|
||||
gpio_set(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
void test_led_toggle(void)
|
||||
{
|
||||
gpio_toggle(GPIOA, GPIO5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback from your main program to set up the board's hardware before
|
||||
* the kernel is started.
|
||||
*/
|
||||
int board_setup(void)
|
||||
{
|
||||
/* Disable interrupts. This makes sure that the sys_tick_handler will
|
||||
* not be called before the first thread has been started.
|
||||
* Interrupts will be enabled by archFirstThreadRestore().
|
||||
*/
|
||||
cm_mask_interrupts(true);
|
||||
|
||||
/* configure system clock, user LED and UART */
|
||||
clock_setup();
|
||||
test_led_setup();
|
||||
usart_setup(115200);
|
||||
|
||||
/* initialise SysTick counter */
|
||||
systick_setup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
10
ports/cortex-m/linker/stm32f072rb.ld
Normal file
10
ports/cortex-m/linker/stm32f072rb.ld
Normal file
@@ -0,0 +1,10 @@
|
||||
/* Memory regions for STM32F072RB, 128K flash, 16K RAM. */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
/* Include main opencm3 linker script */
|
||||
INCLUDE libopencm3_stm32f0.ld
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include "atom.h"
|
||||
#include "atomport-private.h"
|
||||
#include "atomtests.h"
|
||||
@@ -144,6 +145,8 @@ int main ( void )
|
||||
{
|
||||
int8_t status;
|
||||
|
||||
nvic_set_priority(NVIC_PENDSV_IRQ, 0xFF);
|
||||
nvic_set_priority(NVIC_SYSTICK_IRQ, 0xFE);
|
||||
|
||||
/**
|
||||
* Note: to protect OS structures and data during initialisation,
|
||||
|
||||
Reference in New Issue
Block a user