Просмотр исходного кода

Merge pull request #2132 from jesven/k210

add k210 SMP support
Bernard Xiong 6 лет назад
Родитель
Сommit
95b97884e4

+ 2 - 34
bsp/k210/.config

@@ -7,7 +7,8 @@
 # RT-Thread Kernel
 #
 CONFIG_RT_NAME_MAX=8
-# CONFIG_RT_USING_SMP is not set
+CONFIG_RT_USING_SMP=y
+CONFIG_RT_CPUS_NR=2
 CONFIG_RT_ALIGN_SIZE=8
 # CONFIG_RT_THREAD_PRIORITY_8 is not set
 CONFIG_RT_THREAD_PRIORITY_32=y
@@ -326,39 +327,6 @@ CONFIG_PKG_KENDRYTE_SDK_VER="v0.5.2"
 # CONFIG_PKG_USING_DSTR is not set
 # CONFIG_PKG_USING_TINYFRAME is not set
 # CONFIG_PKG_USING_KENDRYTE_DEMO is not set
-# CONFIG_PKG_USING_KENDRYTE_DEMO_V001 is not set
-# CONFIG_PKG_USING_KENDRYTE_DEMO_LATEST_VERSION is not set
-# CONFIG_KENDRYTE_DEMO_NONE is not set
-# CONFIG_KENDRYTE_DEMO_AES_128_TEST is not set
-# CONFIG_KENDRYTE_DEMO_AES_192_TEST is not set
-# CONFIG_KENDRYTE_DEMO_AES_256_TEST is not set
-# CONFIG_KENDRYTE_DEMO_AI_DEMO_SIM is not set
-# CONFIG_KENDRYTE_DEMO_DVP_OV is not set
-# CONFIG_KENDRYTE_DEMO_FACE_DETECT is not set
-# CONFIG_KENDRYTE_DEMO_FFT_TEST is not set
-# CONFIG_KENDRYTE_DEMO_FLASH_W25QXX is not set
-# CONFIG_KENDRYTE_DEMO_FLASH_W25QXX_DMA_TEST is not set
-# CONFIG_KENDRYTE_DEMO_FLASH_W25QXX_TEST is not set
-# CONFIG_KENDRYTE_DEMO_GPIOHS_LED is not set
-# CONFIG_KENDRYTE_DEMO_GPIO_LED is not set
-# CONFIG_KENDRYTE_DEMO_HELLO_WORLD is not set
-# CONFIG_KENDRYTE_DEMO_I2C_SLAVE is not set
-# CONFIG_KENDRYTE_DEMO_KPU is not set
-# CONFIG_KENDRYTE_DEMO_LCD is not set
-# CONFIG_KENDRYTE_DEMO_MIC_PLAY is not set
-# CONFIG_KENDRYTE_DEMO_PLAY_PCM is not set
-# CONFIG_KENDRYTE_DEMO_PWM is not set
-# CONFIG_KENDRYTE_DEMO_RTC is not set
-# CONFIG_KENDRYTE_DEMO_RTC_SD3068 is not set
-# CONFIG_KENDRYTE_DEMO_SD_CARD is not set
-# CONFIG_KENDRYTE_DEMO_SERVO is not set
-# CONFIG_KENDRYTE_DEMO_SHA256_TEST is not set
-# CONFIG_KENDRYTE_DEMO_TIMER is not set
-# CONFIG_KENDRYTE_DEMO_UART is not set
-# CONFIG_KENDRYTE_DEMO_UART_DMA is not set
-# CONFIG_KENDRYTE_DEMO_UART_DMA_IRQ is not set
-# CONFIG_KENDRYTE_DEMO_UART_INTERRUPT is not set
-# CONFIG_KENDRYTE_DEMO_WATCHDOG is not set
 
 #
 # samples: kernel and components samples

+ 12 - 10
bsp/k210/driver/board.c

@@ -37,21 +37,14 @@ void init_bss(void)
     }
 }
 
-void cpu_entry(int cpuid)
+void primary_cpu_entry(void)
 {
     extern void entry(void);
 
     /* disable global interrupt */
+    init_bss();
     rt_hw_interrupt_disable();
-    if (cpuid == 0)
-    {
-        init_bss();
-        entry();
-    }
-    else
-    {
-        while (1) ;
-    }
+    entry();
 }
 
 #include <clint.h>
@@ -85,6 +78,10 @@ int freq(void)
 }
 MSH_CMD_EXPORT(freq, show freq info);
 
+#ifdef RT_USING_SMP
+extern int rt_hw_clint_ipi_enable(void);
+#endif
+
 void rt_hw_board_init(void)
 {
     /* Init FPIOA */
@@ -96,8 +93,13 @@ void rt_hw_board_init(void)
     rt_hw_interrupt_init();
     /* initialize hardware interrupt */
     rt_hw_uart_init();
+
     rt_hw_tick_init();
 
+#ifdef RT_USING_SMP
+    rt_hw_clint_ipi_enable();
+#endif
+
 #ifdef RT_USING_CONSOLE
     /* set console device */
     rt_console_set_device(RT_CONSOLE_DEVICE_NAME);

+ 159 - 0
bsp/k210/rtconfig.h

@@ -7,8 +7,12 @@
 /* RT-Thread Kernel */
 
 #define RT_NAME_MAX 8
+#define RT_USING_SMP
+#define RT_CPUS_NR 2
 #define RT_ALIGN_SIZE 8
+/* RT_THREAD_PRIORITY_8 is not set */
 #define RT_THREAD_PRIORITY_32
+/* RT_THREAD_PRIORITY_256 is not set */
 #define RT_THREAD_PRIORITY_MAX 32
 #define RT_TICK_PER_SECOND 100
 #define RT_USING_OVERFLOW_CHECK
@@ -16,9 +20,19 @@
 #define RT_USING_IDLE_HOOK
 #define RT_IDEL_HOOK_LIST_SIZE 4
 #define IDLE_THREAD_STACK_SIZE 1024
+/* RT_USING_TIMER_SOFT is not set */
 #define RT_DEBUG
 #define RT_DEBUG_INIT_CONFIG
 #define RT_DEBUG_INIT 1
+/* RT_DEBUG_THREAD_CONFIG is not set */
+/* RT_DEBUG_SCHEDULER_CONFIG is not set */
+/* RT_DEBUG_IPC_CONFIG is not set */
+/* RT_DEBUG_TIMER_CONFIG is not set */
+/* RT_DEBUG_IRQ_CONFIG is not set */
+/* RT_DEBUG_MEM_CONFIG is not set */
+/* RT_DEBUG_SLAB_CONFIG is not set */
+/* RT_DEBUG_MEMHEAP_CONFIG is not set */
+/* RT_DEBUG_MODULE_CONFIG is not set */
 
 /* Inter-Thread communication */
 
@@ -27,16 +41,23 @@
 #define RT_USING_EVENT
 #define RT_USING_MAILBOX
 #define RT_USING_MESSAGEQUEUE
+/* RT_USING_SIGNALS is not set */
 
 /* Memory Management */
 
 #define RT_USING_MEMPOOL
+/* RT_USING_MEMHEAP is not set */
+/* RT_USING_NOHEAP is not set */
 #define RT_USING_SMALL_MEM
+/* RT_USING_SLAB is not set */
+/* RT_USING_MEMTRACE is not set */
 #define RT_USING_HEAP
 
 /* Kernel Device Object */
 
 #define RT_USING_DEVICE
+/* RT_USING_DEVICE_OPS is not set */
+/* RT_USING_INTERRUPT_INFO is not set */
 #define RT_USING_CONSOLE
 #define RT_CONSOLEBUF_SIZE 128
 #define RT_CONSOLE_DEVICE_NAME "uarths"
@@ -44,6 +65,7 @@
 #define ARCH_CPU_64BIT
 #define ARCH_RISCV
 #define ARCH_RISCV64
+/* ARCH_CPU_STACK_GROWS_UPWARD is not set */
 
 /* RT-Thread Components */
 
@@ -54,6 +76,7 @@
 
 /* C++ features */
 
+/* RT_USING_CPLUSPLUS is not set */
 
 /* Command shell */
 
@@ -63,9 +86,11 @@
 #define FINSH_HISTORY_LINES 5
 #define FINSH_USING_SYMTAB
 #define FINSH_USING_DESCRIPTION
+/* FINSH_ECHO_DISABLE_DEFAULT is not set */
 #define FINSH_THREAD_PRIORITY 20
 #define FINSH_THREAD_STACK_SIZE 16384
 #define FINSH_CMD_SIZE 80
+/* FINSH_USING_AUTH is not set */
 #define FINSH_USING_MSH
 #define FINSH_USING_MSH_DEFAULT
 #define FINSH_USING_MSH_ONLY
@@ -78,7 +103,13 @@
 #define DFS_FILESYSTEMS_MAX 4
 #define DFS_FILESYSTEM_TYPES_MAX 4
 #define DFS_FD_MAX 16
+/* RT_USING_DFS_MNTTABLE is not set */
+/* RT_USING_DFS_ELMFAT is not set */
 #define RT_USING_DFS_DEVFS
+/* RT_USING_DFS_ROMFS is not set */
+/* RT_USING_DFS_RAMFS is not set */
+/* RT_USING_DFS_UFFS is not set */
+/* RT_USING_DFS_JFFS2 is not set */
 
 /* Device Drivers */
 
@@ -86,87 +117,215 @@
 #define RT_PIPE_BUFSZ 512
 #define RT_USING_SERIAL
 #define RT_SERIAL_USING_DMA
+/* RT_USING_CAN is not set */
+/* RT_USING_HWTIMER is not set */
+/* RT_USING_CPUTIME is not set */
+/* RT_USING_I2C is not set */
+/* RT_USING_PIN is not set */
+/* RT_USING_ADC is not set */
+/* RT_USING_PWM is not set */
+/* RT_USING_MTD_NOR is not set */
+/* RT_USING_MTD_NAND is not set */
+/* RT_USING_MTD is not set */
+/* RT_USING_PM is not set */
+/* RT_USING_RTC is not set */
+/* RT_USING_SDIO is not set */
+/* RT_USING_SPI is not set */
+/* RT_USING_WDT is not set */
+/* RT_USING_AUDIO is not set */
 
 /* Using WiFi */
 
+/* RT_USING_WIFI is not set */
 
 /* Using USB */
 
+/* RT_USING_USB_HOST is not set */
+/* RT_USING_USB_DEVICE is not set */
 
 /* POSIX layer and C standard library */
 
 #define RT_USING_LIBC
+/* RT_USING_PTHREADS is not set */
 #define RT_USING_POSIX
+/* RT_USING_POSIX_MMAP is not set */
+/* RT_USING_POSIX_TERMIOS is not set */
+/* RT_USING_POSIX_AIO is not set */
+/* RT_USING_MODULE is not set */
 
 /* Network */
 
 /* Socket abstraction layer */
 
+/* RT_USING_SAL is not set */
 
 /* light weight TCP/IP stack */
 
+/* RT_USING_LWIP is not set */
 
 /* Modbus master and slave stack */
 
+/* RT_USING_MODBUS is not set */
 
 /* AT commands */
 
+/* RT_USING_AT is not set */
 
 /* VBUS(Virtual Software BUS) */
 
+/* RT_USING_VBUS is not set */
 
 /* Utilities */
 
+/* RT_USING_LOGTRACE is not set */
+/* RT_USING_RYM is not set */
+/* RT_USING_ULOG is not set */
+/* RT_USING_UTEST is not set */
 
 /* RT-Thread online packages */
 
 /* IoT - internet of things */
 
+/* PKG_USING_PAHOMQTT is not set */
+/* PKG_USING_WEBCLIENT is not set */
+/* PKG_USING_WEBNET is not set */
+/* PKG_USING_MONGOOSE is not set */
+/* PKG_USING_WEBTERMINAL is not set */
+/* PKG_USING_CJSON is not set */
+/* PKG_USING_JSMN is not set */
+/* PKG_USING_LJSON is not set */
+/* PKG_USING_EZXML is not set */
+/* PKG_USING_NANOPB is not set */
 
 /* Wi-Fi */
 
 /* Marvell WiFi */
 
+/* PKG_USING_WLANMARVELL is not set */
 
 /* Wiced WiFi */
 
+/* PKG_USING_WLAN_WICED is not set */
+/* PKG_USING_COAP is not set */
+/* PKG_USING_NOPOLL is not set */
+/* PKG_USING_NETUTILS is not set */
+/* PKG_USING_AT_DEVICE is not set */
+/* PKG_USING_WIZNET is not set */
 
 /* IoT Cloud */
 
+/* PKG_USING_ONENET is not set */
+/* PKG_USING_GAGENT_CLOUD is not set */
+/* PKG_USING_ALI_IOTKIT is not set */
+/* PKG_USING_AZURE is not set */
+/* PKG_USING_TENCENT_IOTKIT is not set */
 
 /* security packages */
 
+/* PKG_USING_MBEDTLS is not set */
+/* PKG_USING_libsodium is not set */
+/* PKG_USING_TINYCRYPT is not set */
 
 /* language packages */
 
+/* PKG_USING_LUA is not set */
+/* PKG_USING_JERRYSCRIPT is not set */
+/* PKG_USING_MICROPYTHON is not set */
 
 /* multimedia packages */
 
+/* PKG_USING_OPENMV is not set */
+/* PKG_USING_MUPDF is not set */
 
 /* tools packages */
 
+/* PKG_USING_CMBACKTRACE is not set */
+/* PKG_USING_EASYFLASH is not set */
+/* PKG_USING_EASYLOGGER is not set */
+/* PKG_USING_SYSTEMVIEW is not set */
+/* PKG_USING_RDB is not set */
+/* PKG_USING_QRCODE is not set */
+/* PKG_USING_ULOG_EASYFLASH is not set */
 
 /* system packages */
 
+/* PKG_USING_GUIENGINE is not set */
+/* PKG_USING_CAIRO is not set */
+/* PKG_USING_PIXMAN is not set */
+/* PKG_USING_LWEXT4 is not set */
+/* PKG_USING_PARTITION is not set */
+/* PKG_USING_FAL is not set */
+/* PKG_USING_SQLITE is not set */
+/* PKG_USING_RTI is not set */
+/* PKG_USING_LITTLEVGL2RTT is not set */
+/* PKG_USING_CMSIS is not set */
+/* PKG_USING_DFS_YAFFS is not set */
+/* PKG_USING_LITTLEFS is not set */
 
 /* peripheral libraries and drivers */
 
+/* PKG_USING_REALTEK_AMEBA is not set */
+/* PKG_USING_SHT2X is not set */
+/* PKG_USING_AHT10 is not set */
+/* PKG_USING_AP3216C is not set */
+/* PKG_USING_STM32_SDIO is not set */
+/* PKG_USING_ICM20608 is not set */
+/* PKG_USING_U8G2 is not set */
+/* PKG_USING_BUTTON is not set */
+/* PKG_USING_MPU6XXX is not set */
+/* PKG_USING_PCF8574 is not set */
 #define PKG_USING_KENDRYTE_SDK
 #define PKG_USING_KENDRYTE_SDK_V052
+/* PKG_USING_KENDRYTE_SDK_LATEST_VERSION is not set */
 
 /* miscellaneous packages */
 
+/* PKG_USING_LIBCSV is not set */
+/* PKG_USING_OPTPARSE is not set */
+/* PKG_USING_FASTLZ is not set */
+/* PKG_USING_MINILZO is not set */
+/* PKG_USING_QUICKLZ is not set */
+/* PKG_USING_MULTIBUTTON is not set */
+/* PKG_USING_CANFESTIVAL is not set */
+/* PKG_USING_ZLIB is not set */
+/* PKG_USING_DSTR is not set */
+/* PKG_USING_TINYFRAME is not set */
+/* PKG_USING_KENDRYTE_DEMO is not set */
 
 /* samples: kernel and components samples */
 
+/* PKG_USING_KERNEL_SAMPLES is not set */
+/* PKG_USING_FILESYSTEM_SAMPLES is not set */
+/* PKG_USING_NETWORK_SAMPLES is not set */
+/* PKG_USING_PERIPHERAL_SAMPLES is not set */
+/* PKG_USING_HELLO is not set */
 
 /* Privated Packages of RealThread */
 
+/* PKG_USING_CODEC is not set */
+/* PKG_USING_PLAYER is not set */
+/* PKG_USING_PERSIMMON_SRC is not set */
+/* PKG_USING_JS_PERSIMMON is not set */
+/* PKG_USING_JERRYSCRIPT_WIN32 is not set */
 
 /* Network Utilities */
 
+/* PKG_USING_WICED is not set */
+/* PKG_USING_CLOUDSDK is not set */
+/* PKG_USING_COREMARK is not set */
+/* PKG_USING_POWER_MANAGER is not set */
+/* PKG_USING_RT_OTA is not set */
+/* PKG_USING_RDBD_SRC is not set */
+/* PKG_USING_RTINSIGHT is not set */
+/* PKG_USING_SMARTCONFIG is not set */
+/* PKG_USING_RTX is not set */
 #define BOARD_K210_EVB
 #define BSP_USING_UART_HS
+/* BSP_USING_UART1 is not set */
+/* BSP_USING_UART2 is not set */
+/* BSP_USING_UART3 is not set */
+/* BSP_USING_I2C1 is not set */
+/* BSP_USING_SPI1 is not set */
 #define __STACKSIZE__ 4096
 
 #endif

+ 2 - 3
bsp/k210/rtconfig.py

@@ -15,7 +15,7 @@ if os.getenv('RTT_CC'):
 
 if  CROSS_TOOL == 'gcc':
     PLATFORM    = 'gcc'
-    EXEC_PATH   = r'/opt/riscv64-unknown-elf-gcc-2018.07.0-x86_64-linux-ubuntu14/bin'
+    EXEC_PATH   = r'/opt/riscv64-unknown-elf/bin'
 else:
     print('Please make sure your toolchains is GNU GCC!')
     exit(0)
@@ -27,8 +27,7 @@ BUILD = 'release'
 
 if PLATFORM == 'gcc':
     # toolchains
-    PREFIX  = 'riscv-none-embed-'
-    # PREFIX  = 'riscv64-unknown-elf-'
+    PREFIX  = 'riscv64-unknown-elf-'
     CC      = PREFIX + 'gcc'
     CXX     = PREFIX + 'g++'
     AS      = PREFIX + 'gcc'

+ 98 - 2
libcpu/risc-v/common/context_gcc.S

@@ -6,10 +6,16 @@
  * Change Logs:
  * Date           Author       Notes
  * 2018/10/28     Bernard      The unify RISC-V porting implementation
+ * 2018/12/27     Jesven       Add SMP support
  */
 
 #include "cpuport.h"
 
+#ifdef RT_USING_SMP
+#define rt_hw_interrupt_disable rt_hw_local_irq_disable
+#define rt_hw_interrupt_enable  rt_hw_local_irq_enable
+#endif
+
 /*
  * rt_base_t rt_hw_interrupt_disable(void);
  */
@@ -27,13 +33,23 @@ rt_hw_interrupt_enable:
     ret
 
 /*
- * void rt_hw_context_switch_to(rt_ubase_t to)
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch_to(rt_ubase_t to, stuct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch_to(rt_ubase_t to);
+ * #endif
  * a0 --> to
+ * a1 --> to_thread
  */
     .globl rt_hw_context_switch_to
 rt_hw_context_switch_to:
     LOAD sp, (a0)
 
+#ifdef RT_USING_SMP
+    mv   a0,   a1
+    jal  rt_cpus_lock_status_restore
+#endif
+
     /* load epc from stack */
     LOAD a0,   0 * REGBYTES(sp)
     csrw mepc, a0
@@ -74,9 +90,15 @@ rt_hw_context_switch_to:
     mret
 
 /*
- * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to)
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch(rt_ubase_t from, rt_ubase_t to);
+ * #endif
+ *
  * a0 --> from
  * a1 --> to
+ * a2 --> to_thread
  */
     .globl rt_hw_context_switch
 rt_hw_context_switch:
@@ -136,6 +158,78 @@ save_mpie:
      */
     LOAD sp,  (a1)
 
+#ifdef RT_USING_SMP
+    mv   a0,   a2
+    jal  rt_cpus_lock_status_restore
+#endif /*RT_USING_SMP*/
+
+    /* resw ra to mepc */
+    LOAD a1,   0 * REGBYTES(sp)
+    csrw mepc, a1
+    LOAD x1,   1 * REGBYTES(sp)
+
+    /* force to machin mode(MPP=11) */
+    li a1, 0x00001800;
+    csrs mstatus, a1
+    LOAD a1,   2 * REGBYTES(sp)
+    csrs mstatus, a1
+
+    LOAD x4,   4 * REGBYTES(sp)
+    LOAD x5,   5 * REGBYTES(sp)
+    LOAD x6,   6 * REGBYTES(sp)
+    LOAD x7,   7 * REGBYTES(sp)
+    LOAD x8,   8 * REGBYTES(sp)
+    LOAD x9,   9 * REGBYTES(sp)
+    LOAD x10, 10 * REGBYTES(sp)
+    LOAD x11, 11 * REGBYTES(sp)
+    LOAD x12, 12 * REGBYTES(sp)
+    LOAD x13, 13 * REGBYTES(sp)
+    LOAD x14, 14 * REGBYTES(sp)
+    LOAD x15, 15 * REGBYTES(sp)
+    LOAD x16, 16 * REGBYTES(sp)
+    LOAD x17, 17 * REGBYTES(sp)
+    LOAD x18, 18 * REGBYTES(sp)
+    LOAD x19, 19 * REGBYTES(sp)
+    LOAD x20, 20 * REGBYTES(sp)
+    LOAD x21, 21 * REGBYTES(sp)
+    LOAD x22, 22 * REGBYTES(sp)
+    LOAD x23, 23 * REGBYTES(sp)
+    LOAD x24, 24 * REGBYTES(sp)
+    LOAD x25, 25 * REGBYTES(sp)
+    LOAD x26, 26 * REGBYTES(sp)
+    LOAD x27, 27 * REGBYTES(sp)
+    LOAD x28, 28 * REGBYTES(sp)
+    LOAD x29, 29 * REGBYTES(sp)
+    LOAD x30, 30 * REGBYTES(sp)
+    LOAD x31, 31 * REGBYTES(sp)
+
+    addi sp,  sp, 32 * REGBYTES
+    mret
+
+#ifdef RT_USING_SMP
+/*
+ * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+ *
+ * a0 --> context
+ * a1 --> from
+ * a2 --> to
+ * a3 --> to_thread
+ */
+    .globl rt_hw_context_switch_interrupt
+rt_hw_context_switch_interrupt:
+
+    STORE a0, 0(a1)
+
+    csrr  a1, mepc
+    STORE a1, 0 * REGBYTES(a0)
+
+    csrr  a1, mstatus
+    STORE a1, 2 * REGBYTES(a0)
+
+    LOAD  sp, 0(a2)
+    move  a0, a3
+    call rt_cpus_lock_status_restore
+
     /* resw ra to mepc */
     LOAD a1,   0 * REGBYTES(sp)
     csrw mepc, a1
@@ -178,3 +272,5 @@ save_mpie:
 
     addi sp,  sp, 32 * REGBYTES
     mret
+
+#endif

+ 24 - 0
libcpu/risc-v/common/cpuport.c

@@ -13,9 +13,11 @@
 
 #include "cpuport.h"
 
+#ifndef RT_USING_SMP
 volatile rt_ubase_t  rt_interrupt_from_thread = 0;
 volatile rt_ubase_t  rt_interrupt_to_thread   = 0;
 volatile rt_uint32_t rt_thread_switch_interrupt_flag = 0;
+#endif
 
 struct rt_hw_stack_frame
 {
@@ -93,6 +95,14 @@ rt_uint8_t *rt_hw_stack_init(void       *tentry,
     return stk;
 }
 
+/*
+ * #ifdef RT_USING_SMP
+ * void rt_hw_context_switch_interrupt(void *context, rt_ubase_t from, rt_ubase_t to, struct rt_thread *to_thread);
+ * #else
+ * void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to);
+ * #endif
+ */
+#ifndef RT_USING_SMP
 void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
 {
     if (rt_thread_switch_interrupt_flag == 0)
@@ -103,3 +113,17 @@ void rt_hw_context_switch_interrupt(rt_ubase_t from, rt_ubase_t to)
 
     return ;
 }
+#endif /* end of RT_USING_SMP */
+
+/** shutdown CPU */
+void rt_hw_cpu_shutdown()
+{
+    rt_uint32_t level;
+    rt_kprintf("shutdown...\n");
+
+    level = rt_hw_interrupt_disable();
+    while (level)
+    {
+        RT_ASSERT(0);
+    }
+}

+ 80 - 0
libcpu/risc-v/k210/cpuport_smp.c

@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018/12/23     Bernard      The first version
+ * 2018/12/27     Jesven       Add secondary cpu boot
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <stdint.h>
+
+#include "board.h"
+#include <encoding.h>
+#include <clint.h>
+#include <atomic.h>
+
+#ifdef RT_USING_SMP
+
+int rt_hw_cpu_id(void)
+{
+    return read_csr(mhartid);
+}
+
+void rt_hw_spin_lock(rt_hw_spinlock_t *lock)
+{
+    spinlock_lock((spinlock_t *)lock);
+}
+
+void rt_hw_spin_unlock(rt_hw_spinlock_t *lock)
+{
+    spinlock_unlock((spinlock_t *)lock);
+}
+
+void rt_hw_ipi_send(int ipi_vector, unsigned int cpu_mask)
+{
+    int idx;
+
+    for (idx = 0; idx < RT_CPUS_NR; idx ++)
+    {
+        if (cpu_mask & (1 << idx))
+        {
+            clint_ipi_send(idx);
+        }
+    }
+}
+
+extern rt_base_t secondary_boot_flag;
+void rt_hw_secondary_cpu_up(void)
+{
+    mb();
+    secondary_boot_flag = 0xa55a;
+}
+
+extern void rt_hw_scondary_interrupt_init(void);
+extern int rt_hw_tick_init(void);
+extern int rt_hw_clint_ipi_enable(void);
+
+void secondary_cpu_c_start(void)
+{
+    rt_hw_spin_lock(&_cpus_lock);
+
+    /* initialize interrupt controller */
+    rt_hw_scondary_interrupt_init();
+
+    rt_hw_tick_init();
+
+    rt_hw_clint_ipi_enable();
+
+    rt_system_scheduler_start();
+}
+
+void rt_hw_secondary_cpu_idle_exec(void)
+{
+    asm volatile ("wfi");
+}
+#endif /*RT_USING_SMP*/

+ 86 - 18
libcpu/risc-v/k210/interrupt.c

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2018/10/01     Bernard      The first version
+ * 2018/12/27     Jesven       Change irq enable/disable to cpu0
  */
 
 #include <rthw.h>
@@ -19,7 +20,7 @@
 #define CPU_NUM         2
 #define MAX_HANDLERS    IRQN_MAX
 
-static struct rt_irq_desc irq_desc[CPU_NUM][MAX_HANDLERS];
+static struct rt_irq_desc irq_desc[MAX_HANDLERS];
 
 static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
 {
@@ -27,6 +28,52 @@ static rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector, void *param)
     return RT_NULL;
 }
 
+int rt_hw_clint_ipi_enable(void)
+{
+    /* Set the Machine-Software bit in MIE */
+    set_csr(mie, MIP_MSIP);
+    return 0;
+}
+
+int rt_hw_clint_ipi_disable(void)
+{
+    /* Clear the Machine-Software bit in MIE */
+    clear_csr(mie, MIP_MSIP);
+    return 0;
+}
+
+int rt_hw_plic_irq_enable(plic_irq_t irq_number)
+{
+    unsigned long core_id = 0;
+
+    /* Check parameters */
+    if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
+        return -1;
+    /* Get current enable bit array by IRQ number */
+    uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
+    /* Set enable bit in enable bit array */
+    current |= (uint32_t)1 << (irq_number % 32);
+    /* Write back the enable bit array */
+    plic->target_enables.target[core_id].enable[irq_number / 32] = current;
+    return 0;
+}
+
+int rt_hw_plic_irq_disable(plic_irq_t irq_number)
+{
+    unsigned long core_id = 0;
+
+    /* Check parameters */
+    if (PLIC_NUM_SOURCES < irq_number || 0 > irq_number)
+        return -1;
+    /* Get current enable bit array by IRQ number */
+    uint32_t current = plic->target_enables.target[core_id].enable[irq_number / 32];
+    /* Clear enable bit in enable bit array */
+    current &= ~((uint32_t)1 << (irq_number % 32));
+    /* Write back the enable bit array */
+    plic->target_enables.target[core_id].enable[irq_number / 32] = current;
+    return 0;
+}
+
 /**
  * This function will initialize hardware interrupt
  */
@@ -52,11 +99,11 @@ void rt_hw_interrupt_init(void)
     for (idx = 0; idx < MAX_HANDLERS; idx++)
     {
         rt_hw_interrupt_mask(idx);
-        irq_desc[cpuid][idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
-        irq_desc[cpuid][idx].param = RT_NULL;
+        irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle;
+        irq_desc[idx].param = RT_NULL;
 #ifdef RT_USING_INTERRUPT_INFO
-        rt_snprintf(irq_desc[cpuid][idx].name, RT_NAME_MAX - 1, "default");
-        irq_desc[idx][cpuid].counter = 0;
+        rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default");
+        irq_desc[idx].counter = 0;
 #endif
     }
 
@@ -64,13 +111,31 @@ void rt_hw_interrupt_init(void)
     set_csr(mie, MIP_MEIP);
 }
 
+void rt_hw_scondary_interrupt_init(void)
+{
+    int idx;
+    int cpuid;
+
+    cpuid = current_coreid();
+
+    /* Disable all interrupts for the current core. */
+    for (idx = 0; idx < ((PLIC_NUM_SOURCES + 32u) / 32u); idx ++)
+        plic->target_enables.target[cpuid].enable[idx] = 0;
+
+    /* Set the threshold to zero. */
+    plic->targets.target[cpuid].priority_threshold = 0;
+
+    /* Enable machine external interrupts. */
+    set_csr(mie, MIP_MEIP);
+}
+
 /**
  * This function will mask a interrupt.
  * @param vector the interrupt number
  */
 void rt_hw_interrupt_mask(int vector)
 {
-    plic_irq_disable(vector);
+    rt_hw_plic_irq_disable(vector);
 }
 
 /**
@@ -80,7 +145,7 @@ void rt_hw_interrupt_mask(int vector)
 void rt_hw_interrupt_umask(int vector)
 {
     plic_set_priority(vector, 1);
-    plic_irq_enable(vector);
+    rt_hw_plic_irq_enable(vector);
 }
 
 /**
@@ -92,21 +157,18 @@ void rt_hw_interrupt_umask(int vector)
 rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
         void *param, const char *name)
 {
-    int cpuid;
     rt_isr_handler_t old_handler = RT_NULL;
 
-    cpuid = current_coreid();
-
     if(vector < MAX_HANDLERS)
     {
-        old_handler = irq_desc[cpuid][vector].handler;
+        old_handler = irq_desc[vector].handler;
         if (handler != RT_NULL)
         {
-            irq_desc[cpuid][vector].handler = (rt_isr_handler_t)handler;
-            irq_desc[cpuid][vector].param = param;
+            irq_desc[vector].handler = (rt_isr_handler_t)handler;
+            irq_desc[vector].param = param;
 #ifdef RT_USING_INTERRUPT_INFO
-            rt_snprintf(irq_desc[cpuid][vector].name, RT_NAME_MAX - 1, "%s", name);
-            irq_desc[cpuid][vector].counter = 0;
+            rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name);
+            irq_desc[vector].counter = 0;
 #endif
         }
     }
@@ -149,14 +211,14 @@ uintptr_t handle_irq_m_ext(uintptr_t cause, uintptr_t epc)
         /* Disable software interrupt and timer interrupt */
         clear_csr(mie, MIP_MTIP | MIP_MSIP);
 
-        if (irq_desc[core_id][int_num].handler == (rt_isr_handler_t)rt_hw_interrupt_handle)
+        if (irq_desc[int_num].handler == (rt_isr_handler_t)rt_hw_interrupt_handle)
         {
             /* default handler, route to kendryte bsp plic driver */
             plic_irq_handle(int_num);
         }
-        else if (irq_desc[core_id][int_num].handler)
+        else if (irq_desc[int_num].handler)
         {
-            irq_desc[core_id][int_num].handler(int_num, irq_desc[core_id][int_num].param);
+            irq_desc[int_num].handler(int_num, irq_desc[int_num].param);
         }
 
         /* Perform IRQ complete */
@@ -185,6 +247,12 @@ uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc)
         switch (cause)
         {
             case IRQ_M_SOFT:
+                {
+                    uint64_t core_id = current_coreid();
+
+                    clint_ipi_clear(core_id);
+                    rt_schedule();
+                }
                 break;
             case IRQ_M_EXT:
                 handle_irq_m_ext(mcause, epc);

+ 9 - 0
libcpu/risc-v/k210/interrupt_gcc.S

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2018/10/02     Bernard      The first version
+ * 2018/12/27     Jesven       Add SMP schedule
  */
 
 #include "cpuport.h"
@@ -72,6 +73,13 @@ trap_entry:
     call  handle_trap
     call  rt_interrupt_leave
 
+#ifdef RT_USING_SMP
+    /* s0 --> sp */
+    mv  a0, s0
+    call rt_scheduler_do_irq_switch
+    mv  sp, s0
+#else
+
     /* switch to from_thread stack */
     move  sp, s0
 
@@ -94,6 +102,7 @@ trap_entry:
 
     LOAD  a0,  0 * REGBYTES(sp)
     csrw  mepc, a0
+#endif
 
 spurious_interrupt:
     LOAD  x1,   1 * REGBYTES(sp)

+ 17 - 14
libcpu/risc-v/k210/startup_gcc.S

@@ -6,6 +6,7 @@
  * Change Logs:
  * Date           Author       Notes
  * 2018/10/01     Bernard      The first version
+ * 2018/12/27     Jesven       Add SMP support
  */
 
 #define MSTATUS_FS      0x00006000U /* initial state of FPU     */
@@ -114,20 +115,22 @@ _start:
   add  sp, sp, t1 /* sp = (cpuid + 1) * __STACKSIZE__ + __stack_start__ */
 
   /* other cpu core, jump to cpu entry directly */
-  bnez a0, _cpu_entry
+  bnez a0, secondary_cpu_entry
+  j primary_cpu_entry
 
-#if 0
-  /* clear bss section */
-  la a0, __bss_start
-  la a1, __bss_end
-  bgeu a0, a1, 2f
-1:
-  sw zero, (a0)
-  addi a0, a0, REGBYTES
-  bltu a0, a1, 1b
-2:
+secondary_cpu_entry:
+#ifdef RT_USING_SMP
+  la a0, secondary_boot_flag
+  ld a0, 0(a0)
+  li a1, 0xa55a
+  beq a0, a1, secondary_cpu_c_start
 #endif
+  j secondary_cpu_entry
 
-_cpu_entry:
-  csrr a0, mhartid
-  j cpu_entry
+#ifdef RT_USING_SMP
+.data
+.global secondary_boot_flag
+.align 3
+secondary_boot_flag:
+    .dword 0
+#endif