Add scheduler first release + fix process stack crash
This commit is contained in:
parent
223f92b6b2
commit
105eb7c482
14
Makefile
14
Makefile
|
@ -7,6 +7,7 @@
|
|||
|
||||
KERNEL := output/vhex.g1a
|
||||
USER := output/shell.elf
|
||||
TEST := output/test.elf
|
||||
|
||||
|
||||
##---
|
||||
|
@ -15,11 +16,13 @@ USER := output/shell.elf
|
|||
all:
|
||||
@ make --no-print-directory -C src/lib
|
||||
@ make --no-print-directory -C src/kernel
|
||||
@ make --no-print-directory -C src/user
|
||||
@ make --no-print-directory -C src/user/shell
|
||||
@ make --no-print-directory -C src/user/test
|
||||
|
||||
install: all
|
||||
sudo p7 send --force --no-term $(KERNEL)
|
||||
sudo p7 send --force --directory=VHEX $(USER)
|
||||
sudo p7 send --force --no-term --directory=VHEX $(USER)
|
||||
sudo p7 send --force --directory=VHEX $(TEST)
|
||||
|
||||
|
||||
|
||||
|
@ -30,12 +33,15 @@ install: all
|
|||
clean:
|
||||
make clean --no-print-directory -C src/lib
|
||||
make clean --no-print-directory -C src/kernel
|
||||
make clean --no-print-directory -C src/user
|
||||
make clean --no-print-directory -C src/user/shell
|
||||
make clean --no-print-directory -C src/user/test
|
||||
|
||||
fclean: clean
|
||||
make fclean --no-print-directory -C src/lib
|
||||
make fclean --no-print-directory -C src/kernel
|
||||
make fclean --no-print-directory -C src/user
|
||||
make fclean --no-print-directory -C src/user/shell
|
||||
make fclean --no-print-directory -C src/user/test
|
||||
rm -rf build
|
||||
|
||||
re: fclean all
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
#ifndef __KERNEL_DEVICES_TIMER_H__
|
||||
# define __KERNEL_DEVICES_TIMER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO: MOVE ME !!!!!!!!
|
||||
#define TIMER_NUMBER 3
|
||||
#define TIMER_UNUSED 0xff
|
||||
|
||||
struct timer_cache_s
|
||||
{
|
||||
void *callback;
|
||||
volatile void *arg;
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
#endif /*__KERNEL_DEVICES_TIMER_H__*/
|
|
@ -0,0 +1,80 @@
|
|||
#ifndef __KERNEL_HARDWARE_CPG_H__
|
||||
# define __KERNEL_HARDWARE_CPG_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel/def/union_types.h>
|
||||
#include <kernel/def/attributes.h>
|
||||
|
||||
struct SH7305_cpg_s
|
||||
{
|
||||
volatile long_union(FRQCRA, /* Casio's configuration: 0x0f212213 */
|
||||
uint32_t KICK : 1; /* Kick bits */
|
||||
uint32_t const : 1; /* All 0 */
|
||||
uint32_t STC : 6; /* PLL circuit multiplication ratio */
|
||||
uint32_t IFC : 4; /* CPU clock frequency division ratio */
|
||||
uint32_t const : 4; /* All 0 */
|
||||
uint32_t SFC : 4; /* S clock frequency division ratio */
|
||||
uint32_t BFC : 4; /* Bus clock frequency division ration */
|
||||
uint32_t const : 4; /* All 0 */
|
||||
uint32_t PFC : 4; /* Peripheral clock frequency division ratio */
|
||||
);
|
||||
volatile uint32_t FRQCRB; /* Undocumented (0x00000000) */
|
||||
volatile long_union(FCLKACR, /* Casio's configuration: 0x00000157 */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown : 16; /* Unknown (default 0x0157) */
|
||||
);
|
||||
volatile long_union(FCLKBCR, /* Casio's configuration: 0x0000003f */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown : 16; /* Unknown (default 0x003f) */
|
||||
);
|
||||
|
||||
GAPS(0x08);
|
||||
volatile long_union(IRDACLKCR, /* Casio's configuration: 0x0000003f */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown : 16; /* Unknown (default 0x003f) */
|
||||
);
|
||||
|
||||
GAPS(0x08);
|
||||
volatile long_union(PLLCR, /* Casio's configuration: 0x00005000 */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown0 : 1; /* Unknown (default 0) */
|
||||
uint32_t PLLE : 1; /* PLL enable (?) */
|
||||
uint32_t const : 1; /* All 0 */
|
||||
uint32_t FLLE : 1; /* FLL enable (?) */
|
||||
uint32_t const : 8; /* All 0 */
|
||||
uint32_t unknown1 : 4; /* Unknown (default 0b0000) */
|
||||
);
|
||||
|
||||
GAPS(0x14);
|
||||
volatile long_union(SPUCLKCR, /* Casio's configuration: 0x00000103 */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown : 16; /* Unknown (default 0x0103) */
|
||||
);
|
||||
|
||||
GAPS(0x08);
|
||||
volatile long_union(VCLKCR, /* Casio's configuration: 0x0000003f */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t unknown : 16; /* Unknown (default 0x003f) */
|
||||
);
|
||||
|
||||
|
||||
GAPS(0x04);
|
||||
volatile long_union(FLLFRQ, /* Casio's configuration: 0x00004384 */
|
||||
uint32_t const : 16; /* All 0 */
|
||||
uint32_t SELXM : 2; /* FLL output division */
|
||||
uint32_t unknown : 3; /* Unknown */
|
||||
uint32_t FLF : 11; /* FLL Multiplication Ratio */
|
||||
|
||||
);
|
||||
|
||||
GAPS(0x0c);
|
||||
volatile long_union(LSTATS,
|
||||
uint32_t const : 31; /* All 0 */
|
||||
uint32_t const FQRF : 1; /* Frequency change status */
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
#define SH7305_CPG (*(volatile struct SH7305_cpg_s *)0xa4150000)
|
||||
#endif /*__KERNEL_HARDWARE_CPG_H__*/
|
|
@ -8,29 +8,29 @@
|
|||
|
||||
struct timer_s
|
||||
{
|
||||
volatile uint32_t TCOR; /* Timer Constant register */
|
||||
volatile uint32_t TCNT; /* Timer Counter */
|
||||
volatile word_union(TCR, /* Timer Control Register */
|
||||
uint16_t const : 7; /* All 0 */
|
||||
uint16_t UNF : 1; /* Underflow flags */
|
||||
uint16_t const : 2; /* All 0 */
|
||||
uint16_t UNIE : 1; /* Underflow interrup control */
|
||||
uint16_t const : 2; /* All 0 */
|
||||
uint16_t TPSC : 3; /* Time prescaler */
|
||||
volatile uint32_t TCOR; /* Timer Constant register */
|
||||
volatile uint32_t TCNT; /* Timer Counter */
|
||||
volatile word_union(TCR, /* Timer Control Register */
|
||||
uint16_t const : 7; /* All 0 */
|
||||
uint16_t UNF : 1; /* Underflow flags */
|
||||
uint16_t const : 2; /* All 0 */
|
||||
uint16_t UNIE : 1; /* Underflow interrup control */
|
||||
uint16_t CKREG : 2; /* Input Clock edge */
|
||||
uint16_t TPSC : 3; /* Time prescaler */
|
||||
);
|
||||
GAPS(2);
|
||||
};
|
||||
|
||||
struct __sh7305_tmu_s
|
||||
{
|
||||
volatile byte_union(TSTR, /* Timer Start Register */
|
||||
uint8_t const : 5; /* All 0 */
|
||||
uint8_t STR2 : 1; /* Counter start 2 */
|
||||
uint8_t STR1 : 1; /* Counter start 1 */
|
||||
uint8_t STR0 : 1; /* Counter start 0 */
|
||||
volatile byte_union(TSTR, /* Timer Start Register */
|
||||
uint8_t const : 5; /* All 0 */
|
||||
uint8_t STR2 : 1; /* Counter start 2 */
|
||||
uint8_t STR1 : 1; /* Counter start 1 */
|
||||
uint8_t STR0 : 1; /* Counter start 0 */
|
||||
);
|
||||
GAPS(3);
|
||||
volatile struct timer_s TIMER[3];
|
||||
volatile struct timer_s TIMER[3]; /* Timers */
|
||||
};
|
||||
|
||||
#define SH7305_TMU (*(volatile struct __sh7305_tmu_s *)0xa4490004)
|
||||
|
|
|
@ -15,7 +15,7 @@ struct pm_block_cache_s
|
|||
} status;
|
||||
|
||||
// Space informations.
|
||||
uint16_t start;
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
|
||||
// Linked list
|
||||
|
|
|
@ -14,8 +14,6 @@
|
|||
#define PROCESS_NAME_LENGHT (16)
|
||||
#define PROCESS_MAX (4)
|
||||
|
||||
#define PROC_IDLE (0)
|
||||
|
||||
// define process struct.
|
||||
//TODO: signal !
|
||||
struct process
|
||||
|
@ -93,6 +91,7 @@ struct process_stack
|
|||
// Functions.
|
||||
extern struct process *process_create(const char *name);
|
||||
extern struct process *process_get(pid_t pid);
|
||||
extern pid_t process_get_pid(struct process *process);
|
||||
extern int process_switch(pid_t pid);
|
||||
|
||||
// Internal function.
|
||||
|
|
|
@ -59,10 +59,10 @@ extern int sched_add_task(struct process *process);
|
|||
extern void sched_start(void);
|
||||
|
||||
/*
|
||||
** Save current context of the current task and run the
|
||||
** next one based on internal task priority.
|
||||
** Get the current task context and the next one
|
||||
** based on internal task priority / status.
|
||||
*/
|
||||
extern void sched_schedule(void);
|
||||
extern int sched_schedule(common_context_t **current, common_context_t **next);
|
||||
|
||||
/*
|
||||
** Internal function wich will switch current process
|
||||
|
|
|
@ -14,6 +14,8 @@ extern pid_t sys_fork(void);
|
|||
extern pid_t sys_getpid(void);
|
||||
extern pid_t sys_getppid(void);
|
||||
extern pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
|
||||
extern pid_t sys_fexecve(const char *pathname);
|
||||
extern void sys_exit(int status);
|
||||
|
||||
extern int sys_open(const char *pathname, int flags, ...);
|
||||
extern ssize_t sys_write(int fd, const void *buf, size_t count);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// Process
|
||||
#define __NR_exit 1
|
||||
#define __NR_exec 2
|
||||
#define __NR_fexecve 2
|
||||
#define __NR_waitpid 3
|
||||
|
||||
// VFS
|
||||
|
@ -27,6 +27,7 @@
|
|||
#define __NR_kvram_ascii 12
|
||||
#define __NR_kvram_reverse 13
|
||||
#define __NR_kvram_scroll 14
|
||||
#define __NR_kvram_clr_str_area 15
|
||||
|
||||
//TODO: keyboard
|
||||
|
||||
|
|
|
@ -18,9 +18,9 @@ extern size_t strlen(char const *str);
|
|||
extern void kvram_clear(void);
|
||||
extern void kvram_display(void);
|
||||
extern void kvram_scroll(int lines);
|
||||
extern void kvram_reverse(int x, int y, int width, int height);
|
||||
extern void kvram_print(int x, int y, char const *str);
|
||||
extern void kvram_ascii(int x, int y, char const c);
|
||||
extern void kvram_reverse(int x, int y, int width, int height);
|
||||
extern void kvram_clr_str_area(int x, int y, int width, int height);
|
||||
|
||||
// Kernel printf-wrapper
|
||||
extern void printk(int x, int y, char const *str, ...);
|
||||
|
@ -28,9 +28,21 @@ extern void printk(int x, int y, char const *str, ...);
|
|||
// Hardware specific function (do not use !)
|
||||
extern void t6k11_display(void *vram);
|
||||
|
||||
// Timer functions.
|
||||
//---
|
||||
// Timer functions.
|
||||
//---
|
||||
#define TIMER_NUMBER 3
|
||||
#define TIMER_UNUSED 0xff
|
||||
|
||||
struct timer_cache_s
|
||||
{
|
||||
void *callback;
|
||||
volatile void *arg;
|
||||
uint8_t status;
|
||||
};
|
||||
extern int timer_uninstall(int timer_ID);
|
||||
extern int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode);
|
||||
extern int timer_install(void *callback, void *arg, uint32_t ticks, uint8_t mode);
|
||||
extern int timer_start(int timer_ID);
|
||||
|
||||
// Debug wait
|
||||
#define DBG_WAIT for(int i = 0 ; i < 3000000 ; i++)
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
// Draw primtives
|
||||
extern void dclear(void);
|
||||
extern void dprint(int x, int y, char const *str);
|
||||
extern void dclr_str_area(int x, int y, int with, int height);
|
||||
extern void dprint(int x, int y, char const *str, ...);
|
||||
extern void dascii(int x, int y, char const c);
|
||||
extern void dreverse(int x, int y, int width, int height);
|
||||
extern void dscroll(int line);
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define WUNTRACED 1
|
||||
#define WCONTINUED 2
|
||||
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
|
||||
extern pid_t fexecve(const char *pathname);
|
||||
|
||||
// File syscall
|
||||
#define O_DIRECT 0
|
||||
|
|
|
@ -4,14 +4,6 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define VHEX_BUILTIN(bname) \
|
||||
static int bname(int argc, char **argv); \
|
||||
__attribute__((section(".builtin"))) \
|
||||
struct builtin_s _##bname = { \
|
||||
.name = #bname, \
|
||||
.entry = &bname \
|
||||
}; \
|
||||
static int bname(int argc, char **argv)
|
||||
|
||||
// Define builtin struct.
|
||||
struct builtin_s
|
||||
|
@ -20,5 +12,9 @@ struct builtin_s
|
|||
int (*entry)(int argc, char **argv);
|
||||
};
|
||||
|
||||
// Builtin list
|
||||
extern int builtin_proc(void);
|
||||
extern int builtin_ram(void);
|
||||
|
||||
|
||||
#endif /*__USER_BUILTIN_H__*/
|
||||
|
|
|
@ -174,9 +174,9 @@ int start(void)
|
|||
if (vhex_process == NULL)
|
||||
{
|
||||
kvram_clear();
|
||||
kvram_print(0, 0, "Vhex fatal error !");
|
||||
kvram_print(0, 1, "First process error !");
|
||||
kvram_print(0, 2, "Wait manual reset...");
|
||||
printk(0, 0, "Vhex fatal error !");
|
||||
printk(0, 1, "First process error !");
|
||||
printk(0, 2, "Wait manual reset...");
|
||||
kvram_display();
|
||||
while (1) { __asm__ volatile ("sleep"); }
|
||||
}
|
||||
|
@ -188,9 +188,9 @@ int start(void)
|
|||
{
|
||||
// Display message.
|
||||
kvram_clear();
|
||||
kvram_print(0, 0, "Vhex fatal error !");
|
||||
kvram_print(0, 1, "File \"VHEX/shell.elf\" not found !");
|
||||
kvram_print(0, 2, "Press [MENU key]...");
|
||||
printk(0, 0, "Vhex fatal error !");
|
||||
printk(0, 1, "File \"VHEX/shell.elf\" not found !");
|
||||
printk(0, 2, "Press [MENU key]...");
|
||||
kvram_display();
|
||||
|
||||
// Restore Casio context.
|
||||
|
@ -225,7 +225,7 @@ int start(void)
|
|||
|
||||
// normally the kernel SHOULD / CAN not arrive here.
|
||||
kvram_clear();
|
||||
kvram_print(0, 0, "Kernel job fini !");
|
||||
printk(0, 0, "Kernel job fini !");
|
||||
kvram_display();
|
||||
while (1)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,8 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
|
|||
keyboard.saved.tty.cursor.y = tty.cursor.y;
|
||||
|
||||
// Initialize timer for cursor.
|
||||
timer_fd = timer_install(&cursor_callback, &keyboard, 500, 1);
|
||||
// FIXME: find real ticks value !!
|
||||
timer_fd = timer_install(&cursor_callback, &keyboard, 500 * 500 * 2, 1);
|
||||
if (timer_fd == -1)
|
||||
return (0);
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ void *gladfs_mount(void)
|
|||
if (gladfs_superblock.root_inode == NULL)
|
||||
{
|
||||
kvram_clear();
|
||||
kvram_print(0, 0, "GladFS: ROOT inode alloc error !");
|
||||
printk(0, 0, "GladFS: ROOT inode alloc error !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ static int get_name(int *name_lenght, const char *path, char *name)
|
|||
return (0);
|
||||
}
|
||||
|
||||
//TODO add '..' handling.
|
||||
//TODO: update ?
|
||||
struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
|
@ -114,7 +114,6 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
printk(0, 3, "name: %s$", name);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
while (1);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +137,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
|
||||
// Try to find first child
|
||||
next = vfs_dentry_find_first_child(next);
|
||||
if (next != NULL)
|
||||
/*if (next != NULL)
|
||||
{
|
||||
// Debug !
|
||||
kvram_clear();
|
||||
|
@ -148,7 +147,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
printk(0, 3, "name: %s$", name);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Update name lenght to skip '/' char
|
||||
name_lenght = name_lenght + 1;
|
||||
|
|
|
@ -62,7 +62,7 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
|
|||
|
||||
|
||||
// Debug !
|
||||
kvram_clear();
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "New mknod device !");
|
||||
printk(0, 1, "dentry: %p$", file);
|
||||
printk(0, 2, "inode: %p$", file->inode);
|
||||
|
@ -70,7 +70,7 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
|
|||
printk(0, 4, "dev->file_op: %p$", &device->file_op);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;*/
|
||||
|
||||
// Set file operations
|
||||
file->dentry_op.file_op = &device->file_op;
|
||||
|
|
|
@ -67,13 +67,13 @@ int vfs_mount(const char *source, const char *target,
|
|||
vfs_root_node->dentry_op.inode_op = &filesystem->inode_operations;
|
||||
|
||||
// Debug !
|
||||
kvram_clear();
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "vfs_root_node = %p", vfs_root_node);
|
||||
printk(0, 1, "vfs_root_node = %s$", vfs_root_node->name);
|
||||
printk(0, 2, "vfs_root_node = %p", vfs_root_node->child);
|
||||
printk(0, 3, "vfs_root_node = %p", vfs_root_node->next);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/devices/timer.h>
|
||||
|
||||
// Internal timer "cache".
|
||||
struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
|
||||
__attribute__((constructor))
|
||||
void timer_constructor(void)
|
||||
{
|
||||
for (int i = 0 ; i < TIMER_NUMBER ; i = i + 1)
|
||||
{
|
||||
timercache[i].status = TIMER_UNUSED;
|
||||
timercache[i].callback = NULL;
|
||||
timercache[i].arg = NULL;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/devices/timer.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
void timer_handler(void)
|
||||
{
|
||||
extern struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
static uint32_t counter = 0;
|
||||
uint32_t intevt;
|
||||
int timer_ID;
|
||||
|
||||
|
@ -11,10 +12,18 @@ void timer_handler(void)
|
|||
// @note: tricky way to get timer ID
|
||||
// TODO: find better way !
|
||||
intevt = *(uint32_t*)0xff000028;
|
||||
timer_ID = (intevt - 0x400) >> 9;
|
||||
timer_ID = (intevt - 0x400) / 0x20;
|
||||
|
||||
// Stop timer flag and clear interrupt flags.
|
||||
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID);
|
||||
/*if (intevt != 0x400)
|
||||
{
|
||||
kvram_clear();
|
||||
printk(0, 0, "Timer ID: %d\n", timer_ID);
|
||||
printk(0, 1, "Interrupt: %#x\n", intevt);
|
||||
printk(0, 2, "counter: %d\n", counter++);
|
||||
kvram_display();
|
||||
}*/
|
||||
|
||||
// Clear interrupt flags.
|
||||
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0;
|
||||
|
||||
// Execute callback if possible.
|
||||
|
@ -24,6 +33,4 @@ void timer_handler(void)
|
|||
((void (*)(volatile void *))timercache[timer_ID].callback)(timercache[timer_ID].arg);
|
||||
}
|
||||
|
||||
// Re-start timer.
|
||||
SH7305_TMU.TSTR.BYTE |= 1 << timer_ID;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
extern void keysc_handler(void);
|
||||
extern void timer_handler(void);
|
||||
|
||||
__attribute__((section(".vhex.interrupt"), interrupt_handler))
|
||||
void interrupt_handler(void)
|
||||
{
|
||||
uint32_t intevt = *(uint32_t*)0xff000028;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
.section ".vhex.interrupt", "awx", @progbits
|
||||
|
||||
.global _interrupt_handler_pre
|
||||
.type _interrupt_handler_pre, @function
|
||||
|
||||
.extern _sched_timer_intevt
|
||||
.extern _sched_handler
|
||||
.extern _interrupt_handler
|
||||
|
||||
_interrupt_handler_pre:
|
||||
! Due to PR register used to switch process
|
||||
! context, we SHOULD catch scheduler timer
|
||||
! interrupt before the interrupt handler because
|
||||
! we need to save / restore pr register before
|
||||
! context swtich.
|
||||
mov.l .sched_timer_intevt, r0 ! get the precalculate scheduler timer event
|
||||
mov.l .intevt_register, r1 ! get INTEVT register address
|
||||
mov.l @r0, r0 ! get the scheduler event code
|
||||
mov.l @r1, r1 ! get the interrupt event
|
||||
cmp/eq r0, r1 ! if scheduler timer event == INTEVT...
|
||||
bf general_interrupt ! ...if not, jump at <general_interrupt>
|
||||
|
||||
scheduler_interrupt:
|
||||
mov.l .scheduler_handler, r0 ! get scheduler handler address
|
||||
jmp @r0 ! jump into scheduler handler
|
||||
nop ! (db) nop
|
||||
|
||||
general_interrupt:
|
||||
! Save critical regsiter.
|
||||
stc.l spc, @-r15 ! save SPC register.
|
||||
stc.l ssr, @-r15 ! save SSR register.
|
||||
sts.l pr, @-r15 ! save pr register.
|
||||
|
||||
! Call interrupt handler
|
||||
mov.l .interrupt_handler, r0 ! get interrupt handler address
|
||||
jsr @r0 ! call interurpt handler
|
||||
nop ! (db) nop
|
||||
|
||||
! Restore critical regsiter
|
||||
lds.l @r15+, pr ! restore PR register.
|
||||
ldc.l @r15+, ssr ! restore SSR regsiter.
|
||||
ldc.l @r15+, spc ! restore SPC regsiter.
|
||||
|
||||
! Return
|
||||
rte ! exit
|
||||
nop ! (db) nop
|
||||
|
||||
.align 4
|
||||
.sched_timer_intevt: .long _sched_timer_intevt
|
||||
.scheduler_handler: .long _sched_handler
|
||||
.interrupt_handler: .long _interrupt_handler
|
||||
.intevt_register: .long 0xff000028
|
|
@ -44,10 +44,10 @@ save_current_context:
|
|||
! @note: current process can be NULL !
|
||||
tst r4, r4 ! if current task == NULL...
|
||||
bt context_load ! ...if yes, jump at <context_switch>
|
||||
add #88, r4 ! get &process->context (end)
|
||||
add #84, r4 ! get &process->context (end)
|
||||
|
||||
! save current context
|
||||
sts.l pr, @-r4 ! get pr regsiter
|
||||
!sts.l pr, @-r4 ! get pr regsiter
|
||||
stc.l spc, @-r4 ! get spc regsiter
|
||||
stc.l ssr, @-r4 ! get ssr regsiter
|
||||
sts.l mach, @-r4 ! get mach regsiter
|
||||
|
@ -95,7 +95,7 @@ context_load:
|
|||
lds.l @r5+, mach ! set mach regsiter
|
||||
ldc.l @r5+, ssr ! set ssr regsiter
|
||||
ldc.l @r5+, spc ! set spc regsiter
|
||||
lds.l @r5+, pr ! set pr regsiter
|
||||
!lds.l @r5+, pr ! set pr regsiter
|
||||
|
||||
|
||||
! Process switch
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#include <kernel/context.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
// Test
|
||||
uint32_t counter = 0;
|
||||
|
||||
void sched_debug(common_context_t *context_current, common_context_t *context_next)
|
||||
{
|
||||
extern uint32_t sched_timer_id;
|
||||
extern uint32_t sched_timer_address;
|
||||
|
||||
uint32_t tstr = SH7305_TMU.TSTR.BYTE;
|
||||
uint32_t tcr = *(uint16_t*)sched_timer_address;
|
||||
uint32_t tcor = *(uint32_t*)(sched_timer_address - 4);
|
||||
uint32_t tcnt = *(uint32_t*)(sched_timer_address - 8);
|
||||
|
||||
|
||||
//SH7305_TMU.TSTR.STR2 = 0;
|
||||
//SH7305_TMU.TSTR.STR1 = 0;
|
||||
//SH7305_TMU.TSTR.STR0 = 0;
|
||||
|
||||
//SH7305_TMU.TIMER[0].TCR.UNF = 0;
|
||||
//SH7305_TMU.TIMER[1].TCR.UNF = 0;
|
||||
//SH7305_TMU.TIMER[2].TCR.UNF = 0;
|
||||
|
||||
kvram_clear();
|
||||
printk(0, 0, "Scheduler_schudele !");
|
||||
printk(0, 1, "context current = %p", context_current);
|
||||
printk(0, 2, "context next = %p", context_next);
|
||||
printk(0, 3, "counter = %#x", counter++);
|
||||
printk(0, 4, "TSTR: %#x", tstr);
|
||||
printk(0, 5, "TCOR: %#x", tcor);
|
||||
printk(0, 6, "TCNT: %#x", tcnt);
|
||||
printk(0, 7, "TCR: %#x", tcr);
|
||||
kvram_display();
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
.text
|
||||
|
||||
.global _sched_handler
|
||||
.type _sched_handler, @function
|
||||
|
||||
.extern _sched_timer_id
|
||||
.extern _sched_timer_address
|
||||
.extern _sched_schedule
|
||||
|
||||
.align 2
|
||||
/*
|
||||
** @note
|
||||
** We can use only r0 - r7 register because
|
||||
** we SHOULD not modify the current process context.
|
||||
*/
|
||||
_sched_handler:
|
||||
|
||||
|
||||
/*
|
||||
** Stop scheduler timer and clear interrupt flags
|
||||
*/
|
||||
stop_clear_sched_timer:
|
||||
! Clear scheduler timer interrupt
|
||||
mov.l .sched_timer_address, r0 ! get precalculated scheduler timer address
|
||||
mov.l .timer_unf_field, r1 ! get TIMER.TCR.UNF byte field
|
||||
mov.l @r0, r0 ! get scheduler timer TCR register
|
||||
mov.w @r0, r2 ! get scheduler timer TCR register
|
||||
not r1, r1 ! get interrupt flags bit mask (to remove)
|
||||
and r1, r2 ! clear timer interrupt flags
|
||||
mov.w r2, @r0 ! update timer TCR
|
||||
|
||||
! Stop scheduler timer
|
||||
mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID
|
||||
mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address
|
||||
mov.l @r0, r0 ! get scheduler timer ID
|
||||
mov.b @r1, r2 ! get TMU0.TSTR data
|
||||
not r0, r0 ! get TSTR scheduler timer ID mask (to remove)
|
||||
and r0, r2 ! stop scheduler timer
|
||||
mov.b r2, @r1 ! update TMU0.TSTR
|
||||
|
||||
#ifdef __SCHED_DEBUG__
|
||||
sts.l pr, @-r15 ! save pr register
|
||||
mov #0, r4 ! save r4 register (current context)
|
||||
mov #0, r5 ! save r5 register (next context)
|
||||
mov.l .sched_debug, r0 ! get sched_debug() absraction
|
||||
jsr @r0 ! call abstraction
|
||||
nop ! (db) nop
|
||||
lds.l @r15+, pr ! restore pr register
|
||||
|
||||
bra restart_sched_timer
|
||||
nop
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Get current and next context
|
||||
*/
|
||||
get_contexts:
|
||||
! prologue
|
||||
mov.l r9, @-r15 ! save r9 register
|
||||
mov.l r8, @-r15 ! save r8 register
|
||||
sts.l pr, @-r15 ! save pr register
|
||||
|
||||
! Create to context_common_t **ptr
|
||||
add #-4, r15 ! create first context pointer
|
||||
mov r15, r8 ! save first context pointer
|
||||
add #-4, r15 ! create second context pointer
|
||||
mov r15, r9 ! save second context pointer
|
||||
add #-4, r15 ! create context pointer
|
||||
mov.l r15, @r8 ! save context pointer
|
||||
add #-4, r15 ! create context pointer
|
||||
mov.l r15, @r9 ! save context pointer
|
||||
|
||||
! call high level abstraction
|
||||
mov r8, r4 ! send current contexts pointer
|
||||
mov r9, r5 ! send next context pointer
|
||||
mov.l .sched_schedule, r0 ! get sched_scheduler() abstraction address
|
||||
jsr @r0 ! call sched_schedule() abstract
|
||||
nop ! (db) nop
|
||||
|
||||
! Restore stack and register (epilogue)
|
||||
mov.l @r8, r4 ! save current context
|
||||
mov.l @r9, r5 ! save next context
|
||||
add #16, r15 ! restore stack
|
||||
lds.l @r15+, pr ! restore pr register
|
||||
mov.l @r15+, r8 ! restore r8 register
|
||||
mov.l @r15+, r9 ! restore r9 register
|
||||
|
||||
! Check context error
|
||||
tst r0, r0 ! check if returned value == 0...
|
||||
bt debug ! if yes, jump at <debug>
|
||||
bra restart_sched_timer ! jump at <restart_sched_timer>
|
||||
nop ! (db) nop
|
||||
|
||||
|
||||
/*
|
||||
** Debug part, used to debug the contexts
|
||||
*/
|
||||
debug:
|
||||
#ifdef __SCHED_DEBUG__
|
||||
sts.l pr, @-r15 ! save pr register
|
||||
mov.l r4, @-r15 ! save r4 register (current context)
|
||||
mov.l r5, @-r15 ! save r5 register (next context)
|
||||
mov.l .sched_debug, r0 ! get sched_debug() absraction
|
||||
jsr @r0 ! call abstraction
|
||||
nop ! (db) nop
|
||||
mov.l @r15+, r5 ! restore r5 register
|
||||
mov.l @r15+, r4 ! restore r4 register
|
||||
lds.l @r15+, pr ! restore pr register
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Context switch
|
||||
*/
|
||||
save_current_context:
|
||||
! Check current process
|
||||
! @note: current process can be NULL !
|
||||
tst r4, r4 ! if current task == NULL...
|
||||
bt next_context_load ! ...if yes, jump at <context_switch>
|
||||
add #88, r4 ! get &process->context (end)
|
||||
|
||||
! save current context
|
||||
sts.l pr, @-r4 ! get pr regsiter
|
||||
stc.l spc, @-r4 ! get spc regsiter
|
||||
stc.l ssr, @-r4 ! get ssr regsiter
|
||||
sts.l mach, @-r4 ! get mach regsiter
|
||||
sts.l macl, @-r4 ! get macl regsiter
|
||||
stc.l gbr, @-r4 ! get gbr regsiter
|
||||
mov.l r15, @-r4 ! get r15 register
|
||||
mov.l r14, @-r4 ! get r14 regsiter
|
||||
mov.l r13, @-r4 ! get r13 regsiter
|
||||
mov.l r12, @-r4 ! get r12 regsiter
|
||||
mov.l r11, @-r4 ! get r11 regsiter
|
||||
mov.l r10, @-r4 ! get r10 regsiter
|
||||
mov.l r9, @-r4 ! get r9 regsiter
|
||||
mov.l r8, @-r4 ! get r8 regsiter
|
||||
stc.l R7_BANK, @-r4 ! get "process" r7 regsiter
|
||||
stc.l R6_BANK, @-r4 ! get "process" r6 regsiter
|
||||
stc.l R5_BANK, @-r4 ! get "process" r5 regsiter
|
||||
stc.l R4_BANK, @-r4 ! get "process" r4 regsiter
|
||||
stc.l R3_BANK, @-r4 ! get "process" r3 regsiter
|
||||
stc.l R2_BANK, @-r4 ! get "process" r2 regsiter
|
||||
stc.l R1_BANK, @-r4 ! get "process" r1 regsiter
|
||||
stc.l R0_BANK, @-r4 ! get "process" r0 regsiter
|
||||
|
||||
next_context_load:
|
||||
! Load next process
|
||||
! @note: next process can not be NULL !
|
||||
ldc.l @r5+, R0_BANK ! set "process" r0 regsiter
|
||||
ldc.l @r5+, R1_BANK ! set "process" r1 regsiter
|
||||
ldc.l @r5+, R2_BANK ! set "process" r2 regsiter
|
||||
ldc.l @r5+, R3_BANK ! set "process" r3 regsiter
|
||||
ldc.l @r5+, R4_BANK ! set "process" r4 regsiter
|
||||
ldc.l @r5+, R5_BANK ! set "process" r5 regsiter
|
||||
ldc.l @r5+, R6_BANK ! set "process" r6 regsiter
|
||||
ldc.l @r5+, R7_BANK ! set "process" r7 regsiter
|
||||
mov.l @r5+, r8 ! set r8 regsiter
|
||||
mov.l @r5+, r9 ! set r9 regsiter
|
||||
mov.l @r5+, r10 ! set r10 regsiter
|
||||
mov.l @r5+, r11 ! set r11 regsiter
|
||||
mov.l @r5+, r12 ! set r12 regsiter
|
||||
mov.l @r5+, r13 ! set r13 regsiter
|
||||
mov.l @r5+, r14 ! set r14 regsiter
|
||||
mov.l @r5+, r15 ! set r15 register
|
||||
ldc.l @r5+, gbr ! set gbr regsiter
|
||||
lds.l @r5+, macl ! set macl regsiter
|
||||
lds.l @r5+, mach ! set mach regsiter
|
||||
ldc.l @r5+, ssr ! set ssr regsiter
|
||||
ldc.l @r5+, spc ! set spc regsiter
|
||||
lds.l @r5+, pr ! set pr regsiter
|
||||
|
||||
|
||||
/*
|
||||
** Restart timer
|
||||
*/
|
||||
restart_sched_timer:
|
||||
mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID
|
||||
mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address
|
||||
mov.l @r0, r0 ! get scheduler timer ID
|
||||
mov.b @r1, r2 ! get TMU0.TSTR data
|
||||
or r0, r2 ! start scheduler timer
|
||||
mov.b r2, @r1 ! update TMU0.TSTR
|
||||
|
||||
|
||||
/*
|
||||
** Process switch
|
||||
*/
|
||||
process_switch:
|
||||
rte ! use RTE to switch process
|
||||
nop ! (db) nop
|
||||
|
||||
|
||||
.align 4
|
||||
.sched_timer_tstr_bit: .long _sched_timer_tstr_bit
|
||||
.sched_timer_address: .long _sched_timer_address
|
||||
.sched_schedule: .long _sched_schedule
|
||||
.timer_tstr_register: .long 0xa4490004
|
||||
.timer_unf_field: .long 0x00000100
|
||||
#ifndef __SCHED_DEBUG__
|
||||
.sched_debug: .long _sched_debug
|
||||
#endif
|
||||
.end
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
// This function SHOULD NOT be called
|
||||
// without atomic operation !!
|
||||
// TODO: dynamic allocation ?
|
||||
pid_t process_alloc(struct process **process)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
{
|
||||
if (process_stack[i].status == PROC_IDLE)
|
||||
if (process_stack[i].status == PROC_UNUSED)
|
||||
{
|
||||
process_stack[i].status = PROC_USED;
|
||||
*process = &process_stack[i].process;
|
||||
return (i);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
struct process *process_get(pid_t pid)
|
||||
struct process *process_get_proc(pid_t pid)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
|
||||
|
@ -11,3 +11,17 @@ struct process *process_get(pid_t pid)
|
|||
// Return process.
|
||||
return (&process_stack[pid].process);
|
||||
}
|
||||
|
||||
pid_t process_get_pid(struct process *target)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
int i;
|
||||
|
||||
i = -1;
|
||||
while (++i < PROCESS_MAX)
|
||||
{
|
||||
if (&process_stack[i].process == target)
|
||||
return (i);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,6 @@ void process_constructor(void)
|
|||
// Set all process to idle state.
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
{
|
||||
process_stack[i].status = PROC_IDLE;
|
||||
process_stack[i].status = PROC_UNUSED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,26 +3,20 @@
|
|||
#include <kernel/util.h>
|
||||
|
||||
//TODO: assembly !
|
||||
void sched_schedule(void)
|
||||
// @note: This part *SHOULD* be exeption safe !
|
||||
int sched_schedule(common_context_t **context_current, common_context_t **context_next)
|
||||
{
|
||||
extern struct sched_task *sched_task_current;
|
||||
extern struct sched_task *sched_task_queue;
|
||||
struct sched_task *task_current;
|
||||
struct sched_task *task_next;
|
||||
common_context_t *context_current;
|
||||
common_context_t *context_next;
|
||||
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Check current task
|
||||
// TODO: check process status !!
|
||||
if (sched_task_current == NULL)
|
||||
{
|
||||
task_current = NULL;
|
||||
task_next = (sched_task_queue != NULL)
|
||||
? sched_task_queue
|
||||
: NULL;
|
||||
|
||||
task_next = (sched_task_queue != NULL) ? sched_task_queue : NULL;
|
||||
} else {
|
||||
task_current = sched_task_current;
|
||||
task_next = (sched_task_current->next != NULL)
|
||||
|
@ -32,39 +26,23 @@ void sched_schedule(void)
|
|||
|
||||
// Check potantial error
|
||||
if (task_next == NULL || task_next == sched_task_current)
|
||||
{
|
||||
atomic_stop();
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: check process status !!!
|
||||
return (-1);
|
||||
|
||||
// Update internal scheduler task cursor
|
||||
sched_task_current = task_next;
|
||||
|
||||
|
||||
// Get context
|
||||
context_current =
|
||||
(task_current != NULL)
|
||||
? &task_current->process->context
|
||||
: NULL;
|
||||
context_next =
|
||||
(task_next != NULL)
|
||||
? &task_next->process->context
|
||||
: NULL;
|
||||
*context_current = (task_current != NULL) ? &task_current->process->context : NULL;
|
||||
*context_next = &task_next->process->context;
|
||||
|
||||
// DEBUG !
|
||||
kvram_clear();
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "Scheduler_schudele !");
|
||||
printk(0, 1, "task current = %p", task_current);
|
||||
printk(0, 2, "task next = %p", task_next);
|
||||
printk(0, 3, "context current = %p", context_current);
|
||||
printk(0, 4, "context next = %p", context_next);
|
||||
printk(0, 3, "context current = %p", *context_current);
|
||||
printk(0, 4, "context next = %p", *context_next);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
printk(0, 5, "context switch !");
|
||||
kvram_display();
|
||||
|
||||
// Context switch
|
||||
sched_context_switch(context_current, context_next);
|
||||
DBG_WAIT;*/
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,114 @@
|
|||
#include <kernel/scheduler.h>
|
||||
#include <kernel/hardware/cpg.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
// Internal data used by the scheduler handler
|
||||
uint32_t sched_timer_id = 0;
|
||||
uint32_t sched_timer_address = 0;
|
||||
uint32_t sched_timer_intevt = 0;
|
||||
uint32_t sched_timer_tstr_bit = 0;
|
||||
|
||||
// Internal private function
|
||||
//void sched_handler(void);
|
||||
|
||||
//FIXME: remove me and wrap timer interrupt when occur !!
|
||||
static void scheduler_timer_callback(void)
|
||||
{
|
||||
common_context_t *context_current;
|
||||
common_context_t *context_next;
|
||||
|
||||
//TODO: quantum handling !!
|
||||
//TODO: scheduler block / unblock options !!
|
||||
//FIXME: Get SPC, SSR, ... !!
|
||||
|
||||
// Get current context and
|
||||
if (sched_schedule(&context_current, &context_next) != 0)
|
||||
return;
|
||||
|
||||
// Debug
|
||||
//kvram_clear();
|
||||
//printk(0, 0, "Scheduler_schudele !");
|
||||
//printk(0, 1, "context current = %p", context_current);
|
||||
//printk(0, 2, "context next = %p", context_next);
|
||||
//kvram_display();
|
||||
//printk(0, 3, "context switch !");
|
||||
//kvram_display();
|
||||
//DBG_WAIT;
|
||||
|
||||
// Context switch
|
||||
sched_context_switch(context_current, context_next);
|
||||
}
|
||||
|
||||
void sched_start(void)
|
||||
{
|
||||
extern struct sched_task *sched_task_queue;
|
||||
extern struct process *process_current;
|
||||
uint32_t fll_freq;
|
||||
uint32_t pll_freq;
|
||||
uint32_t cpu_freq;
|
||||
uint32_t bus_freq;
|
||||
uint32_t per_freq;
|
||||
|
||||
//TODO: get CPU frequency !
|
||||
//TODO: setup TMU0 interrupt !
|
||||
|
||||
// Calculate FLL frequency (Khz)
|
||||
// @note: RCLK = 32 768 Hz
|
||||
fll_freq = SH7305_CPG.FLLFRQ.FLF * 32768; // Hz
|
||||
fll_freq = fll_freq / (1 << SH7305_CPG.FLLFRQ.SELXM); // Check FLL output division
|
||||
|
||||
// Calculate PLL frequency (Khz)
|
||||
pll_freq = fll_freq * (SH7305_CPG.FRQCRA.STC + 1);
|
||||
|
||||
// Calculate CPU clock frequency !
|
||||
cpu_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.IFC + 1));
|
||||
|
||||
// Calculate BUS clock frequency !
|
||||
bus_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.BFC + 1));
|
||||
|
||||
// Calculate Peripheral clock frequency !
|
||||
per_freq = pll_freq / (1 << (SH7305_CPG.FRQCRA.PFC + 1));
|
||||
|
||||
|
||||
// Debug
|
||||
kvram_clear();
|
||||
printk(0, 0,
|
||||
"FLL freq: %d.%d Mhz\n"
|
||||
"PLL freq: %d.%d Mhz\n"
|
||||
"CPU freq: %d.%d Mhz\n"
|
||||
"BUS freq: %d.%d Mhz\n"
|
||||
"Per freq: %d.%d Mhz",
|
||||
fll_freq / 1000000, (((fll_freq - ((fll_freq / 1000000)) * 1000000)) + 999) / 1000,
|
||||
pll_freq / 1000000, (((pll_freq - ((pll_freq / 1000000)) * 1000000)) + 999) / 1000,
|
||||
cpu_freq / 1000000, (((cpu_freq - ((cpu_freq / 1000000)) * 1000000)) + 999) / 1000,
|
||||
bus_freq / 1000000, (((bus_freq - ((bus_freq / 1000000)) * 1000000)) + 999) / 1000,
|
||||
per_freq / 1000000, (((per_freq - ((per_freq / 1000000)) * 1000000)) + 999) / 1000
|
||||
);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
|
||||
// Register first process !
|
||||
process_current = sched_task_queue->process;
|
||||
sched_schedule();
|
||||
|
||||
// Setup TMU0 (scheduler) interrupt !
|
||||
// @note: I use Po/4 on TMU prescaler
|
||||
// TODO: generate quantum and quantum counter for preemption !
|
||||
uint32_t ticks = (per_freq / 4) / 16;
|
||||
//sched_timer_id = timer_install(scheduler_timer_callback, NULL, ticks, 0);
|
||||
sched_timer_id = timer_install(NULL, NULL, ticks, 0);
|
||||
sched_timer_address = (uint32_t)&SH7305_TMU.TIMER[sched_timer_id].TCR;
|
||||
sched_timer_intevt = 0x400 + (0x20 * sched_timer_id);
|
||||
sched_timer_tstr_bit = 1 << sched_timer_id;
|
||||
|
||||
// Debug
|
||||
kvram_clear();
|
||||
printk(0, 0, "timer ID: %d", sched_timer_id);
|
||||
printk(0, 1, "timer addr: %#x", sched_timer_address);
|
||||
printk(0, 2, "timer event: %#x", sched_timer_intevt);
|
||||
printk(0, 3, "timer TSTR: %#x", sched_timer_tstr_bit);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
|
||||
|
||||
// Start scheduler timer
|
||||
timer_start(sched_timer_id);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
void sys_exit(int status)
|
||||
{
|
||||
kvram_clear();
|
||||
printk(0, 0, "PROCESS EXIT SYSCALL !!!!");
|
||||
printk(0, 0, "Wait manual reset...");
|
||||
kvram_display();
|
||||
while (1);
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/loader.h>
|
||||
#include <kernel/atomic.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
pid_t sys_fexecve(const char *pathname)
|
||||
{
|
||||
struct process *proc;
|
||||
pid_t child_pid;
|
||||
FILE *bin;
|
||||
int error;
|
||||
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Try create new process
|
||||
proc = process_create(pathname);
|
||||
if (proc == NULL)
|
||||
{
|
||||
kvram_clear();
|
||||
printk(0, 0, "sys_fexecve: alloc error !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Try to load binary into physical memory
|
||||
proc->context.spc = (uint32_t)loader(pathname, proc);
|
||||
if (proc->context.spc == 0x00000000)
|
||||
{
|
||||
kvram_clear();
|
||||
printk(0, 0, "sys_fexecve: loader error !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
process_free(proc);
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Debug
|
||||
kvram_clear();
|
||||
printk(0, 0, "New proc loaded !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
|
||||
// Add new process into task queue
|
||||
error = sched_add_task(proc);
|
||||
if (error != 0)
|
||||
{
|
||||
kvram_clear();
|
||||
printk(0, 0, "sys_fexecve: scheduler error !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
process_free(proc);
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Debug
|
||||
printk(0, 1, "New proc sched added !");
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
|
||||
// Get child process PID
|
||||
child_pid = process_get_pid(proc);
|
||||
|
||||
// Debug
|
||||
printk(0, 2, "New proc PID = %#x !", child_pid);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
return (child_pid);
|
||||
}
|
|
@ -2,20 +2,41 @@
|
|||
|
||||
pid_t sys_fork(void)
|
||||
{
|
||||
extern process_t *process_current;
|
||||
process_t **process_new;
|
||||
pid_t process_pid;
|
||||
extern struct process *process_current;
|
||||
struct process *process_new;
|
||||
pid_t process_new_pid;
|
||||
|
||||
// Check error
|
||||
if (process_current == NULL)
|
||||
return (-1);
|
||||
|
||||
// Get the new process slot.
|
||||
process_new = &process_current->child;
|
||||
while (*process_new != NULL)
|
||||
process_new = &(*process_new)->next;
|
||||
|
||||
// Try to find new sheduler place.
|
||||
process_pid = process_alloc(&(*process_new));
|
||||
if (*process_new == NULL)
|
||||
new_pid = process_alloc(&process_new);
|
||||
if (new_pid != 0)
|
||||
return (-1);
|
||||
|
||||
// Initialize context.
|
||||
|
||||
// Try to create user stack
|
||||
process_new->memory.stack.size.user = process_current->;
|
||||
process_new->memory.stack.user = (uint32_t)pm_alloc(process_new->memory.stack.size.user);
|
||||
if (process_new->memory.stack.user == 0x00000000)
|
||||
{
|
||||
process_free(process_new);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Try to create kernel stack
|
||||
process_new->memory.stack.size.kernel = process_current->memory.stack.size.kernel;
|
||||
process_new->memory.stack.kernel = (uint32_t)pm_alloc(process_new->memory.stack.size.kernel);
|
||||
if (process_new->memory.stack.kernel == 0x00000000)
|
||||
{
|
||||
pm_free(process_new->memory.stack.user);
|
||||
process_free(process_new);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
//TODO: dump stack data
|
||||
//TODO: dump code data
|
||||
//TODO: Initialize context.
|
||||
return (-1);
|
||||
}*/
|
||||
|
|
|
@ -12,35 +12,36 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
|||
DBG_WAIT;
|
||||
}
|
||||
|
||||
static const void *sys_handler[15] = {
|
||||
static const void *sys_handler[16] = {
|
||||
// Kernel Test
|
||||
sys_test, //restart
|
||||
sys_test, // test
|
||||
|
||||
// Process
|
||||
NULL, //exit
|
||||
sys_waitpid, //waitpid
|
||||
NULL, //exec
|
||||
sys_exit, // exit
|
||||
sys_fexecve, // fexecve
|
||||
sys_waitpid, // waitpid
|
||||
|
||||
// VFS
|
||||
sys_read, //read
|
||||
sys_write, //write
|
||||
sys_open, //open
|
||||
sys_close, //close
|
||||
sys_lseek, //lseek
|
||||
sys_read, // read
|
||||
sys_write, // write
|
||||
sys_open, // open
|
||||
sys_close, // close
|
||||
sys_lseek, // lseek
|
||||
|
||||
// Display
|
||||
kvram_display, //kvram_display
|
||||
kvram_clear, //kvram_clear
|
||||
kvram_print, //kvram_print
|
||||
kvram_ascii, //kvram_ascii
|
||||
kvram_reverse, //kvram_reverse
|
||||
kvram_scroll //kvram_scroll
|
||||
kvram_display, // kvram_display
|
||||
kvram_clear, // kvram_clear
|
||||
printk, // printk
|
||||
kvram_ascii, // kvram_ascii
|
||||
kvram_reverse, // kvram_reverse
|
||||
kvram_scroll, // kvram_scroll
|
||||
kvram_clr_str_area // kvram_clr_str_area
|
||||
};
|
||||
|
||||
void *sys_get_handler(int sysno)
|
||||
{
|
||||
// Check sysno validity
|
||||
if (sysno < 0 || sysno >= 14)
|
||||
if (sysno < 0 || sysno >= 16)
|
||||
return (0);
|
||||
|
||||
// DEBUG
|
||||
|
|
|
@ -31,6 +31,7 @@ _syscall_pre:
|
|||
! Switch register bank and allow interrupt
|
||||
! @note: user context has been saved
|
||||
! during the `exception_handler_pre`
|
||||
! TODO: do not allow interrupt ?
|
||||
mov.l .sr_mask, r1 ! get SR mask for BL and IMASK
|
||||
and r1, r0 ! set SR.BL = 0, SR.RB = 0 and SR.IMASK = 0b0000
|
||||
ldc r0, sr ! update SR regsiter
|
||||
|
|
|
@ -133,42 +133,49 @@ void kvram_reverse(int x, int y, int width, int height)
|
|||
atomic_stop();
|
||||
}
|
||||
|
||||
/* kvram_print() - Print string on Video RAM */
|
||||
void kvram_print(int x, int y, char const *str)
|
||||
/* kvram_clr_str_area() - Clear area based on kernel font size on Video RAM */
|
||||
//FIXME: secure
|
||||
void kvram_clr_str_area(int x, int y, int width, int height)
|
||||
{
|
||||
int default_pos_x;
|
||||
int starting_x;
|
||||
int i;
|
||||
uint32_t vram_offset_y;
|
||||
int cur_x;
|
||||
int cur_y;
|
||||
|
||||
// Initialize part
|
||||
i = -1;
|
||||
starting_x = x;
|
||||
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
|
||||
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
|
||||
default_pos_x = x;
|
||||
width = width * (KERNEL_FONT_REAL_WIDTH + 1);
|
||||
height = height * (KERNEL_FONT_REAL_HEIGHT + 1);
|
||||
|
||||
// Walk into string and display character by character
|
||||
while (str[++i] != '\0')
|
||||
// Get VRAM offset
|
||||
vram_offset_y = y << 2;
|
||||
|
||||
//DEbug
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "kvram_clr_str_area debug !");
|
||||
printk(0, 1, "x = %d", x);
|
||||
printk(0, 2, "y = %d", y);
|
||||
printk(0, 3, "width = %d", width);
|
||||
printk(0, 4, "height = %d", height);
|
||||
kvram_display();
|
||||
DBG_WAIT;*/
|
||||
|
||||
// Clear area, pixel per pixel x____x
|
||||
// TODO: update me !!!!
|
||||
cur_y = -1;
|
||||
while (++cur_y < height)
|
||||
{
|
||||
// New line
|
||||
if (str[i] == '\n')
|
||||
cur_x = -1;
|
||||
while (++cur_x < width)
|
||||
{
|
||||
y = y + KERNEL_FONT_REAL_HEIGHT + 1;
|
||||
x = default_pos_x;
|
||||
continue;
|
||||
}
|
||||
// Horizontal tab
|
||||
if (str[i] == '\t')
|
||||
{
|
||||
x = x / (KERNEL_FONT_REAL_WIDTH + 1);
|
||||
x = (x + (4 - ((x - starting_x) & 3))) * (KERNEL_FONT_REAL_WIDTH + 1);
|
||||
continue;
|
||||
vram[((x + cur_x) >> 5) + vram_offset_y] &=
|
||||
~(0x80000000 >> ((x + cur_x) & 31));
|
||||
}
|
||||
|
||||
// Default, display character
|
||||
font_draw(x, y, str[i]);
|
||||
x = x + KERNEL_FONT_REAL_WIDTH + 1;
|
||||
// update internal counter
|
||||
vram_offset_y = vram_offset_y + 4;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* kvram_ascii() - Draw ASCII character into Video RAM */
|
||||
|
|
|
@ -1,10 +1,39 @@
|
|||
#include <kernel/util.h>
|
||||
#include <kernel/hardware/tmu.h>
|
||||
#include <kernel/devices/timer.h>
|
||||
#include <kernel/atomic.h>
|
||||
|
||||
//TODO: update !
|
||||
int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
|
||||
// Internal timer "cache".
|
||||
struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
|
||||
__attribute__((constructor))
|
||||
void timer_constructor(void)
|
||||
{
|
||||
// Initialise internal cache
|
||||
for (int i = 0 ; i < TIMER_NUMBER ; i = i + 1)
|
||||
{
|
||||
timercache[i].status = TIMER_UNUSED;
|
||||
timercache[i].callback = NULL;
|
||||
timercache[i].arg = NULL;
|
||||
}
|
||||
|
||||
// Configure TMU
|
||||
SH7305_TMU.TSTR.STR0 = 0; // Stop timer 0
|
||||
SH7305_TMU.TSTR.STR1 = 0; // Stop timer 1
|
||||
SH7305_TMU.TSTR.STR2 = 0; // Stop timer 2
|
||||
|
||||
// Configure TMU timers
|
||||
for (int i = 0 ; i < 3 ; ++i)
|
||||
{
|
||||
SH7305_TMU.TIMER[i].TCOR = 0xffffffff; // Reset timer constant register
|
||||
SH7305_TMU.TIMER[i].TCNT = 0xffffffff; // Reset timer counter
|
||||
SH7305_TMU.TIMER[i].TCR.UNF = 0; // Clear interrupt flags
|
||||
SH7305_TMU.TIMER[i].TCR.UNIE = 0; // Disable timerinterrupt
|
||||
SH7305_TMU.TIMER[i].TCR.CKREG = 0b00; // Count on rising edge
|
||||
SH7305_TMU.TIMER[i].TCR.TPSC = 0b000; // Select P/4 prescaler
|
||||
}
|
||||
}
|
||||
|
||||
int timer_install(void *callback, void *arg, uint32_t ticks, uint8_t mode)
|
||||
{
|
||||
extern struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
int timer_ID;
|
||||
|
@ -20,6 +49,12 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
|
|||
if (timer_ID >= TIMER_NUMBER)
|
||||
return (-1);
|
||||
|
||||
// Debug !!
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "Timer find: %d\n", timer_ID);
|
||||
printk(0, 1, "TMU = %p\n", &SH7305_TMU.TIMER[timer_ID]);
|
||||
kvram_display();
|
||||
DBG_WAIT;*/
|
||||
|
||||
// Initialise internal timer data.
|
||||
timercache[timer_ID].callback = callback;
|
||||
|
@ -29,12 +64,11 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
|
|||
// Initialise hardware module.
|
||||
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID); // Stop timer.
|
||||
|
||||
// Convert delay in millisecond into timer tick.
|
||||
// TODO !!
|
||||
SH7305_TMU.TIMER[timer_ID].TCOR = delay_ms * 2000;
|
||||
SH7305_TMU.TIMER[timer_ID].TCNT = delay_ms * 2000;
|
||||
SH7305_TMU.TIMER[timer_ID].TCR.TPSC = 0b000; // TODO use appropriate divisor !
|
||||
// Setup Timer
|
||||
SH7305_TMU.TIMER[timer_ID].TCOR = ticks;
|
||||
SH7305_TMU.TIMER[timer_ID].TCNT = ticks;
|
||||
|
||||
// Configure timer
|
||||
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Clear interrupt flag.
|
||||
SH7305_TMU.TIMER[timer_ID].TCR.UNIE = 1; // Enable interrupt.
|
||||
|
||||
|
@ -48,7 +82,6 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
|
|||
return (timer_ID);
|
||||
}
|
||||
|
||||
//TODO: update !
|
||||
int timer_uninstall(int timer_ID)
|
||||
{
|
||||
extern struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
|
@ -71,6 +104,27 @@ int timer_uninstall(int timer_ID)
|
|||
|
||||
// Free'd timer cache.
|
||||
timercache[timer_ID].status = TIMER_UNUSED;
|
||||
timercache[timer_ID].callback = NULL;
|
||||
timercache[timer_ID].arg = NULL;
|
||||
|
||||
// Stop atomic operation and return.
|
||||
atomic_stop();
|
||||
return (0);
|
||||
}
|
||||
|
||||
int timer_start(int timer_ID)
|
||||
{
|
||||
extern struct timer_cache_s timercache[TIMER_NUMBER];
|
||||
|
||||
// Check bad ID
|
||||
if (timer_ID < 0 || timer_ID >= TIMER_NUMBER)
|
||||
return (-1);
|
||||
|
||||
// Start Atomic operation.
|
||||
atomic_start();
|
||||
|
||||
// Start hardware timer.
|
||||
SH7305_TMU.TSTR.BYTE |= 1 << timer_ID;
|
||||
|
||||
// Stop atomic operation and return.
|
||||
atomic_stop();
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _dclr_str_area
|
||||
.type _dclr_str_area, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_dclr_str_area:
|
||||
trapa #__NR_kvram_clr_str_area
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
.text
|
||||
.global _fexecve
|
||||
.type _fexecve, @function
|
||||
|
||||
#include "kernel/unistd_32.h"
|
||||
|
||||
.align 2
|
||||
_fexecve:
|
||||
trapa #__NR_fexecve
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -3,16 +3,16 @@
|
|||
## Project: Vhex - On-calc debugger
|
||||
## Author: yann.magnin@epitech.eu
|
||||
## ---
|
||||
include ../../global.mk
|
||||
include ../../../global.mk
|
||||
|
||||
##---
|
||||
## Static variables
|
||||
##--
|
||||
HEADER := -I../../include -I../../include/user
|
||||
LIBS := -L../lib/ -l_unistd -l_stdio -l_string -l_display
|
||||
BUILD := ../../build/user
|
||||
DEBUG := ../../debug
|
||||
OUTPUT := ../../output
|
||||
HEADER := -I../../../include -I../../../include/user
|
||||
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
|
||||
BUILD := ../../../build/user/shell
|
||||
DEBUG := ../../../debug
|
||||
OUTPUT := ../../../output
|
||||
|
||||
NAME := shell
|
||||
EXEC := $(OUTPUT)/$(NAME).elf
|
||||
|
@ -26,7 +26,7 @@ MEMORY_MAP := $(DEBUG)/$(NAME).map
|
|||
## Automated variables
|
||||
##---
|
||||
SRC :=
|
||||
DIRECTORY := $(shell find shell -not -path "*/\.*" -type d)
|
||||
DIRECTORY := $(shell find . -not -path "*/\.*" -type d)
|
||||
# Get all source files
|
||||
$(foreach path,$(DIRECTORY),$(eval \
|
||||
SRC += $(wildcard $(path)/*.c) \
|
||||
|
@ -34,7 +34,7 @@ $(foreach path,$(DIRECTORY),$(eval \
|
|||
$(wildcard $(path)/*.s) \
|
||||
))
|
||||
# Geneate all object files
|
||||
OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
|
||||
OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
|
||||
|
||||
|
||||
|
||||
|
@ -75,7 +75,7 @@ sec:
|
|||
## Automated rules
|
||||
##---
|
||||
define rule-src
|
||||
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
|
||||
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
|
||||
@ printf "compiling $(white)$$<$(nocolor)..."
|
||||
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
|
||||
@ printf "$(green)[ok]$(nocolor)\n"
|
|
@ -0,0 +1,43 @@
|
|||
#include <lib/unistd.h>
|
||||
#include <lib/display.h>
|
||||
#include <builtin.h>
|
||||
|
||||
int builtin_proc(void)
|
||||
{
|
||||
pid_t child;
|
||||
|
||||
// Debug
|
||||
dclear();
|
||||
dprint(0, 0, "Proc builtin !");
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 3000000 ; i++);
|
||||
|
||||
// Try to create first child
|
||||
/*child = fork();
|
||||
if (child == -1)
|
||||
{
|
||||
dprint(0, 1, "fork() fail !");
|
||||
dupdate();
|
||||
for (int i = 0 ; i < 3000000 ; i++);
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Check parent
|
||||
if (child_pid != 0)
|
||||
{
|
||||
int counter = 0;
|
||||
while (1)
|
||||
{
|
||||
dprint(0, 1, "parent: %d", counter++);
|
||||
for (int i = 0 ; i < 3000000 ; i++);
|
||||
}
|
||||
} else {
|
||||
int counter = 0;
|
||||
while (1)
|
||||
{
|
||||
dprint(0, 2, "child: %d", counter++);
|
||||
for (int i = 0 ; i < 9000000 ; i++);
|
||||
}
|
||||
}*/
|
||||
return (0);
|
||||
}
|
|
@ -27,11 +27,6 @@ SECTIONS
|
|||
.rodata : {
|
||||
*(.rodata);
|
||||
*(.rodata.*);
|
||||
|
||||
/* Builtin */
|
||||
_bbuiltin_section = ALIGN(4) ;
|
||||
*(.builtin);
|
||||
_ebuiltin_section = . ;
|
||||
}
|
||||
|
||||
.data ALIGN(4) : {
|
|
@ -1,48 +1,88 @@
|
|||
#include "util.h"
|
||||
#include "builtin.h"
|
||||
#include <lib/string.h>
|
||||
#include <lib/display.h>
|
||||
#include <lib/unistd.h>
|
||||
|
||||
// Internal builtin list
|
||||
// FIXME: due to PIE binary format, we can not
|
||||
// FIXME: use address of builtin_proc !!
|
||||
/*struct builtin_s list[1] = {
|
||||
{
|
||||
.name = "proc",
|
||||
.entry = (void*)&builtin_proc
|
||||
},
|
||||
//{
|
||||
// .name = "ram",
|
||||
// .entry = (void *)&builtin_ram
|
||||
//}
|
||||
};*/
|
||||
|
||||
|
||||
//TODO: use agc, argv.
|
||||
int check_builtin(char *cmd)
|
||||
{
|
||||
extern uint32_t bbuiltin_section;
|
||||
extern uint32_t ebuiltin_section;
|
||||
struct builtin_s *list;
|
||||
int wstatus;
|
||||
//pid_t pid;
|
||||
int i;
|
||||
|
||||
i = -1;
|
||||
list = (void*)&bbuiltin_section;
|
||||
while ((uint32_t)&list[++i] < (uint32_t)&ebuiltin_section)
|
||||
// Process test
|
||||
dclear();
|
||||
dprint(0, 0, "Process Load Test !");
|
||||
|
||||
// Load process test
|
||||
pid_t pid = fexecve("/mnt/smemfs/VHEX/test.elf");
|
||||
if (pid < 0)
|
||||
{
|
||||
dprint(0, 1, "Process error !");
|
||||
dupdate();
|
||||
for(int i = 0 ; i < 3000000 ; ++i);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
dclear();
|
||||
dprint(0, 0, "Process Test !");;
|
||||
while (1)
|
||||
{
|
||||
dclr_str_area(0, 1, 20, 1);
|
||||
dprint(0, 1, "P process: %d", counter);
|
||||
dupdate();
|
||||
counter = counter + 1;
|
||||
for (int i = 0 ; i < 30000 ; ++i);
|
||||
}
|
||||
|
||||
//int wstatus;
|
||||
//pid_t pid;
|
||||
//int i;
|
||||
|
||||
// Try to find builtin
|
||||
/* for (int i = 0 ; i < 1 ; i++)
|
||||
{
|
||||
if (strcmp(list[i].name, cmd) != 0)
|
||||
continue;
|
||||
|
||||
|
||||
// Execute builtin
|
||||
list[i].entry(0, NULL);
|
||||
return (0);
|
||||
}
|
||||
}*/
|
||||
return (-1);
|
||||
// Create subprocess
|
||||
//pid = fork();
|
||||
//if (pid < 0)
|
||||
// return (1);
|
||||
|
||||
// If we are the child execute
|
||||
// the builtins.
|
||||
//if (pid == 0)
|
||||
// //{
|
||||
// dclear();
|
||||
// dprint(0, 0, "Child process !!");
|
||||
// dprint(0, 1, "PID = %d", getpid());
|
||||
// dprint(0, 2, "PPID = %d", getppid());
|
||||
// dupdate();
|
||||
// Create subprocess
|
||||
//pid = fork();
|
||||
//if (pid < 0)
|
||||
// return (1);
|
||||
|
||||
// If we are the child execute
|
||||
// the builtins.
|
||||
//if (pid == 0)
|
||||
// //{
|
||||
// dclear();
|
||||
// dprint(0, 0, "Child process !!");
|
||||
// dprint(0, 1, "PID = %d", getpid());
|
||||
// dprint(0, 2, "PPID = %d", getppid());
|
||||
// dupdate();
|
||||
|
||||
// } else {
|
||||
// waitpid(pid, &wstatus, WCONTINUED);
|
||||
//TODO: signal handling.
|
||||
//TODO: signal handling.
|
||||
// }
|
||||
// }
|
||||
// return (1);
|
||||
}
|
||||
// }
|
||||
// return (1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
#!/usr/bin/make -f
|
||||
## ---
|
||||
## Project: Vhex - On-calc debugger
|
||||
## Author: yann.magnin@epitech.eu
|
||||
## ---
|
||||
include ../../../global.mk
|
||||
|
||||
##---
|
||||
## Static variables
|
||||
##--
|
||||
HEADER := -I../../../include -I../../../include/user
|
||||
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
|
||||
BUILD := ../../../build/user/test
|
||||
DEBUG := ../../../debug
|
||||
OUTPUT := ../../../output
|
||||
|
||||
NAME := test
|
||||
EXEC := $(OUTPUT)/$(NAME).elf
|
||||
LDFLAG := -T $(NAME).ld
|
||||
MEMORY_MAP := $(DEBUG)/$(NAME).map
|
||||
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## Automated variables
|
||||
##---
|
||||
SRC :=
|
||||
DIRECTORY := $(shell find . -not -path "*/\.*" -type d)
|
||||
# Get all source files
|
||||
$(foreach path,$(DIRECTORY),$(eval \
|
||||
SRC += $(wildcard $(path)/*.c) \
|
||||
$(wildcard $(path)/*.S) \
|
||||
$(wildcard $(path)/*.s) \
|
||||
))
|
||||
# Geneate all object files
|
||||
OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
|
||||
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## General rules
|
||||
##---
|
||||
all: | $(BUILD) $(DEBUG) $(EXEC)
|
||||
|
||||
$(EXEC): $(OBJ)
|
||||
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) -lgcc > $(MEMORY_MAP)
|
||||
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
|
||||
rm -f $(DEBUG)/$(NAME).elf.big
|
||||
|
||||
$(BUILD) $(DEBUG):
|
||||
@ printf "Create $(blue)$@$(nocolor) directory\n"
|
||||
@ mkdir -p $@
|
||||
|
||||
install: $(EXEC)
|
||||
sudo p7 send --force -d VHEX $^
|
||||
|
||||
check:
|
||||
@ echo 'src: $(SRC)'
|
||||
@ echo 'obj: $(OBJ)'
|
||||
@ echo 'directory: $(DIRECTORY)'
|
||||
|
||||
asm:
|
||||
@ $(OBJDUMP) -D $(EXEC) | less
|
||||
|
||||
map:
|
||||
@ cat $(MEMORY_MAP) | less
|
||||
|
||||
sec:
|
||||
@ $(OBJDUMP) -h $(EXEC)
|
||||
|
||||
|
||||
##---
|
||||
## Automated rules
|
||||
##---
|
||||
define rule-src
|
||||
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
|
||||
@ printf "compiling $(white)$$<$(nocolor)..."
|
||||
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
|
||||
@ printf "$(green)[ok]$(nocolor)\n"
|
||||
endef
|
||||
|
||||
$(foreach source,$(SRC),$(eval \
|
||||
$(call rule-src,$(source))) \
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
##---
|
||||
## Cleaning rules
|
||||
##---
|
||||
clean:
|
||||
rm -rf $(BUILD)
|
||||
rm -rf $(DEBUG)
|
||||
|
||||
fclean: clean
|
||||
rm -f $(EXEC)
|
||||
|
||||
re: fclean all
|
||||
|
||||
|
||||
|
||||
|
||||
.PHONY: re fclean clean all install
|
|
@ -1,8 +1,19 @@
|
|||
/*#include <kernel/syscall.h>
|
||||
#include <lib/display.h>
|
||||
|
||||
void test(void)
|
||||
int main(void)
|
||||
{
|
||||
uint8_t *vram;
|
||||
uint32_t counter = 0;
|
||||
while (1)
|
||||
{
|
||||
// Display data
|
||||
dclr_str_area(0, 2, 20, 1);
|
||||
dprint(0, 2, "C process: %d", counter);
|
||||
dupdate();
|
||||
|
||||
vram = casio_Bdisp_GetVRAM();
|
||||
}*/
|
||||
// Update counter and "wait"
|
||||
counter = counter + 1;
|
||||
if (counter >= 100)
|
||||
counter = 0;
|
||||
for (int i = 0 ; i < 300000 ; ++i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
OUTPUT_ARCH(sh3)
|
||||
OUTPUT_FORMAT(elf32-sh)
|
||||
ENTRY(_main)
|
||||
|
||||
/*
|
||||
** Linker script for user executables.
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
/* virtual memory, read-write segment */
|
||||
userram (WX) : o = 0x00000000, l = 256k
|
||||
}
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD ;
|
||||
data PT_LOAD ;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text : {
|
||||
*(.text);
|
||||
*(.text.*);
|
||||
} : text
|
||||
|
||||
.rodata : {
|
||||
*(.rodata);
|
||||
*(.rodata.*);
|
||||
}
|
||||
|
||||
.data ALIGN(4) : {
|
||||
*(.plt);
|
||||
*(.data);
|
||||
*(.data.*);
|
||||
|
||||
/* bss section included to avoid missaligned segment */
|
||||
*(.bss);
|
||||
*(.bss.*);
|
||||
*(COMMON);
|
||||
} : data
|
||||
|
||||
|
||||
.relocgot : {
|
||||
BRELOC_GOT = . ;
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
ERELOC_GOT = . ;
|
||||
}
|
||||
|
||||
/* unwanted section */
|
||||
/DISCARD/ : {
|
||||
*(.debug_info)
|
||||
*(.debug_abbrev)
|
||||
*(.debug_loc)
|
||||
*(.debug_aranges)
|
||||
*(.debug_ranges)
|
||||
*(.debug_line)
|
||||
*(.debug_str)
|
||||
*(.jcr)
|
||||
*(.eh_frame_hdr)
|
||||
*(.eh_frame)
|
||||
*(.comment)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
.global _test
|
||||
/*.global _test
|
||||
.type _test, @function
|
||||
|
||||
.align 2
|
||||
|
@ -20,4 +20,4 @@ _test:
|
|||
.align 4
|
||||
.syscall_entry: .long 0xa0010070
|
||||
.syscall_vram: .long 0x00000135
|
||||
.end
|
||||
.end*/
|
||||
|
|
Loading…
Reference in New Issue