Fix TTY read / write primitives

This commit is contained in:
Yann MAGNIN 2019-12-20 11:31:34 +01:00
parent 2a65492bca
commit df00142f07
16 changed files with 297 additions and 135 deletions

View File

@ -7,7 +7,7 @@
##---
## Static variables
##--
HEADER := include
HEADER := -Iinclude -Iinclude/user
BUILD := build
DEBUG := debug
@ -62,7 +62,7 @@ OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
all: | $(BUILD) $(DEBUG) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) -I $(HEADER) -lgcc > $(MEMORY_MAP)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin
$(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON)
@ -94,7 +94,7 @@ sec:
define rule-src
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< -I $(HEADER) -lgcc
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef

View File

@ -8,12 +8,12 @@
// Define default buffer size.
// TODO: remove me ?
#define TTY_BUFFER_LINES (DISPLAY_SCREEN_WIDTH * 3)
#define TTY_BUFFER_COLUMNS (DISPLAY_SCREEN_HEIGHT)
#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3)
#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX)
struct tty_s
{
char buffer[TTY_BUFFER_LINES][TTY_BUFFER_COLUMNS];
char buffer[TTY_BUFFER_LINES + 1][TTY_BUFFER_COLUMNS + 1];
struct {
int16_t x;
int16_t y;
@ -56,4 +56,9 @@ extern ssize_t tty_write(const void *buffer, size_t count);
extern ssize_t tty_read(void *buffer, size_t count);
extern int tty_close(void);
// IOCTL.
#define TTY_IOCTL_GETDX (0x00)
#define TTY_IOCTL_GETDY (0x01)
extern void tty_ioctl(uint32_t cmd, ...);
#endif /*__KERNEL_TTY_H__*/

24
include/user/builtin.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __USER_BUILTIN_H__
# define __USER_BUILTIN_H__
#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
{
char name[10];
int (*entry)(int argc, char **argv);
};
#endif /*__USER_BUILTIN_H__*/

9
include/user/util.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef __USER_UTIL_H__
# define __USER_UTIL_H__
#include <stddef.h>
#include <stdint.h>
extern int check_builtin(char *cmd);
#endif /*__USER_UTIL_H__*/

View File

@ -39,7 +39,15 @@ extern mpu_t mpu_get(void);
extern int main(void);
/* TODO: explain !! */
//
// rom_explore() - explore all add-in ROM part.
// @note:
// For now, we can not use the MMU so we can
// not handle TLB miss. Casio load only the first 4ko
// of the add-in. To avoid TLB miss we explore all
// add-in binary to force Casio to generate all pages
// into the TLB.
//
static void rom_explore(volatile void *rom, int32_t size)
{
uint8_t unused;
@ -53,6 +61,7 @@ static void rom_explore(volatile void *rom, int32_t size)
}
}
/* section_execute() - Used to execute contructors and destructors */
static void section_execute(void *bsection, void *esection)
{
while ((uint32_t)bsection < (uint32_t)esection)
@ -62,10 +71,11 @@ static void section_execute(void *bsection, void *esection)
}
}
/* start() - Kernel entry point */
__attribute__((section(".pretext")))
int start(void)
{
unsigned int key;
int error;
// Wipe .bss section and dump .data / Vhex sections
@ -91,14 +101,14 @@ int start(void)
// before switching the VBR.
rom_explore(&brom, (int32_t)&srom);
// Get Casio's hardware context and set
// Save Casio's hardware context and set
// Vhex hardware context.
// @note:
// This operation should be atomic
// because if an interruption or exception
// occur during the hardware context change
// the calculator will crash.
// And this is why between each `atomic_start`
// And this is why between each `atomic_start`
// and `atomic_end()` the code *SHOULD* be
// exception safe.
atomic_start();

View File

@ -43,8 +43,9 @@ void vhex_context_set(void)
SH7305_KEYSC.AUTOFIX.UNKNOWN0 = 0b100; // Unknown, use Casio's value. (autofix)
SH7305_KEYSC.AUTOFIX.UNKNOWN1 = 0b10; // Unknown, use Casio's value. (autofix)
SH7305_KEYSC.SCAN_MODE.UNKNOWN = 0b001; // Unknown, use Casio's value. (scan mode)
SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000100; // Interrupt when one key is pressed or released.
SH7305_KEYSC.SCAN_WAIT.TIME = 0x00; // No time between each interrupt.
//SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000100; // Interrupt when keys are pressed or released.
SH7305_KEYSC.INTERRUPT.KYCPU_IE = 0b0000010; // Falling + pressed + rising.
SH7305_KEYSC.SCAN_WAIT.TIME = 0x05; // No time between each interrupt.
SH7305_KEYSC.SCAN_INTERVAL = 0x98; // Unknown, use Casio's value. (scan interval)
SH7305_KEYSC.KYOUTDR.KYO5DT = 0b11; // Trigger when high-impedance state is detected.
SH7305_KEYSC.KYOUTDR.KYO4DT = 0b11; // Trigger when high-impedance state is detected.
@ -58,7 +59,7 @@ void vhex_context_set(void)
SH7305_KEYSC.KYINDR.KYDIR3 = 1; // Scan [F4],[MENU],[EXIT],[sin],[)],[DEL],[x],[+],[(-)]
SH7305_KEYSC.KYINDR.KYDIR2 = 1; // Scan [F5],[left],[down],[cos],[,],[%],[-],[EXE]
SH7305_KEYSC.KYINDR.KYDIR1 = 1; // Scan [F6],[up],[right],[tan],[->]
SH7305_INTC.IPRF.KEYSC = 15; // Set KEYSC interrupt priority (max).
SH7305_INTC.IPRF.KEYSC = 10; // Set KEYSC interrupt priority (max).
SH7305_INTC.IMCR5.KEYI = 1; // Clear KEYSC interrupt mask.
// Configure power / sleep mode.

View File

@ -0,0 +1,43 @@
#include <kernel/devices/tty.h>
#include <stdarg.h>
void tty_ioctl(uint32_t cmd, ...)
{
extern struct tty_s tty;
va_list ap;
va_start(ap, cmd);
switch (cmd)
{
case TTY_IOCTL_GETDX:
{
int *dx = va_arg(ap, int*);
*dx = tty.cursor.x * (KERNEL_FONT_REAL_WIDTH + 1);
break;
}
case TTY_IOCTL_GETDY:
{
int *dy = va_arg(ap, int*);
int start = tty.cursor.y;
int saved_start;
int line = -1;
while (++line < DISPLAY_VCHAR_MAX - 1)
{
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty.cursor.max.y : start - 1;
// Check if the line existe.
if (tty.buffer[start][0] == '\0')
{
start = saved_start;
break;
}
}
*dy = line * (KERNEL_FONT_REAL_HEIGHT + 1);
break;
}
}
va_end(ap);
}

View File

@ -25,6 +25,7 @@ int tty_open(void)
// Set TTY primitives
// TODO: Add USB primitives
// TODO: update this part.
tty.primitives.write = &display_write;
tty.primitives.read = &keyboard_read;

View File

@ -10,18 +10,21 @@
// Intenral functions
static void wait_keyboard_event(void);
static int check_special(struct keyboard_obj_s *keyboard);
static int check_signal(struct keyboard_obj_s *keyboard);
static int check_special(struct keyboard_obj_s *keyboard, key_t key);
static int check_signal(struct keyboard_obj_s *keyboard, key_t key);
static void tty_buffer_display(struct keyboard_obj_s *keyboard);
static void update_buffer(struct keyboard_obj_s *keyboard);
static int update_buffer(struct keyboard_obj_s *keyboard, key_t key);
static int buffer_insert(struct keyboard_obj_s *keyboard, char n);
static void cursor_callback(struct keyboard_obj_s *keyboard);
//FIXME: this function is device-specifique !!
ssize_t tty_read(void *buffer, size_t count)
{
struct keyboard_obj_s keyboard;
extern struct keycache_s *keylist;
extern struct tty_s tty;
struct keycache_s *keynode;
struct keyboard_obj_s keyboard;
int first_key;
int timer_fd;
// Check potential error.
@ -43,6 +46,8 @@ ssize_t tty_read(void *buffer, size_t count)
// Initialize timer for cursor.
timer_fd = timer_install(&cursor_callback, &keyboard, 500, 1);
if (timer_fd == -1)
return (0);
// Main Loop, wait [EXE] key.
while ((keyboard.mode & 0x04) == 0)
@ -54,10 +59,23 @@ ssize_t tty_read(void *buffer, size_t count)
// signal, special key then update
// the buffer.
atomic_start();
if (check_signal(&keyboard) == 0 &&
check_special(&keyboard) == 0)
keynode = keylist;
first_key = 0;
while (keynode != NULL && (keynode->counter == 1 ||
(first_key == 0 &&
keynode->counter > 10 &&
(keynode->counter & 1) == 0)))
{
update_buffer(&keyboard);
// Repeat key flags.
first_key = 1;
// Handle current key
if (check_signal(&keyboard, keynode->keycode) == 0 &&
check_special(&keyboard, keynode->keycode) == 0)
update_buffer(&keyboard, keynode->keycode);
// Get next key.
keynode = keynode->next;
}
atomic_end();
@ -72,13 +90,14 @@ ssize_t tty_read(void *buffer, size_t count)
return (keyboard.buffer.clen);
}
//FIXME: function driver specific !
static void wait_keyboard_event(void)
{
extern volatile uint8_t keylist_isUpdate;
// Wait key list update.
// @note:
// To avoid reentrace data corruption
// To ensure reentrace and avoid data corruption
// we should wait kernel indication.
// TODO: explain correctly x)
while (keylist_isUpdate == 0)
@ -88,37 +107,43 @@ static void wait_keyboard_event(void)
keylist_isUpdate = 0;
}
static int check_signal(struct keyboard_obj_s *keyboard)
static int check_signal(struct keyboard_obj_s *keyboard, key_t key)
{
//TODO
(void)key;
(void)keyboard;
return (0);
}
static int check_special(struct keyboard_obj_s *keyboard)
static int check_special(struct keyboard_obj_s *keyboard, key_t key)
{
extern fx9860_context_t casio_context;
extern fx9860_context_t vhex_context;
extern struct keycache_s *keylist;
struct keycache_s *keynode;
unsigned int key;
unsigned int tmp;
// Find key code.
keynode = keylist;
while (keynode != NULL)
switch (key)
{
// Check MAJ.
if (keynode->keycode == KEY_ALPHA && keynode->counter == 1)
case KEY_ALPHA:
{
keyboard->mode = keyboard->mode ^ 0x02;
return (1);
}
// Check Alpha / num mode.
if (keynode->keycode == KEY_SHIFT && keynode->counter == 1)
case KEY_SHIFT:
{
keyboard->mode = keyboard->mode ^ 0x01;
return (1);
}
// Check DEL key.
if (keynode->keycode == KEY_DEL && keyboard->buffer.cursor > 0)
case KEY_DEL:
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
// Move seconde part.
memcpy(
&keyboard->buffer.addr[keyboard->buffer.cursor - 1],
@ -130,10 +155,12 @@ static int check_special(struct keyboard_obj_s *keyboard)
keyboard->buffer.clen = keyboard->buffer.clen - 1;
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
return (1);
}
// Check MENU key.
if (keynode->keycode == KEY_MENU && keynode->counter == 1)
// TODO: fix me !
case KEY_MENU:
{
// Save current Vhex context and restore Casio's context.
atomic_start();
@ -155,10 +182,11 @@ static int check_special(struct keyboard_obj_s *keyboard)
fx9860_context_save(&casio_context);
fx9860_context_restore(&vhex_context);
atomic_end();
return (1);
}
// Check EXE key.
if (keynode->keycode == KEY_EXE && keynode->counter == 1)
case KEY_EXE:
{
// Add new line character.
keyboard->buffer.addr[keyboard->buffer.clen] = '\n';
@ -171,24 +199,28 @@ static int check_special(struct keyboard_obj_s *keyboard)
}
// Check LEFT key.
if (keynode->keycode == KEY_LEFT &&
keynode->counter == 1 &&
keyboard->buffer.cursor > 0)
case KEY_LEFT:
{
// Check potential error.
if (keyboard->buffer.cursor <= 0)
return (1);
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
return (1);
}
// Check RIGHT key.
if (keynode->keycode == KEY_RIGHT &&
keynode->counter == 1 &&
keyboard->buffer.cursor < keyboard->buffer.clen)
case KEY_RIGHT:
{
if (keyboard->buffer.cursor >= keyboard->buffer.clen)
return (1);
// Move cursor.
keyboard->buffer.cursor = keyboard->buffer.cursor + 1;
return (1);
}
//TODO: AC/on
// get next keynode
keynode = keynode->next;
default: break;
}
return (0);
}
@ -208,18 +240,11 @@ static void tty_buffer_display(struct keyboard_obj_s *keyboard)
? keyboard->buffer.clen + 1
: keyboard->buffer.clen;
// Write buffer.
tty_write(keyboard->buffer.addr, size);
// Check Y-axis udpate.
// TODO !!!
//if (keyboard->saved.tty.cursor.y < tty.cursor.y)
// keyboard->saved.tty.cursor.y -=
// tty.cursor.y - keyboard->saved.tty.cursor.y;
}
static void update_buffer(struct keyboard_obj_s *keyboard)
static int update_buffer(struct keyboard_obj_s *keyboard, key_t key)
{
static const uint8_t keylist_alpha[] = {
KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN,
@ -234,12 +259,10 @@ static void update_buffer(struct keyboard_obj_s *keyboard)
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV,
KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER,
KEY_DOT, KEY_FD, KEY_UNUSED
KEY_DOT, KEY_FD, KEY_ARROW, KEY_UNUSED
};
static const char keylist_num_char[] = "0123456789+-x/(),^.|";
extern struct keycache_s *keylist;
static const char keylist_num_char[] = "0123456789+-x/(),^.|_";
const uint8_t *keycode_list;
struct keycache_s *keynode;
char character;
int i;
@ -249,33 +272,22 @@ static void update_buffer(struct keyboard_obj_s *keyboard)
? keylist_alpha
: keylist_num;
// Walk into pressed key list
keynode = keylist;
while (keynode != NULL && keynode->counter == 1)
{
// Try to find the pressed key.
i = -1;
while (keycode_list[++i] != KEY_UNUSED &&
keycode_list[i] != keynode->keycode);
// If the key match, update buffer.
if (keycode_list[i] == keynode->keycode)
{
// Get the char to be written
if ((keyboard->mode & 1) == 0)
character = (keyboard->mode & 2) ? 'A' + i : 'a' + i;
else
character = keylist_num_char[i];
// Insert new character if possible.
// if not, return;
if (buffer_insert(keyboard, character) != 0)
return;
}
// Try to find the pressed key.
i = -1;
while (keycode_list[++i] != KEY_UNUSED && keycode_list[i] != key);
if (keycode_list[i] != key)
return (0);
// Get the next pressed key.
keynode = keynode->next;
}
// If the key match, update buffer.
// Get the char to be written
if ((keyboard->mode & 1) == 0)
character = (keyboard->mode & 2) ? 'A' + i : 'a' + i;
else
character = keylist_num_char[i];
// Insert new character if possible.
buffer_insert(keyboard, character);
return (1);
}
static int buffer_insert(struct keyboard_obj_s *keyboard, char n)
@ -310,17 +322,31 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
// Draw cursor if needed
if (keyboard->cvisible == 0)
{
// Geneate TTY buffer cursor position.
x = keyboard->buffer.cursor + keyboard->saved.tty.cursor.x;
y = x / tty.cursor.max.x;
x = x - (y * tty.cursor.max.x);
y = y + keyboard->saved.tty.cursor.y;
dreverse(
x * (KERNEL_FONT_REAL_WIDTH + 1),
y * (KERNEL_FONT_REAL_HEIGHT + 1),
(KERNEL_FONT_REAL_WIDTH + 1),
(KERNEL_FONT_REAL_HEIGHT + 1)
);
// Save current cursor position and
// resotre saved position.
int sttyx = tty.cursor.x;
int sttyy = tty.cursor.x;
tty.cursor.x = x;
tty.cursor.y = y;
// Get Display X and Y position.
tty_ioctl(TTY_IOCTL_GETDX, &x);
tty_ioctl(TTY_IOCTL_GETDY, &y);
// Display cursor.
dreverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1));
dupdate();
// Restore TTY cursor position
tty.cursor.x = sttyx;
tty.cursor.y = sttyy;
}
// Update cursor status.
keyboard->cvisible = keyboard->cvisible ^ 1;

View File

@ -11,7 +11,7 @@ static void tty_vertical_update(void)
{
// Get next line.
tty.cursor.y =
(tty.cursor.y + 1 < tty.cursor.max.y)
(tty.cursor.y + 1 <= tty.cursor.max.y)
? tty.cursor.y + 1
: 0;
@ -102,7 +102,7 @@ static ssize_t tty_buffer_update(const uint8_t *buffer, size_t count)
return (i);
}
// TODO: this function is device-specific !
// FIXME: this function is device-specific !
// TODO: Update me ?
static void tty_display(void)
{
@ -128,13 +128,10 @@ static void tty_display(void)
// Get the "first" line and number of line.
// @note: circular buffer.
line = 1;
line = 0;
start = tty.cursor.y;
while (line < DISPLAY_VCHAR_MAX - 1)
while (++line < DISPLAY_VCHAR_MAX)
{
// update line counter.
line = line + 1;
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty.cursor.max.y : start - 1;
@ -147,17 +144,6 @@ static void tty_display(void)
}
}
/* dclear();
dprint(0, 0, "start = %d", start);
dprint(0, 1, "line = %d", line);
dprint(0, 2, "vline = %d", DISPLAY_VCHAR_MAX);
dprint(0, 3, "hline = %d", DISPLAY_HCHAR_MAX);
dupdate();
for (int i = 0 ; i < 900000 ; i = i + 1);
dclear();
dupdate();*/
// Display "on-screen" string lines.
i = -1;
while (++i < line)
@ -174,9 +160,8 @@ static void tty_display(void)
// Display line.
tty.primitives.write(tty.buffer[start], line_len);
// Get "next" line.
start = (start + 1 < tty.cursor.max.y) ? start + 1 : 0;
start = (start + 1 > tty.cursor.max.y) ? 0 : start + 1;
}
// Display on screen.

View File

@ -1,33 +1,21 @@
#include <lib/stdio.h>
#include <lib/display.h>
#include "builtin.h"
#include <kernel/devices/ubc.h>
#include <kernel/devices/tty.h>
#include <kernel/hardware/power.h>
#include <kernel/syscall.h>
#include <lib/display.h>
// TODO: remove me !!
extern void test(void);
//TODO: add shell.
int main(void)
VHEX_BUILTIN(fxdb)
{
char input[12];
//TODO: handle parameter.
(void)argc;
(void)argv;
// Sleep test.
// Open TTY.
tty_open();
// Entry ! :D
tty_write("Boot Complete !\n", 16);
// Keyboard test.
while (1)
{
tty_write(">", 1);
tty_read(input, 12);
}
dclear();
dprint(0, 0, "FXDB - entry !!");
dupdate();
for (int i = 0 ; i < 9000000 ; i = i + 1);
return (0);
// Open User Break Controller.
// @note:
@ -44,12 +32,9 @@ int main(void)
// @note:
// Thus USC should be start after the jump.
//
//((void(*)(void))0x08100000)();
//((void(*)(void))&vhex_dbr)();
test();
// Power OFF UBC module.
ubc_close();
return (0);
}

37
src/user/shell/main.c Normal file
View File

@ -0,0 +1,37 @@
#include <kernel/devices/tty.h>
#include "util.h"
//TODO: documentation.
int main(void)
{
char input[12];
int cmd_size;
char **argv;
int argc;
// Open TTY.
tty_open();
// Entry ! :D
tty_write("Boot Complete !\n", 16);
// Shell main loop.
while (1)
{
// Get user command.
tty_write(">", 1);
cmd_size = tty_read(input, 12);
// Remove '\n' char.
// FIXME: create argc, argv !!
input[cmd_size - 1] = '\0';
// Check buit-in.
if (check_builtin(input) != 0)
{
tty_write(input, cmd_size - 1);
tty_write(": command not found\n", 20);
}
}
return (0);
}

View File

@ -0,0 +1,31 @@
#include "util.h"
#include "builtin.h"
#include <lib/string.h>
#include <lib/display.h>
//TODO: use agc, argv.
int check_builtin(char *cmd)
{
extern uint32_t bbuiltin_section;
extern uint32_t ebuiltin_section;
struct builtin_s *list;
int i;
i = -1;
list = (void*)&bbuiltin_section;
while ((uint32_t)&list[++i] < (uint32_t)&ebuiltin_section)
{
dclear();
dprint(0, 0, "builtin - %s", list[i].name);
dupdate();
for (int i = 0 ; i < 9000000 ; i = i + 1);
if (strcmp(list[i].name, cmd) == 0)
{
list[i].entry(0, NULL);
return (0);
}
}
return (1);
}

View File

@ -56,6 +56,11 @@ SECTIONS
*(SORT_BY_INIT_PRIORITY(.dtors.*))
*(.dtors);
_edtors = ALIGN(4) ;
/* Built-in */
_bbuiltin_section = ALIGN(4) ;
*(.builtin);
_ebuiltin_section = ALIGN(4) ;
} > rom : text