diff --git a/.vscode/settings.json b/.vscode/settings.json index 29e621ee7..06ad18f96 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -129,7 +129,10 @@ "pthread.h": "c", "*.in": "cpp", "syscall_backend.h": "c", - "misc_backend.h": "c" + "misc_backend.h": "c", + "queue.h": "c", + "irq.h": "c", + "irq_sender.h": "c" }, "cortex-debug.showRTOS": false, } \ No newline at end of file diff --git a/mkrtos_knl/arch/armv7m/arch.c b/mkrtos_knl/arch/armv7m/arch.c index 1e7f368a7..25efc193e 100644 --- a/mkrtos_knl/arch/armv7m/arch.c +++ b/mkrtos_knl/arch/armv7m/arch.c @@ -15,6 +15,7 @@ #include "thread.h" #include "stm32f2xx_conf.h" #include "mpu.h" +#include "core_cm3.h" __ALIGN__(THREAD_BLOCK_SIZE) static uint8_t thread_knl_stack[THREAD_BLOCK_SIZE] = {0}; void *_estack = thread_knl_stack + THREAD_BLOCK_SIZE; @@ -38,6 +39,16 @@ void sys_startup(void) // 初始化systick时钟 SysTick_Config(SystemCoreClock / SYS_SCHE_HZ); } + +void arch_disable_irq(int inx) +{ + NVIC_DisableIRQ(inx); +} +void arch_enable_irq(int inx) +{ + NVIC_EnableIRQ(inx); +} + void arch_init(void) { SystemInit(); diff --git a/mkrtos_knl/arch/inc/arch.h b/mkrtos_knl/arch/inc/arch.h index 87c8c5b25..c209a4a19 100755 --- a/mkrtos_knl/arch/inc/arch.h +++ b/mkrtos_knl/arch/inc/arch.h @@ -44,6 +44,16 @@ static inline umword_t arch_get_sp(void) :); return ret; } +static inline umword_t arch_get_isr_no(void) +{ + umword_t num; + __asm__ __volatile__( + "mrs %0,IPSR" + : "=r"(num) + : + :); + return num; +} static inline void arch_set_knl_sp(umword_t sp) { write_sysreg(sp, msp); @@ -60,6 +70,9 @@ static inline umword_t arch_get_user_sp(void) { return read_sysreg(psp); } +void arch_disable_irq(int inx); +void arch_enable_irq(int inx); + #define sti() \ do \ { \ diff --git a/mkrtos_knl/drivers/uart/stm32f2_uart.c b/mkrtos_knl/drivers/uart/stm32f2_uart.c index e4dd80eaf..2398092dd 100755 --- a/mkrtos_knl/drivers/uart/stm32f2_uart.c +++ b/mkrtos_knl/drivers/uart/stm32f2_uart.c @@ -3,6 +3,8 @@ #include "types.h" #include "uart/uart.h" #include "init.h" +#include "queue.h" +#include #define CR3_CLEAR_MASK ((uint16_t)(USART_CR3_RTSE | USART_CR3_CTSE)) static void uart_set_word_len(USART_TypeDef *USARTx, uint16_t len) @@ -124,15 +126,35 @@ static void uart_hardware_flow_rts(USART_TypeDef *USARTx, uint16_t flow) } static uart_t uart = { .baud = 115200}; + uart_t *uart_get_global(void) { return &uart; } +#define QUEUE_LEN 129 +static queue_t queue; +static uint8_t queue_data[QUEUE_LEN]; +void uart_tigger(irq_entry_t *irq) +{ + if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) + { + // 清除中断标志位 + USART_ClearITPendingBit(USART1, USART_IT_RXNE); + q_enqueue(&queue, USART_ReceiveData(USART1)); + + if (irq->irq->wait_thread && thread_get_status(irq->irq->wait_thread) == THREAD_SUSPEND) + { + thread_ready(irq->irq->wait_thread, TRUE); + } + } +} + void uart_init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; + q_init(&queue, queue_data, QUEUE_LEN); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); @@ -167,6 +189,7 @@ void uart_init(void) USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); + USART_Cmd(USART1, ENABLE); } INIT_HIGH_HAD(uart_init); @@ -186,5 +209,19 @@ void uart_putc(uart_t *uart, int data) } int uart_getc(uart_t *uart) { + uint8_t e; + umword_t status; + + status = cpulock_lock(); + if (q_dequeue(&queue, &e) >= 0) + { + cpulock_set(status); + return e; + } + cpulock_set(status); return -1; } +int uart_get_len(uart_t *uart) +{ + return q_queue_len(&queue); +} diff --git a/mkrtos_knl/inc/drv/uart/uart.h b/mkrtos_knl/inc/drv/uart/uart.h index f93f789ad..2f3a5fcca 100755 --- a/mkrtos_knl/inc/drv/uart/uart.h +++ b/mkrtos_knl/inc/drv/uart/uart.h @@ -2,6 +2,7 @@ #pragma once #include "types.h" +#include "irq.h" typedef struct uart { @@ -15,4 +16,5 @@ typedef struct uart uart_t *uart_get_global(void); void uart_set(uart_t *uart); void uart_putc(uart_t *uart, int data); -int uart_getc(uart_t *uart); \ No newline at end of file +int uart_getc(uart_t *uart); +void uart_tigger(irq_entry_t *irq); \ No newline at end of file diff --git a/mkrtos_knl/inc/knl/irq.h b/mkrtos_knl/inc/knl/irq.h index e69de29bb..6c5f15123 100755 --- a/mkrtos_knl/inc/knl/irq.h +++ b/mkrtos_knl/inc/knl/irq.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#define IRQ_INVALID_NO ((umword_t)(-1)) +#define IRQ_REG_TAB_SIZE 80 +#define USER_ISR_START_NO 16 + +bool_t irq_check_usability(int inx); +void irq_alloc(int inx, irq_sender_t *irq, void (*irq_tigger_func)(irq_entry_t *irq)); +void irq_free(int inx); +irq_entry_t *irq_get(int inx); diff --git a/mkrtos_knl/inc/knl/irq_sender.h b/mkrtos_knl/inc/knl/irq_sender.h new file mode 100644 index 000000000..ccfa8faf9 --- /dev/null +++ b/mkrtos_knl/inc/knl/irq_sender.h @@ -0,0 +1,28 @@ +#pragma once + +#include "types.h" +#include +#include +#include +struct irq_sender; +typedef struct irq_sender irq_sender_t; +struct irq_entry; +typedef struct irq_entry irq_entry_t; + +typedef struct irq_entry +{ + irq_sender_t *irq; + void (*irq_tigger_func)(irq_entry_t *irq); +} irq_entry_t; + +typedef struct irq_sender +{ + kobject_t kobj; + umword_t irq_id; //!< 绑定的中断号 + ref_counter_t ref; + thread_t *wait_thread; //!< 等待中断的线程 +} irq_sender_t; + +void irq_sender_init(irq_sender_t *irq); +int irq_sender_wait(irq_sender_t *irq, thread_t *th); +void irq_sender_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f); diff --git a/mkrtos_knl/inc/knl/log.h b/mkrtos_knl/inc/knl/log.h index fd12a7cd7..7f7d72cd7 100755 --- a/mkrtos_knl/inc/knl/log.h +++ b/mkrtos_knl/inc/knl/log.h @@ -11,7 +11,4 @@ #include "types.h" #include "kobject.h" -typedef struct log -{ - kobject_t kobj; -} log_t; + diff --git a/mkrtos_knl/inc/knl/printk.h b/mkrtos_knl/inc/knl/printk.h index d7a45feee..6aa6438e9 100755 --- a/mkrtos_knl/inc/knl/printk.h +++ b/mkrtos_knl/inc/knl/printk.h @@ -1,14 +1,17 @@ -/* - * @Author: zhangzheng 1358745329@qq.com - * @Date: 2023-08-14 09:47:54 - * @LastEditors: zhangzheng 1358745329@qq.com - * @LastEditTime: 2023-08-14 13:06:46 - * @FilePath: /mkrtos-real/mkrtos_knl/inc/knl/printk.h - * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE +/** + * @file printk.h + * @author zhagnzheng (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-14 + * + * @copyright Copyright (c) 2023 + * */ #pragma once #include "types.h" void putc(int c); +int getc(void); void printk(const char *fmt, ...); diff --git a/mkrtos_knl/inc/knl/prot.h b/mkrtos_knl/inc/knl/prot.h index d1481c984..bf9b9253d 100755 --- a/mkrtos_knl/inc/knl/prot.h +++ b/mkrtos_knl/inc/knl/prot.h @@ -18,9 +18,10 @@ #define IPC_PROT 5 #define MM_PROT 6 #define SYS_PROT 7 +#define IRQ_PROT 8 #define FACTORY_PORT_START FACTORY_PROT -#define FACTORY_FUNC_MAX (SYS_PROT + 1) +#define FACTORY_FUNC_MAX (IRQ_PROT + 1) #define FACTORY_PORT_END FACTORY_FUNC_MAX typedef struct msg_tag diff --git a/mkrtos_knl/inc/knl/thread.h b/mkrtos_knl/inc/knl/thread.h index 5c3314dec..ea898dc1c 100755 --- a/mkrtos_knl/inc/knl/thread.h +++ b/mkrtos_knl/inc/knl/thread.h @@ -1,10 +1,12 @@ -/* - * @Author: zhangzheng 1358745329@qq.com - * @Date: 2023-08-14 09:47:54 - * @LastEditors: zhangzheng 1358745329@qq.com - * @LastEditTime: 2023-08-18 16:21:48 - * @FilePath: /mkrtos-real/mkrtos_knl/inc/knl/thread.h - * @Description: 线程管理相关 +/** + * @file thread.h + * @author zhangzheng (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-14 + * + * @copyright Copyright (c) 2023 + * */ #pragma once diff --git a/mkrtos_knl/inc/lib/queue.h b/mkrtos_knl/inc/lib/queue.h new file mode 100644 index 000000000..cdd3fb3b2 --- /dev/null +++ b/mkrtos_knl/inc/lib/queue.h @@ -0,0 +1,17 @@ +#pragma once + +#include "types.h" + +typedef struct queue +{ + uint8_t *m; + int front; + int rear; + int size; +} queue_t; + +void q_init(queue_t *q, uint8_t *data, int size); +int q_empty(queue_t *q); +int q_enqueue(queue_t *q, uint8_t e); +int q_dequeue(queue_t *q, uint8_t *e); +int q_queue_len(queue_t *q); diff --git a/mkrtos_knl/knl/CMakeLists.txt b/mkrtos_knl/knl/CMakeLists.txt index c83db9a37..8ad5cac18 100755 --- a/mkrtos_knl/knl/CMakeLists.txt +++ b/mkrtos_knl/knl/CMakeLists.txt @@ -10,4 +10,5 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc + ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv ) diff --git a/mkrtos_knl/knl/globals.c b/mkrtos_knl/knl/globals.c index 43cd79b33..9f83114f6 100755 --- a/mkrtos_knl/knl/globals.c +++ b/mkrtos_knl/knl/globals.c @@ -15,7 +15,7 @@ #include "mm_man.h" #include "ipc.h" static mem_t global_mem; //!< 全局内存管理块 -static uint8_t mem_block[960 * 1024]; //!< 内核内存分配堆 +static uint8_t mem_block[960 * 1024]; //!< 内核内存分配堆 TODO:自动识别大小,或者从bootstrap中读取 static kobject_t *kobj_ls[FACTORY_FUNC_MAX]; //!< 全局静态内核对象 void global_reg_kobj(kobject_t *kobj, int inx) @@ -42,7 +42,6 @@ static void mem_sys_init(void) log_dump(); mm_man_dump(); sys_dump(); - // ipc_dump(); mem_init(&global_mem); mem_heap_add(mm_get_global(), mem_block, sizeof(mem_block)); } diff --git a/mkrtos_knl/knl/ipc.c b/mkrtos_knl/knl/ipc.c index 5002a19e4..ee3c4d1ca 100755 --- a/mkrtos_knl/knl/ipc.c +++ b/mkrtos_knl/knl/ipc.c @@ -28,7 +28,7 @@ typedef struct ipc_wait_item typedef struct ipc { kobject_t kobj; //!< 内核对象 - spinlock_t lock; //!< 操作的锁TODO: 使用内核对象锁 + spinlock_t lock; //!< 操作的锁 TODO: 使用内核对象锁 slist_head_t wait_send; //!< 发送等待队列 slist_head_t recv_send; //!< 发送等待队列 slist_head_t node; //!< 超时检查链表 @@ -40,11 +40,11 @@ typedef struct ipc enum ipc_op { - IPC_CALL, //!< 客户端CALL操作 - IPC_WAIT, //!< 服务端等待接收信息 - IPC_REPLY, //!< 服务端回复信息 - IPC_BIND, //!< 绑定服务端线程 - IPC_UNBIND, //!< 解除绑定 + IPC_CALL, //!< 客户端CALL操作 + IPC_WAIT, //!< 服务端等待接收信息 + IPC_REPLY, //!< 服务端回复信息 + IPC_BIND, //!< 绑定服务端线程 + IPC_UNBIND, //!< 解除绑定 }; static void wake_up_th(ipc_t *ipc); static slist_head_t wait_list; diff --git a/mkrtos_knl/knl/irq.c b/mkrtos_knl/knl/irq.c index 6663f51dd..f3f1bb195 100755 --- a/mkrtos_knl/knl/irq.c +++ b/mkrtos_knl/knl/irq.c @@ -1,4 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*TODO:换成更节省内存的方式*/ +static irq_entry_t irqs[IRQ_REG_TAB_SIZE] = {0}; +static void irq_tigger(irq_entry_t *irq); + +bool_t irq_check_usability(int inx) +{ + if (inx >= IRQ_REG_TAB_SIZE) + { + return FALSE; + } + return irqs[inx].irq_tigger_func == NULL; +} +void irq_alloc(int inx, irq_sender_t *irq, void (*irq_tigger_func)(irq_entry_t *irq)) +{ + assert(irqs[inx].irq_tigger_func == NULL); + irqs[inx].irq = irq; + irqs[inx].irq_tigger_func = irq_tigger_func; +} +void irq_free(int inx) +{ + assert(inx < IRQ_REG_TAB_SIZE); + irqs[inx].irq_tigger_func = NULL; +} +irq_entry_t *irq_get(int inx) +{ + assert(inx < IRQ_REG_TAB_SIZE); + return &irqs[inx]; +} +/** + * @brief 中断的入口函数 + * + */ void entry_handler(void) { + umword_t isr_no = arch_get_isr_no(); + + isr_no -= USER_ISR_START_NO; + + if (!irq_check_usability(isr_no)) + { + if (irqs[isr_no].irq_tigger_func) + { + irqs[isr_no].irq_tigger_func(&irqs[isr_no]); + } + } } diff --git a/mkrtos_knl/knl/irq_sender.c b/mkrtos_knl/knl/irq_sender.c new file mode 100644 index 000000000..fc6a6f27c --- /dev/null +++ b/mkrtos_knl/knl/irq_sender.c @@ -0,0 +1,150 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum irq_sender_op +{ + BIND_IRQ, //!< 绑定一个中断号 + UNBIND_IRQ, //!< 解除绑定 + WAIT_IRQ, //!< 等待中断触发 + ACK_IRQ, //!< 中断确认 +}; +/** + * @brief irq_sender的默认中断触发函数 + * + * @param irq + */ +static void irq_tigger(irq_entry_t *irq) +{ + if (irq->irq->wait_thread && thread_get_status(irq->irq->wait_thread) == THREAD_SUSPEND) + { + arch_disable_irq(irq->irq->irq_id); + thread_ready(irq->irq->wait_thread, TRUE); + } +} +int irq_sender_wait(irq_sender_t *irq, thread_t *th) +{ + // TODO:临界保护 + if (!irq->wait_thread) + { + irq->wait_thread = th; + ref_counter_inc(&irq->wait_thread->ref); //! 线程引用计数+1 + thread_suspend(irq->wait_thread); + ref_counter_dec(&irq->wait_thread->ref); //! 线程引用计数+1 + irq->wait_thread = NULL; + return 0; + } + else + { + return -EACCES; + } +} +void irq_sender_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f) +{ + assert(kobj); + assert(f); + msg_tag_t tag = msg_tag_init4(0, 0, 0, -EINVAL); + thread_t *th = thread_get_current(); + irq_sender_t *irq = container_of(kobj, irq_sender_t, kobj); + + if (sys_p.prot != IPC_PROT) + { + f->r[0] = msg_tag_init4(0, 0, 0, -EPROTO).raw; + return; + } + switch (sys_p.op) + { + case BIND_IRQ: + { + umword_t irq_no = f->r[1]; + if (irq_check_usability(irq_no)) + { + irq->irq_id = irq_no; + irq_alloc(irq_no, irq, irq_tigger); + ref_counter_inc(&irq->ref); + tag = msg_tag_init4(0, 0, 0, 0); + } + else + { + tag = msg_tag_init4(0, 0, 0, -EACCES); + } + } + break; + case UNBIND_IRQ: + { + umword_t irq_no = f->r[1]; + if (!irq_check_usability(irq_no) && irq_get(irq_no)->irq == irq) + { + irq_free(irq_no); + ref_counter_dec(&irq->ref); + tag = msg_tag_init4(0, 0, 0, 0); + } + else + { + tag = msg_tag_init4(0, 0, 0, -EACCES); + } + } + break; + case WAIT_IRQ: + { + int ret = irq_sender_wait(irq, th); + msg_tag_init4(0, 0, 0, ret); + } + break; + case ACK_IRQ: + { + arch_enable_irq(irq->irq_id); + } + break; + default: + break; + } + f->r[0] = tag.raw; +} +void irq_sender_init(irq_sender_t *irq) +{ + kobject_init(&irq->kobj); + ref_counter_init(&irq->ref); + ref_counter_inc(&irq->ref); + irq->kobj.invoke_func = irq_sender_syscall; + irq->irq_id = IRQ_INVALID_NO; +} +static irq_sender_t *irq_create(ram_limit_t *lim) +{ + irq_sender_t *irq = mm_limit_alloc(lim, sizeof(irq_sender_t)); + + if (!irq) + { + return NULL; + } + irq_sender_init(irq); + return irq; +} +static kobject_t *irq_create_func(ram_limit_t *lim, umword_t arg0, umword_t arg1, + umword_t arg2, umword_t arg3) +{ + irq_sender_t *irq = irq_create(lim); + + if (!irq) + { + return NULL; + } + return &irq->kobj; +} + +/** + * @brief 工厂注册函数 + * + */ +static void irq_factory_register(void) +{ + factory_register(irq_create_func, IRQ_PROT); +} +INIT_KOBJ(irq_factory_register); diff --git a/mkrtos_knl/knl/log.c b/mkrtos_knl/knl/log.c index 4ccf9b95b..e60d0ce04 100755 --- a/mkrtos_knl/knl/log.c +++ b/mkrtos_knl/knl/log.c @@ -1,10 +1,12 @@ -/* - * @Author: zhangzheng 1358745329@qq.com - * @Date: 2023-08-14 09:47:54 - * @LastEditors: zhangzheng 1358745329@qq.com - * @LastEditTime: 2023-08-14 13:10:35 - * @FilePath: /mkrtos-real/mkrtos_knl/knl/log.c - * @Description: 内核的信息输出对象,用户态使用该对象进行数据输出。 +/** + * @file log.c + * @author zhangzheng (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-14 + * + * @copyright Copyright (c) 2023 + * */ #include "log.h" @@ -15,6 +17,12 @@ #include "printk.h" #include "types.h" #include "util.h" +#include "irq_sender.h" +#include "uart/uart.h" +typedef struct log +{ + irq_sender_t kobj; +} log_t; static log_t log; enum log_op @@ -25,11 +33,18 @@ enum log_op }; static void log_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f); +static void log_trigger(irq_entry_t *irq) +{ + uart_tigger(irq); +} + static void log_reg(void) { - kobject_init(&log.kobj); - log.kobj.invoke_func = log_syscall; - global_reg_kobj(&log.kobj, LOG_PROT); + // kobject_init(&log.kobj); + irq_sender_init(&log.kobj); + log.kobj.kobj.invoke_func = log_syscall; + global_reg_kobj(&log.kobj.kobj, LOG_PROT); + irq_alloc(37 /*USART1_IRQn*/, &log.kobj, log_trigger); } INIT_KOBJ(log_reg); static msg_tag_t log_write_data(log_t *log, const char *data, int len) @@ -40,33 +55,68 @@ static msg_tag_t log_write_data(log_t *log, const char *data, int len) } return msg_tag_init(0); } +static int log_read_data(log_t *log, uint8_t *data, int len) +{ + for (int i = 0; i < len; i++) + { + again:; + int c = getc(); + + if (c < 0 && i == 0) + { + int ret = irq_sender_wait(&log->kobj, thread_get_current()); + if (ret < 0) + { + return ret; + } + goto again; + } + else if (c < 0) + { + return i; + } + data[i] = (uint8_t)c; + } + return len; +} static void log_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_tag, entry_frame_t *f) { msg_tag_t tag = msg_tag_init4(0, 0, 0, -EINVAL); - if (sys_p.prot != LOG_PROT) + if (sys_p.prot == LOG_PROT) + { + + switch (sys_p.op) + { + case WRITE_DATA: + tag = log_write_data( + (log_t *)kobj, (const char *)(&f->r[1]), + MIN(in_tag.msg_buf_len * WORD_BYTES, WORD_BYTES * 5)); + break; + case READ_DATA: + { + int ret = log_read_data((log_t *)kobj, (uint8_t *)(&f->r[1]), MIN(f->r[1], WORD_BYTES * 5)); + tag = msg_tag_init4(0, 0, 0, ret); + } + break; + case SET_FLAGS: + printk("don't support set flags.\n"); + break; + default: + tag = msg_tag_init4(0, 0, 0, -ENOSYS); + break; + } + f->r[0] = tag.raw; + } + else if (sys_p.prot == IRQ_PROT) + { + irq_sender_syscall(kobj, sys_p, in_tag, f); + } + else { f->r[0] = msg_tag_init4(0, 0, 0, -EPROTO).raw; return; } - switch (sys_p.op) - { - case WRITE_DATA: - tag = log_write_data( - (log_t *)kobj, (const char *)(&f->r[1]), - MIN(in_tag.msg_buf_len * WORD_BYTES, WORD_BYTES * 5)); - break; - case READ_DATA: - printk("don't support read data.\n"); - break; - case SET_FLAGS: - printk("don't support set flags.\n"); - break; - default: - tag = msg_tag_init4(0, 0, 0, -ENOSYS); - break; - } - f->r[0] = tag.raw; return; } diff --git a/mkrtos_knl/knl/printk.c b/mkrtos_knl/knl/printk.c index 1ff91dca3..0329dca25 100755 --- a/mkrtos_knl/knl/printk.c +++ b/mkrtos_knl/knl/printk.c @@ -1,15 +1,18 @@ -/* - * @Author: zhangzheng 1358745329@qq.com - * @Date: 2023-08-14 09:47:54 - * @LastEditors: zhangzheng 1358745329@qq.com - * @LastEditTime: 2023-08-14 13:11:18 - * @FilePath: /mkrtos-real/mkrtos_knl/knl/printk.c - * @Description: 内核信息输出,内核内使用 +/** + * @file printk.c + * @author zhangzheng (1358745329@qq.com) + * @brief + * @version 0.1 + * @date 2023-09-14 + * + * @copyright Copyright (c) 2023 + * */ #include "printk.h" #include "stdarg.h" #include "xprintf.h" #include "spinlock.h" +#include "uart/uart.h" static spinlock_t lock; static char print_cache[128]; @@ -35,6 +38,10 @@ void putc(int c) { xputc(c); } +int getc(void) +{ + return uart_getc(uart_get_global()); +} /** * @brief 输出数据 * diff --git a/mkrtos_knl/knl/syscall.c b/mkrtos_knl/knl/syscall.c index b13728583..d5f0a90a0 100644 --- a/mkrtos_knl/knl/syscall.c +++ b/mkrtos_knl/knl/syscall.c @@ -37,7 +37,7 @@ end:; addr_t u_sp = arch_get_user_sp(); pf_s_t *pf_a = (pf_s_t *)u_sp; - // pf_a->rg0[0] = tag.raw; + pf_a->rg0[0] = entry.r[0]; pf_a->rg0[1] = entry.r[1]; pf_a->rg0[2] = entry.r[2]; pf_a->rg0[3] = entry.r[3]; diff --git a/mkrtos_knl/knl/thread.c b/mkrtos_knl/knl/thread.c index c6d8b8429..5b12abd5e 100755 --- a/mkrtos_knl/knl/thread.c +++ b/mkrtos_knl/knl/thread.c @@ -213,6 +213,7 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t stack_bottom = (umword_t)(cur_th->msg.msg); } thread_set_exc_regs(tag_th, f->r[1], f->r[2], f->r[3], stack_bottom); + tag = msg_tag_init4(0, 0, 0, 0); } break; case MSG_BUG_SET: @@ -242,6 +243,7 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t tag_th->sche.prio = (f->r[1] >= PRIO_MAX ? PRIO_MAX - 1 : f->r[1]); thread_ready(tag_th, TRUE); } + tag = msg_tag_init4(0, 0, 0, 0); } break; case BIND_TASK: @@ -253,6 +255,7 @@ static void thread_syscall(kobject_t *kobj, syscall_prot_t sys_p, msg_tag_t in_t return; } thread_bind(tag_th, task_kobj); + tag = msg_tag_init4(0, 0, 0, 0); printk("thread bind to %d\n", f->r[7], f->r[1]); } break; diff --git a/mkrtos_knl/lib/CMakeLists.txt b/mkrtos_knl/lib/CMakeLists.txt index b7a585476..357f03f40 100755 --- a/mkrtos_knl/lib/CMakeLists.txt +++ b/mkrtos_knl/lib/CMakeLists.txt @@ -9,4 +9,6 @@ target_include_directories( ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/lib ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/knl ${CMAKE_SOURCE_DIR}/mkrtos_knl/inc/drv + + ${CMAKE_SOURCE_DIR}/mkrtos_knl/arch/inc ) diff --git a/mkrtos_knl/lib/queue.c b/mkrtos_knl/lib/queue.c new file mode 100644 index 000000000..dadf16168 --- /dev/null +++ b/mkrtos_knl/lib/queue.c @@ -0,0 +1,47 @@ +#include "types.h" +#include "queue.h" +#include + +void q_init(queue_t *q, uint8_t *data, int size) +{ + q->front = 0; + q->rear = 0; + q->m = data; + q->size = size; +} +int q_empty(queue_t *q) +{ + assert(q); + if (q->front == q->rear) + { + return 1; + } + else + { + return 0; + } +} +int q_enqueue(queue_t *q, uint8_t e) +{ + if (((q->rear + 1) % q->size) == q->front) + { + return -1; + } + q->m[q->rear] = e; + q->rear = (q->rear + 1) % q->size; + return 0; +} +int q_dequeue(queue_t *q, uint8_t *e) +{ + if (q->front == q->rear) + { + return -1; + } + *e = q->m[q->front]; + q->front = (q->front + 1) % q->size; + return 0; +} +int q_queue_len(queue_t *q) +{ + return (q->rear - q->front + q->size) % q->size; +} \ No newline at end of file diff --git a/mkrtos_user/lib/libc_backend/inc/syscall_backend.h b/mkrtos_user/lib/libc_backend/inc/syscall_backend.h index e53319142..fb38f2aea 100644 --- a/mkrtos_user/lib/libc_backend/inc/syscall_backend.h +++ b/mkrtos_user/lib/libc_backend/inc/syscall_backend.h @@ -38,3 +38,4 @@ long syscall_backend(long sys_inx, ...); umword_t be_mmap2(va_list ap); +umword_t be_munmap(va_list ap); diff --git a/mkrtos_user/lib/libc_backend/src/mm_backend.c b/mkrtos_user/lib/libc_backend/src/mm_backend.c index 51373cf20..fdda35a25 100644 --- a/mkrtos_user/lib/libc_backend/src/mm_backend.c +++ b/mkrtos_user/lib/libc_backend/src/mm_backend.c @@ -4,21 +4,27 @@ #include "u_ipc.h" #include "u_mm.h" #include "u_app.h" +#include "u_log.h" #include +#include +static pthread_spinlock_t lock; extern void *app_start_addr; -// extern char __heap_start__[]; -extern umword_t __heap_size__; -// extern void *_start_; static umword_t mm_bitemp[32 /*TODO:自动分配,或者静态划分*/]; -// extern char heap[]; -static void *mm_page_alloc(void) +static void *mm_page_alloc(int page_nr) { - // pthread_spin_lock(&lock); + int cnt = 0; + mword_t find_inx = -1; app_info_t *info = app_info_get(app_start_addr); + assert(info); void *heap_addr = RAM_BASE() + info->i.heap_offset - info->i.data_offset; - size_t max_page_nr = (info->i.heap_size) / 512; - printf("heap is 0x%x, max page nr is %d.\n", heap_addr, max_page_nr); - for (umword_t i = 0; i < max_page_nr; i++) + size_t max_page_nr = (info->i.heap_size) / PAGE_SIZE; + if (max_page_nr > sizeof(mm_bitemp) * WORD_BITS) + { + ulog_write_str(LOG_PROT, "mm bitmap is to small.\n"); + } + // printf("heap is 0x%x, max page nr is %d.\n", heap_addr, max_page_nr); + pthread_spin_lock(&lock); + for (umword_t i = 0; i < ROUND_UP(max_page_nr, WORD_BITS); i++) { if (mm_bitemp[i] != (umword_t)(-1)) { @@ -27,19 +33,56 @@ static void *mm_page_alloc(void) if (MK_GET_BIT(mm_bitemp[i], j) == 0) { // 找到空闲的 - umword_t find_inx = i * WORD_BITS + j; - MK_SET_BIT(mm_bitemp[i], j); - // pthread_spin_unlock(&lock); - return find_inx * PAGE_SIZE + (char *)heap_addr; + if (find_inx == -1) + { + find_inx = i * WORD_BITS + j; + } + cnt++; + if (find_inx + cnt >= max_page_nr) + { + pthread_spin_unlock(&lock); + return NULL; + } + if (cnt >= page_nr) + { + for (int m = find_inx; m < find_inx + cnt; m++) + { + + MK_SET_BIT(mm_bitemp[m / WORD_BITS], m % WORD_BITS); + } + pthread_spin_unlock(&lock); + printf("st_inx:%d, cnt:%d\n", find_inx, cnt); + return find_inx * PAGE_SIZE + (char *)heap_addr; + } + } + else + { + cnt = 0; + find_inx = -1; } } } } - // pthread_spin_unlock(&lock); + pthread_spin_unlock(&lock); return NULL; } +static void mm_page_free(int st, int nr) +{ + app_info_t *info = app_info_get(app_start_addr); + assert(info); + void *heap_addr = RAM_BASE() + info->i.heap_offset - info->i.data_offset; + size_t max_page_nr = (info->i.heap_size) / PAGE_SIZE; + + pthread_spin_lock(&lock); + for (int i = st; (i < st + nr) && (i < max_page_nr); i++) + { + MK_CLR_BIT(mm_bitemp[i / WORD_BITS], i % WORD_BITS); + } + pthread_spin_unlock(&lock); +} + static int sys_mmap2(void *start, size_t len, int prot, int flags, int fd, off_t _offset, umword_t *addr) { if (fd >= 0) @@ -47,7 +90,7 @@ static int sys_mmap2(void *start, size_t len, int prot, int flags, int fd, off_t return -ENOSYS; } len = ALIGN(len, PAGE_SIZE); - *addr = (umword_t)mm_page_alloc(); + *addr = (umword_t)mm_page_alloc(len / PAGE_SIZE); return 0; } @@ -72,3 +115,18 @@ umword_t be_mmap2(va_list ap) } return addr; } +umword_t be_munmap(va_list ap) +{ + void *start; + size_t len; + + ARG_2_BE(ap, len, size_t, start, void *); + app_info_t *info = app_info_get(app_start_addr); + assert(info); + void *heap_addr = RAM_BASE() + info->i.heap_offset - info->i.data_offset; + + len = ALIGN(len, PAGE_SIZE); + printf("munmap 0x%x, 0x%x.\n", start, len); + mm_page_free(((umword_t)(start) - (umword_t)heap_addr) / PAGE_SIZE, len / PAGE_SIZE); + return 0; +} diff --git a/mkrtos_user/lib/libc_backend/src/syscall_backend.c b/mkrtos_user/lib/libc_backend/src/syscall_backend.c index db2fb10f5..bcf61db06 100644 --- a/mkrtos_user/lib/libc_backend/src/syscall_backend.c +++ b/mkrtos_user/lib/libc_backend/src/syscall_backend.c @@ -8,6 +8,7 @@ typedef long (*sys_call_func)(va_list ap); static const sys_call_func sys_call_list[] = { // TODO: add syscall func pointer. + [SYS_munmap] = be_munmap, [SYS_mmap2] = be_mmap2, [SYS_read] = sys_be_read, [SYS_write] = sys_be_read, diff --git a/mkrtos_user/lib/sys/inc/u_app.h b/mkrtos_user/lib/sys/inc/u_app.h index 4195c3636..4fb941b16 100644 --- a/mkrtos_user/lib/sys/inc/u_app.h +++ b/mkrtos_user/lib/sys/inc/u_app.h @@ -1,5 +1,7 @@ #include "u_types.h" +#define APP_MAGIC "MKRTOS." + typedef struct app_info { const char d[32]; @@ -28,5 +30,14 @@ typedef struct app_info static inline app_info_t *app_info_get(void *addr) { - return (app_info_t *)addr; + app_info_t *app = (app_info_t *)addr; + const char *magic = APP_MAGIC; + for (int i = 0; i < sizeof(app->magic) - 1; i++) + { + if (app->magic[i] != magic[i]) + { + return NULL; + } + } + return app; } diff --git a/mkrtos_user/lib/sys/inc/u_log.h b/mkrtos_user/lib/sys/inc/u_log.h index c0d76858f..9e3c45c03 100644 --- a/mkrtos_user/lib/sys/inc/u_log.h +++ b/mkrtos_user/lib/sys/inc/u_log.h @@ -5,3 +5,4 @@ #define ULOG_RW_MAX_BYTES (WORD_BYTES * 5) void ulog_write_bytes(obj_handler_t obj_inx, const uint8_t *data, umword_t len); void ulog_write_str(obj_handler_t obj_inx, const char *str); +int ulog_read_bytes(obj_handler_t obj_inx, uint8_t *data, umword_t len); diff --git a/mkrtos_user/lib/sys/inc/u_prot.h b/mkrtos_user/lib/sys/inc/u_prot.h index d19f14ce2..0d4884700 100644 --- a/mkrtos_user/lib/sys/inc/u_prot.h +++ b/mkrtos_user/lib/sys/inc/u_prot.h @@ -9,6 +9,7 @@ #define IPC_PROT 5 #define MM_PROT 6 #define SYS_PROT 7 +#define IRQ_PROT 8 #define THREAD_MAIN THREAD_PROT #define TASK_THIS TASK_PROT diff --git a/mkrtos_user/lib/sys/src/u_log.c b/mkrtos_user/lib/sys/src/u_log.c index d054871e4..92d5b865f 100644 --- a/mkrtos_user/lib/sys/src/u_log.c +++ b/mkrtos_user/lib/sys/src/u_log.c @@ -11,6 +11,47 @@ enum log_op READ_DATA, SET_FLAGS }; +static msg_tag_t ulog_read_bytes_raw(obj_handler_t obj_inx, umword_t data[5], int len) +{ + register volatile umword_t r0 asm("r0"); + register volatile umword_t r1 asm("r1"); + register volatile umword_t r2 asm("r2"); + register volatile umword_t r3 asm("r3"); + register volatile umword_t r4 asm("r4"); + register volatile umword_t r5 asm("r5"); + syscall(syscall_prot_create(READ_DATA, LOG_PROT, obj_inx), + msg_tag_init4(0, 0, 0, 0).raw, + len, + 0, + 0, + 0, + 0); + msg_tag_t tag = msg_tag_init(r0); + { + ((umword_t *)data)[0] = r1; + ((umword_t *)data)[1] = r2; + ((umword_t *)data)[2] = r3; + ((umword_t *)data)[3] = r4; + ((umword_t *)data)[4] = r5; + } + + return tag; +} +int ulog_read_bytes(obj_handler_t obj_inx, uint8_t *data, umword_t len) +{ + umword_t buffer[5]; + + msg_tag_t tag = ulog_read_bytes_raw(obj_inx, buffer, len); + + if (msg_tag_get_val(tag) > 0) + { + for (int i = 0; i < msg_tag_get_val(tag); i++) + { + data[i] = ((uint8_t *)buffer)[i]; + } + } + return msg_tag_get_val(tag); +} void ulog_write_bytes(obj_handler_t obj_inx, const uint8_t *data, umword_t len) { uint8_t write_buf[ULOG_RW_MAX_BYTES] = {0}; @@ -38,6 +79,10 @@ void ulog_write_bytes(obj_handler_t obj_inx, const uint8_t *data, umword_t len) { return; } + for (int i = 0; i < ULOG_RW_MAX_BYTES; i++) + { + write_buf[i] = 0; + } } } diff --git a/mkrtos_user/lib/sys_util/src/u_hd_man.c b/mkrtos_user/lib/sys_util/src/u_hd_man.c index 5eb8a3007..c5951acf4 100644 --- a/mkrtos_user/lib/sys_util/src/u_hd_man.c +++ b/mkrtos_user/lib/sys_util/src/u_hd_man.c @@ -5,8 +5,9 @@ #include "u_task.h" #include "u_hd_man.h" #include -#define HANDLER_START_INX 10 -#define HANDLER_MAX_NR 64 + +#define HANDLER_START_INX 10 //!< fd开始的值,前10个内核保留 +#define HANDLER_MAX_NR 64 //!< 单个task最大支持的hd数量 static umword_t bitmap_handler_alloc[HANDLER_MAX_NR / WORD_BYTES]; static pthread_spinlock_t lock; @@ -39,6 +40,11 @@ void handler_free(obj_handler_t hd_inx) hd_inx -= HANDLER_START_INX; umword_t word_offset = hd_inx / WORD_BITS; umword_t bits_offset = hd_inx % WORD_BITS; + + if (word_offset >= (HANDLER_MAX_NR / WORD_BYTES)) + { + return; + } pthread_spin_lock(&lock); MK_CLR_BIT(bitmap_handler_alloc[word_offset], bits_offset); pthread_spin_unlock(&lock); diff --git a/mkrtos_user/server/init/src/main.c b/mkrtos_user/server/init/src/main.c index 054b75e60..873d0cbd7 100644 --- a/mkrtos_user/server/init/src/main.c +++ b/mkrtos_user/server/init/src/main.c @@ -13,8 +13,18 @@ extern void futex_init(void); int main(int argc, char *args[]) { + uint8_t data[10]; // futex_init(); ulog_write_str(LOG_PROT, "init..\n"); + // while (1) + // { + // int len = ulog_read_bytes(LOG_PROT, data, sizeof(data) - 1); + // if (len > 0) + // { + // data[len] = 0; + // printf("%s\n", data); + // } + // } #if 0 mm_test(); ulog_test(); diff --git a/mkrtos_user/server/shell/src/heap_stack.c b/mkrtos_user/server/shell/src/heap_stack.c index d1ec5dc02..644fa12a7 100644 --- a/mkrtos_user/server/shell/src/heap_stack.c +++ b/mkrtos_user/server/shell/src/heap_stack.c @@ -13,5 +13,5 @@ #define STACK_ATTR #endif -__attribute__((used)) HEAP_ATTR char heap[HEAP_SIZE]; +__attribute__((used)) HEAP_ATTR static char heap[HEAP_SIZE]; __attribute__((used)) STACK_ATTR static char stack[STACK_SIZE]; diff --git a/mkrtos_user/server/shell/src/main.c b/mkrtos_user/server/shell/src/main.c index 77ca738f4..7e78268d1 100644 --- a/mkrtos_user/server/shell/src/main.c +++ b/mkrtos_user/server/shell/src/main.c @@ -9,11 +9,27 @@ #include #include #include + +void malloc_test(void) +{ + void *mem = malloc(1024); + assert(mem); + void *mem1 = malloc(1024); + assert(mem1); + free(mem); + free(mem1); + mem = malloc(4 * 1024); + assert(mem); + free(mem); + mem1 = malloc(1024); + assert(mem1); + free(mem1); +} + int main(int argc, char *args[]) { ulog_write_str(LOG_PROT, "MKRTOS:\n"); - void *mem = malloc(12); - free(mem); + malloc_test(); ipc_wait(12, 0); ipc_reply(12, msg_tag_init4(0, 0, 0, 0)); char *buf;