OSDN Git Service

Added KOZOS application.
authorShinichiro Nakamura <shinta.main.jp@gmail.com>
Fri, 13 Jul 2012 21:36:35 +0000 (06:36 +0900)
committerShinichiro Nakamura <shinta.main.jp@gmail.com>
Fri, 13 Jul 2012 21:36:35 +0000 (06:36 +0900)
61 files changed:
firm/sample/sample1/os/Makefile [new file with mode: 0644]
firm/sample/sample1/os/defines.h [new file with mode: 0644]
firm/sample/sample1/os/diskio.h [new file with mode: 0644]
firm/sample/sample1/os/driver.h [new file with mode: 0644]
firm/sample/sample1/os/driver_audio.c [new file with mode: 0644]
firm/sample/sample1/os/driver_audio.h [new file with mode: 0644]
firm/sample/sample1/os/driver_console.c [new file with mode: 0644]
firm/sample/sample1/os/driver_console.h [new file with mode: 0644]
firm/sample/sample1/os/driver_lcd.c [new file with mode: 0644]
firm/sample/sample1/os/driver_lcd.h [new file with mode: 0644]
firm/sample/sample1/os/driver_led.c [new file with mode: 0644]
firm/sample/sample1/os/driver_led.h [new file with mode: 0644]
firm/sample/sample1/os/driver_timer.c [new file with mode: 0644]
firm/sample/sample1/os/driver_timer.h [new file with mode: 0644]
firm/sample/sample1/os/integer.h [new file with mode: 0644]
firm/sample/sample1/os/interrupt.c [new file with mode: 0644]
firm/sample/sample1/os/interrupt.h [new file with mode: 0644]
firm/sample/sample1/os/intr.h [new file with mode: 0644]
firm/sample/sample1/os/kozos.c [new file with mode: 0644]
firm/sample/sample1/os/kozos.h [new file with mode: 0644]
firm/sample/sample1/os/ld.scr [new file with mode: 0644]
firm/sample/sample1/os/led.c [new file with mode: 0644]
firm/sample/sample1/os/led.h [new file with mode: 0644]
firm/sample/sample1/os/lib.c [new file with mode: 0644]
firm/sample/sample1/os/lib.h [new file with mode: 0644]
firm/sample/sample1/os/logo_20x16.bmp [new file with mode: 0644]
firm/sample/sample1/os/logo_30x24.bmp [new file with mode: 0644]
firm/sample/sample1/os/logo_40x32.bmp [new file with mode: 0644]
firm/sample/sample1/os/main.c [new file with mode: 0644]
firm/sample/sample1/os/memory.c [new file with mode: 0644]
firm/sample/sample1/os/memory.h [new file with mode: 0644]
firm/sample/sample1/os/mmc.c [new file with mode: 0644]
firm/sample/sample1/os/pff.c [new file with mode: 0644]
firm/sample/sample1/os/pff.h [new file with mode: 0644]
firm/sample/sample1/os/portconf.h [new file with mode: 0644]
firm/sample/sample1/os/re.c [new file with mode: 0644]
firm/sample/sample1/os/re.h [new file with mode: 0644]
firm/sample/sample1/os/serial.c [new file with mode: 0644]
firm/sample/sample1/os/serial.h [new file with mode: 0644]
firm/sample/sample1/os/sg12232c.c [new file with mode: 0644]
firm/sample/sample1/os/sg12232c.h [new file with mode: 0644]
firm/sample/sample1/os/spi.c [new file with mode: 0644]
firm/sample/sample1/os/spi.h [new file with mode: 0644]
firm/sample/sample1/os/spreg.c [new file with mode: 0644]
firm/sample/sample1/os/spreg.h [new file with mode: 0644]
firm/sample/sample1/os/startup.s [new file with mode: 0644]
firm/sample/sample1/os/sw.c [new file with mode: 0644]
firm/sample/sample1/os/sw.h [new file with mode: 0644]
firm/sample/sample1/os/syscall.c [new file with mode: 0644]
firm/sample/sample1/os/syscall.h [new file with mode: 0644]
firm/sample/sample1/os/task.h [new file with mode: 0644]
firm/sample/sample1/os/task_command.c [new file with mode: 0644]
firm/sample/sample1/os/task_command.h [new file with mode: 0644]
firm/sample/sample1/os/task_ir.c [new file with mode: 0644]
firm/sample/sample1/os/task_ir.h [new file with mode: 0644]
firm/sample/sample1/os/task_userinput.c [new file with mode: 0644]
firm/sample/sample1/os/task_userinput.h [new file with mode: 0644]
firm/sample/sample1/os/timer.c [new file with mode: 0644]
firm/sample/sample1/os/timer.h [new file with mode: 0644]
firm/sample/sample1/os/vs1011e.c [new file with mode: 0644]
firm/sample/sample1/os/vs1011e.h [new file with mode: 0644]

diff --git a/firm/sample/sample1/os/Makefile b/firm/sample/sample1/os/Makefile
new file mode 100644 (file)
index 0000000..1e7ae7e
--- /dev/null
@@ -0,0 +1,84 @@
+PREFIX  = /usr/local
+ARCH    = h8300-elf
+BINDIR  = $(PREFIX)/bin
+ADDNAME = $(ARCH)-
+
+VPATH=
+
+AR      = $(BINDIR)/$(ADDNAME)ar
+AS      = $(BINDIR)/$(ADDNAME)as
+CC      = $(BINDIR)/$(ADDNAME)gcc
+LD      = $(BINDIR)/$(ADDNAME)ld
+NM      = $(BINDIR)/$(ADDNAME)nm
+OBJCOPY = $(BINDIR)/$(ADDNAME)objcopy
+OBJDUMP = $(BINDIR)/$(ADDNAME)objdump
+RANLIB  = $(BINDIR)/$(ADDNAME)ranlib
+STRIP   = $(BINDIR)/$(ADDNAME)strip
+
+KZ_XMODEM = ../../tools/kz_xmodem/kz_xmodem
+KZ_XMODEM_SERDEV = /dev/ttyUSB0
+
+# Low level components
+OBJS  = startup.o main.o interrupt.o
+OBJS += lib.o serial.o timer.o
+OBJS += led.o sg12232c.o
+OBJS += re.o sw.o
+OBJS += mmc.o pff.o
+OBJS += vs1011e.o
+OBJS += spi.o spreg.o
+
+# Tasks
+OBJS += task_ir.o
+OBJS += task_userinput.o
+OBJS += task_command.o
+
+# Kernel
+OBJS += kozos.o syscall.o memory.o
+
+# Drivers
+OBJS += driver_console.o
+OBJS += driver_timer.o
+OBJS += driver_lcd.o
+OBJS += driver_led.o
+OBJS += driver_audio.o
+
+TARGET = kozos
+
+CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
+#CFLAGS += -mint32 # int¤ò32¥Ó¥Ã¥È¤Ë¤¹¤ë¤È³Ý»»¡¿³ä»»¤¬¤Ç¤­¤Ê¤¯¤Ê¤ë
+CFLAGS += -I. -I./driver -I./task
+#CFLAGS += -g
+CFLAGS += -Os
+CFLAGS += -DKOZOS
+
+LFLAGS = -static -T ld.scr -L. -lgcc
+
+.SUFFIXES: .c .o
+.SUFFIXES: .s .o
+.SUFFIXES: .S .o
+
+all :          $(TARGET)
+
+$(TARGET) :    $(OBJS)
+               $(CC) $(OBJS) -o $(TARGET) $(CFLAGS) $(LFLAGS)
+               cp $(TARGET) $(TARGET).elf
+               $(STRIP) $(TARGET)
+
+.c.o :         $<
+               $(CC) -c $(CFLAGS) $<
+
+.s.o :         $<
+               $(CC) -c $(CFLAGS) $<
+
+.S.o :         $<
+               $(CC) -c $(CFLAGS) $<
+
+clean :
+               rm -f $(OBJS) $(TARGET) $(TARGET).elf
+
+load :
+       $(KZ_XMODEM) $(TARGET) $(KZ_XMODEM_SERDEV)
+
+console :
+       minicom -o console -b 9600 -D $(KZ_XMODEM_SERDEV)
+
diff --git a/firm/sample/sample1/os/defines.h b/firm/sample/sample1/os/defines.h
new file mode 100644 (file)
index 0000000..62cd20e
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _DEFINES_H_INCLUDED_
+#define _DEFINES_H_INCLUDED_
+
+#define NULL ((void *)0)
+#define SERIAL_DEFAULT_DEVICE 1
+#define TIMER_DEFAULT_DEVICE  1
+
+typedef char  int8;
+typedef short int16;
+typedef long  int32;
+typedef unsigned char  uint8;
+typedef unsigned short uint16;
+typedef unsigned long  uint32;
+
+typedef uint32 kz_thread_id_t;
+typedef int (*kz_func_t)(int argc, char *argv[]);
+typedef void (*kz_handler_t)(void);
+
+typedef enum {
+  MSGBOX_ID_CONSINPUT = 0,
+  MSGBOX_ID_CONSOUTPUT,
+  MSGBOX_ID_TIMDRIVE,
+  MSGBOX_ID_TIMEXPIRE,
+  MSGBOX_ID_LEDDRIVE,
+  MSGBOX_ID_LCDDRIVE,
+  MSGBOX_ID_AUDIODRIVE,
+  MSGBOX_ID_NUM
+} kz_msgbox_id_t;
+
+#endif
diff --git a/firm/sample/sample1/os/diskio.h b/firm/sample/sample1/os/diskio.h
new file mode 100644 (file)
index 0000000..b2b181a
--- /dev/null
@@ -0,0 +1,39 @@
+/*-----------------------------------------------------------------------\r
+/  PFF - Low level disk interface modlue include file    (C)ChaN, 2010\r
+/-----------------------------------------------------------------------*/\r
+\r
+#ifndef _DISKIO\r
+#define _DISKIO\r
+\r
+#include "integer.h"\r
+#include "pff.h"\r
+\r
+\r
+/* Status of Disk Functions */\r
+typedef BYTE   DSTATUS;\r
+\r
+#define STA_NOINIT             0x01    /* Drive not initialized */\r
+#define STA_NODISK             0x02    /* No medium in the drive */\r
+\r
+\r
+/* Results of Disk Functions */\r
+typedef enum {\r
+       RES_OK = 0,             /* 0: Function succeeded */\r
+       RES_ERROR,              /* 1: Disk error */\r
+       RES_NOTRDY,             /* 2: Not ready */\r
+       RES_PARERR              /* 3: Invalid parameter */\r
+} DRESULT;\r
+\r
+\r
+/*---------------------------------------*/\r
+/* Prototypes for disk control functions */\r
+\r
+DSTATUS disk_initialize (void);\r
+#if _USE_READ\r
+DRESULT disk_readp (BYTE*, DWORD, WORD, WORD);\r
+#endif\r
+#if _USE_WRITE\r
+DRESULT disk_writep (const BYTE*, DWORD);\r
+#endif\r
+\r
+#endif\r
diff --git a/firm/sample/sample1/os/driver.h b/firm/sample/sample1/os/driver.h
new file mode 100644 (file)
index 0000000..4d11539
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef DRIVER_H
+#define DRIVER_H
+
+#include "driver_audio.h"
+#include "driver_console.h"
+#include "driver_lcd.h"
+#include "driver_led.h"
+#include "driver_timer.h"
+
+#endif
+
diff --git a/firm/sample/sample1/os/driver_audio.c b/firm/sample/sample1/os/driver_audio.c
new file mode 100644 (file)
index 0000000..6eea89b
--- /dev/null
@@ -0,0 +1,44 @@
+#include "driver_audio.h"
+#include "vs1011e.h"
+#include "kozos.h"
+
+#define AUDIODRV_CMD_PULSE  'p'
+
+void audio_pulse(void)
+{
+  char *p;
+  p = kz_kmalloc(1);
+  p[0] = AUDIODRV_CMD_PULSE;
+  kz_send(MSGBOX_ID_AUDIODRIVE, 1, p);
+}
+
+static int audiodrv_command(char *p)
+{
+  int cmd = p[0];
+  volatile int i;
+  switch (cmd) {
+  case AUDIODRV_CMD_PULSE:
+    vs1011e_sinetest_init();
+    for (i = 0; i < 2000; i++) { }
+    vs1011e_sinetest_fini();
+    break;
+  default:
+    break;
+  }
+  kz_kmfree(p);
+
+  return 0;
+}
+
+int driver_audio(int argc, char *argv[])
+{
+  int size;
+  char *p;
+
+  while (1) {
+    kz_recv(MSGBOX_ID_AUDIODRIVE, &size, &p);
+    audiodrv_command(p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/driver_audio.h b/firm/sample/sample1/os/driver_audio.h
new file mode 100644 (file)
index 0000000..9c5c394
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _AUDIODRV_H_INCLUDED_
+#define _AUDIODRV_H_INCLUDED_
+
+void audio_pulse(void);
+int driver_audio(int argc, char *argv[]);
+
+#endif
+
diff --git a/firm/sample/sample1/os/driver_console.c b/firm/sample/sample1/os/driver_console.c
new file mode 100644 (file)
index 0000000..811e689
--- /dev/null
@@ -0,0 +1,214 @@
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "interrupt.h"
+#include "serial.h"
+#include "lib.h"
+#include "driver_console.h"
+
+#define CONS_BUFFER_SIZE 32
+
+#define CONSDRV_CMD_USE   'u' /* ¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Î»ÈÍѳ«»Ï */
+#define CONSDRV_CMD_WRITE 'w' /* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎÏ */
+
+static struct consreg {
+  kz_thread_id_t id; /* ¥³¥ó¥½¡¼¥ë¤òÍøÍѤ¹¤ë¥¹¥ì¥Ã¥É */
+  int index;         /* ÍøÍѤ¹¤ë¥·¥ê¥¢¥ë¤ÎÈÖ¹æ */
+
+  char *send_buf;    /* Á÷¿®¥Ð¥Ã¥Õ¥¡ */
+  char *recv_buf;    /* ¼õ¿®¥Ð¥Ã¥Õ¥¡ */
+  int send_len;      /* Á÷¿®¥Ð¥Ã¥Õ¥¡Ãæ¤Î¥Ç¡¼¥¿¥µ¥¤¥º */
+  int recv_len;      /* ¼õ¿®¥Ð¥Ã¥Õ¥¡Ãæ¤Î¥Ç¡¼¥¿¥µ¥¤¥º */
+
+  /* kozos.c ¤Î kz_msgbox ¤ÈƱÍͤÎÍýͳ¤Ç¡¤¥À¥ß¡¼¡¦¥á¥ó¥Ð¤Ç¥µ¥¤¥ºÄ´À°¤¹¤ë */
+  long dummy[3];
+} consreg[CONSDRV_DEVICE_NUM];
+
+/* ¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Î»ÈÍѳ«»Ï¤ò¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+void console_use(int index)
+{
+  char *p;
+  p = kz_kmalloc(3);
+  p[0] = '0';
+  p[1] = CONSDRV_CMD_USE;
+  p[2] = '0' + index;
+  kz_send(MSGBOX_ID_CONSOUTPUT, 3, p);
+}
+
+/* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎϤò¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+void console_write(char *str)
+{
+  char *p;
+  int len;
+  len = strlen(str);
+  p = kz_kmalloc(len + 2);
+  p[0] = '0';
+  p[1] = CONSDRV_CMD_WRITE;
+  memcpy(&p[2], str, len);
+  kz_send(MSGBOX_ID_CONSOUTPUT, len + 2, p);
+}
+
+/*
+ * °Ê²¼¤Î£²¤Ä¤Î´Ø¿ô(send_char(), send_string())¤Ï³ä¹þ¤ß½èÍý¤È¥¹¥ì¥Ã¥É¤«¤é
+ * ¸Æ¤Ð¤ì¤ë¤¬Á÷¿®¥Ð¥Ã¥Õ¥¡¤òÁàºî¤·¤Æ¤ª¤êºÆÆþÉԲĤΤ¿¤á¡¤¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ó½Ð¤¹
+ * ¾ì¹ç¤ÏÇÓ¾¤Î¤¿¤á³ä¹þ¤ß¶Ø»ß¾õÂ֤ǸƤ֤³¤È¡¥
+ */
+
+/* Á÷¿®¥Ð¥Ã¥Õ¥¡¤ÎÀèƬ£±Ê¸»ú¤òÁ÷¿®¤¹¤ë */
+static void send_char(struct consreg *cons)
+{
+  int i;
+  serial_send_byte(cons->index, cons->send_buf[0]);
+  cons->send_len--;
+  /* ÀèƬʸ»ú¤òÁ÷¿®¤·¤¿¤Î¤Ç¡¤£±Ê¸»ú¤Ö¤ó¤º¤é¤¹ */
+  for (i = 0; i < cons->send_len; i++)
+    cons->send_buf[i] = cons->send_buf[i + 1];
+}
+
+/* Ê¸»úÎó¤òÁ÷¿®¥Ð¥Ã¥Õ¥¡¤Ë½ñ¤­¹þ¤ßÁ÷¿®³«»Ï¤¹¤ë */
+static void send_string(struct consreg *cons, char *str, int len)
+{
+  int i;
+  for (i = 0; i < len; i++) { /* Ê¸»úÎó¤òÁ÷¿®¥Ð¥Ã¥Õ¥¡¤Ë¥³¥Ô¡¼ */
+    if (str[i] == '\n') /* \n¢ª\r\n¤ËÊÑ´¹ */
+      cons->send_buf[cons->send_len++] = '\r';
+    cons->send_buf[cons->send_len++] = str[i];
+  }
+  /*
+   * Á÷¿®³ä¹þ¤ß̵¸ú¤Ê¤é¤Ð¡¤Á÷¿®³«»Ï¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤ÇÁ÷¿®³«»Ï¤¹¤ë¡¥
+   * Á÷¿®³ä¹þ¤ßÍ­¸ú¤Ê¤é¤ÐÁ÷¿®³«»Ï¤µ¤ì¤Æ¤ª¤ê¡¤Á÷¿®³ä¹þ¤ß¤Î±äŤÇ
+   * Á÷¿®¥Ð¥Ã¥Õ¥¡Æâ¤Î¥Ç¡¼¥¿¤¬½ç¼¡Á÷¿®¤µ¤ì¤ë¤Î¤Ç¡¤²¿¤â¤·¤Ê¤¯¤Æ¤è¤¤¡¥
+   */
+  if (cons->send_len && !serial_intr_is_send_enable(cons->index)) {
+    serial_intr_send_enable(cons->index); /* Á÷¿®³ä¹þ¤ßÍ­¸ú²½ */
+    send_char(cons); /* Á÷¿®³«»Ï */
+  }
+}
+
+/*
+ * °Ê²¼¤Ï³ä¹þ¤ß¥Ï¥ó¥É¥é¤«¤é¸Æ¤Ð¤ì¤ë³ä¹þ¤ß½èÍý¤Ç¤¢¤ê¡¤ÈóƱ´ü¤Ç
+ * ¸Æ¤Ð¤ì¤ë¤Î¤Ç¡¤¥é¥¤¥Ö¥é¥ê´Ø¿ô¤Ê¤É¤ò¸Æ¤Ó½Ð¤¹¾ì¹ç¤Ë¤ÏÃí°Õ¤¬É¬Íס¥
+ * ´ðËܤȤ·¤Æ¡¤°Ê²¼¤Î¤¤¤º¤ì¤«¤ËÅö¤Æ¤Ï¤Þ¤ë´Ø¿ô¤·¤«¸Æ¤Ó½Ð¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * ¡¦ºÆÆþ²Äǽ¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤Ï̵¤¤´Ø¿ô¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤¬¤¢¤ë¤¬¡¤³ä¹þ¤ß¶Ø»ß¤Ç¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¡¥
+ * ¤Þ¤¿Èó¥³¥ó¥Æ¥­¥¹¥È¾õÂ֤ǸƤФì¤ë¤¿¤á¡¤¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ÏÍøÍѤ·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * (¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤òÍøÍѤ¹¤ë¤³¤È)
+ */
+static int consdrv_intrproc(struct consreg *cons)
+{
+  unsigned char c;
+  char *p;
+
+  if (serial_is_recv_enable(cons->index)) { /* ¼õ¿®³ä¹þ¤ß */
+    c = serial_recv_byte(cons->index);
+    if (c == '\r') /* ²þ¹Ô¥³¡¼¥ÉÊÑ´¹(\r¢ª\n) */
+      c = '\n';
+
+    send_string(cons, &c, 1); /* ¥¨¥³¡¼¥Ð¥Ã¥¯½èÍý */
+
+    if (cons->id) {
+      if (c != '\n') {
+       /* ²þ¹Ô¤Ç¤Ê¤¤¤Ê¤é¡¤¼õ¿®¥Ð¥Ã¥Õ¥¡¤Ë¥Ð¥Ã¥Õ¥¡¥ê¥ó¥°¤¹¤ë */
+       cons->recv_buf[cons->recv_len++] = c;
+      } else {
+       /*
+        * Enter¤¬²¡¤µ¤ì¤¿¤é¡¤¥Ð¥Ã¥Õ¥¡¤ÎÆâÍƤò
+        * ¥³¥Þ¥ó¥É½èÍý¥¹¥ì¥Ã¥É¤ËÄÌÃΤ¹¤ë¡¥
+        * (³ä¹þ¤ß¥Ï¥ó¥É¥é¤Ê¤Î¤Ç¡¤¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤òÍøÍѤ¹¤ë)
+        */
+       p = kx_kmalloc(CONS_BUFFER_SIZE);
+       memcpy(p, cons->recv_buf, cons->recv_len);
+       kx_send(MSGBOX_ID_CONSINPUT, cons->recv_len, p);
+       cons->recv_len = 0;
+      }
+    }
+  }
+
+  if (serial_is_send_enable(cons->index)) { /* Á÷¿®³ä¹þ¤ß */
+    if (!cons->id || !cons->send_len) {
+      /* Á÷¿®¥Ç¡¼¥¿¤¬Ìµ¤¤¤Ê¤é¤Ð¡¤Á÷¿®½èÍý½ªÎ» */
+      serial_intr_send_disable(cons->index);
+    } else {
+      /* Á÷¿®¥Ç¡¼¥¿¤¬¤¢¤ë¤Ê¤é¤Ð¡¤°ú³¤­Á÷¿®¤¹¤ë */
+      send_char(cons);
+    }
+  }
+
+  return 0;
+}
+
+/* ³ä¹þ¤ß¥Ï¥ó¥É¥é */
+static void consdrv_intr(void)
+{
+  int i;
+  struct consreg *cons;
+
+  for (i = 0; i < CONSDRV_DEVICE_NUM; i++) {
+    cons = &consreg[i];
+    if (cons->id) {
+      if (serial_is_send_enable(cons->index) ||
+         serial_is_recv_enable(cons->index))
+       /* ³ä¹þ¤ß¤¬¤¢¤ë¤Ê¤é¤Ð¡¤³ä¹þ¤ß½èÍý¤ò¸Æ¤Ó½Ð¤¹ */
+       consdrv_intrproc(cons);
+    }
+  }
+}
+
+static int consdrv_init(void)
+{
+  memset(consreg, 0, sizeof(consreg));
+  return 0;
+}
+
+/* ¥¹¥ì¥Ã¥É¤«¤é¤ÎÍ×µá¤ò½èÍý¤¹¤ë */
+static int consdrv_command(struct consreg *cons, kz_thread_id_t id,
+                          int index, int size, char *command)
+{
+  switch (command[0]) {
+  case CONSDRV_CMD_USE: /* ¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Î»ÈÍѳ«»Ï */
+    cons->id = id;
+    cons->index = command[1] - '0';
+    cons->send_buf = kz_kmalloc(CONS_BUFFER_SIZE);
+    cons->recv_buf = kz_kmalloc(CONS_BUFFER_SIZE);
+    cons->send_len = 0;
+    cons->recv_len = 0;
+    serial_init(cons->index);
+    serial_intr_recv_enable(cons->index); /* ¼õ¿®³ä¹þ¤ßÍ­¸ú²½(¼õ¿®³«»Ï) */
+    break;
+
+  case CONSDRV_CMD_WRITE: /* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎÏ */
+    /*
+     * send_string()¤Ç¤ÏÁ÷¿®¥Ð¥Ã¥Õ¥¡¤òÁàºî¤·¤Æ¤ª¤êºÆÆþÉԲĤʤΤǡ¤
+     * ÇÓ¾¤Î¤¿¤á¤Ë³ä¹þ¤ß¶Ø»ß¤Ë¤·¤Æ¸Æ¤Ó½Ð¤¹¡¥
+     */
+    INTR_DISABLE;
+    send_string(cons, command + 1, size - 1); /* Ê¸»úÎó¤ÎÁ÷¿® */
+    INTR_ENABLE;
+    break;
+
+  default:
+    break;
+  }
+
+  return 0;
+}
+
+int driver_console(int argc, char *argv[])
+{
+  int size, index;
+  kz_thread_id_t id;
+  char *p;
+
+  consdrv_init();
+  kz_setintr(SOFTVEC_TYPE_SERINTR, consdrv_intr); /* ³ä¹þ¤ß¥Ï¥ó¥É¥éÀßÄê */
+
+  while (1) {
+    id = kz_recv(MSGBOX_ID_CONSOUTPUT, &size, &p);
+    index = p[0] - '0';
+    consdrv_command(&consreg[index], id, index, size - 1, p + 1);
+    kz_kmfree(p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/driver_console.h b/firm/sample/sample1/os/driver_console.h
new file mode 100644 (file)
index 0000000..4cc7341
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _CONSDRV_H_INCLUDED_
+#define _CONSDRV_H_INCLUDED_
+
+#define CONSDRV_DEVICE_NUM 1
+
+void console_use(int index);
+void console_write(char *str);
+
+int driver_console(int argc, char *argv[]);
+
+#endif
diff --git a/firm/sample/sample1/os/driver_lcd.c b/firm/sample/sample1/os/driver_lcd.c
new file mode 100644 (file)
index 0000000..ce093b3
--- /dev/null
@@ -0,0 +1,214 @@
+#include "driver_lcd.h"
+#include "sg12232c.h"
+#include "kozos.h"
+#include "lib.h"
+
+#define LCDDRV_CMD_LCD_CLEAR        'c' /* LCD\e$B$N>C5n\e(B */
+#define LCDDRV_CMD_LCD_DRAW_BOX     'b' /* BOX\e$BIA2h%3%^%s%I\e(B */
+#define LCDDRV_CMD_LCD_DRAW_LOGO    'l' /* LOGO\e$BIA2h%3%^%s%I\e(B */
+#define LCDDRV_CMD_LCD_DRAW_TEXT    't' /* TEXT\e$BIA2h%3%^%s%I\e(B */
+
+void lcddrv_clear(void)
+{
+  char *p;
+  p = kz_kmalloc(1);
+  p[0] = LCDDRV_CMD_LCD_CLEAR;
+  kz_send(MSGBOX_ID_LCDDRIVE, 1, p);
+}
+
+void lcddrv_draw_box(int x1, int y1, int x2, int y2, int on)
+{
+  char *p;
+  p = kz_kmalloc(6);
+  p[0] = LCDDRV_CMD_LCD_DRAW_BOX;
+  p[1] = x1;
+  p[2] = y1;
+  p[3] = x2;
+  p[4] = y2;
+  p[5] = !on;
+  kz_send(MSGBOX_ID_LCDDRIVE, 6, p);
+}
+
+void lcddrv_draw_logo(int x, int y, int size)
+{
+  char *p;
+  p = kz_kmalloc(4);
+  p[0] = LCDDRV_CMD_LCD_DRAW_LOGO;
+  p[1] = x;
+  p[2] = y;
+  p[3] = size;
+  kz_send(MSGBOX_ID_LCDDRIVE, 4, p);
+}
+
+void lcddrv_draw_text(int x, int y, char *str)
+{
+  char *p;
+  int len;
+  len = strlen(str);
+  p = kz_kmalloc(3 + len + 1);
+  p[0] = LCDDRV_CMD_LCD_DRAW_TEXT;
+  p[1] = x;
+  p[2] = y;
+  memcpy(&p[3], str, len);
+  p[3 + len] = '\0';
+  kz_send(MSGBOX_ID_LCDDRIVE, 3 + len + 1, p);
+}
+
+static void draw_logo(const int ofsx, const int ofsy, const int size)
+{
+  static const uint8 logo_40x32[] = {
+      0x00,0x00,0x00,0x00,0x00,
+      0x00,0x00,0x00,0x00,0x00,
+      0x00,0x1f,0xfc,0x00,0x00,
+      0x00,0x1f,0xff,0xc0,0x00,
+      0x00,0x1f,0xff,0xf0,0x00,
+      0x00,0x0f,0x7f,0xfc,0x00,
+      0x00,0x0f,0x7f,0xff,0x00,
+      0x00,0x0f,0x7f,0xff,0xc0,
+      0x00,0x0f,0x7f,0xff,0xe0,
+      0x00,0x07,0x3f,0xff,0xf0,
+      0x00,0x07,0x9f,0xff,0xfc,
+      0x00,0x07,0xc1,0xff,0xfe,
+      0x3f,0xff,0xff,0xff,0xff,
+      0x3f,0xff,0xff,0xff,0xff,
+      0x1f,0xff,0xff,0xff,0xff,
+      0x1f,0xff,0xff,0xff,0xff,
+      0x1f,0xff,0xfc,0xff,0xff,
+      0x1f,0xff,0xf0,0x3f,0xff,
+      0x1f,0xff,0xf0,0x07,0xff,
+      0x1f,0xff,0xe0,0x41,0xff,
+      0x0f,0xff,0xe0,0x21,0xff,
+      0x0f,0xff,0xe2,0x13,0xff,
+      0x07,0xff,0xf1,0x07,0xff,
+      0x07,0xff,0xf8,0x8f,0xff,
+      0x03,0xff,0xf8,0x1f,0xff,
+      0x03,0xff,0xfc,0x3f,0xff,
+      0x01,0xff,0xfc,0x7f,0xff,
+      0x00,0xff,0xfe,0xff,0xff,
+      0x00,0xff,0xff,0xff,0xff,
+      0x00,0x7f,0xff,0xff,0xff,
+      0x00,0x3f,0xff,0xff,0xff,
+      0x00,0x1f,0xff,0xff,0xff,
+  };
+  static const uint8 logo_30x24[] = {
+      0x00,0x00,0x00,0x00,
+      0x00,0xfe,0x00,0x00,
+      0x00,0xff,0xe0,0x00,
+      0x00,0x7f,0xf8,0x00,
+      0x00,0x77,0xff,0x00,
+      0x00,0x77,0xff,0x80,
+      0x00,0x77,0xff,0xe0,
+      0x00,0x73,0xff,0xf0,
+      0x00,0x38,0x7f,0xf8,
+      0x3f,0xff,0xff,0xfc,
+      0x3f,0xff,0xff,0xfc,
+      0x3f,0xff,0xff,0xfc,
+      0x3f,0xff,0x1f,0xfc,
+      0x3f,0xfe,0x07,0xfc,
+      0x1f,0xfe,0x23,0xfc,
+      0x1f,0xfc,0x11,0xfc,
+      0x1f,0xfe,0x8b,0xfc,
+      0x0f,0xfe,0x47,0xfc,
+      0x0f,0xff,0x2f,0xfc,
+      0x07,0xff,0x1f,0xfc,
+      0x03,0xff,0xbf,0xfc,
+      0x03,0xff,0xff,0xfc,
+      0x01,0xff,0xff,0xfc,
+      0x00,0xff,0xff,0xfc,
+  };
+  static const uint8 logo_20x16[] = {
+      0x00,0x00,0x00,
+      0x03,0xf0,0x00,
+      0x03,0xfe,0x00,
+      0x03,0x7f,0x00,
+      0x03,0x7f,0xc0,
+      0x03,0x8f,0xe0,
+      0x7f,0xff,0xf0,
+      0x7f,0xff,0xf0,
+      0x7f,0xc7,0xf0,
+      0x3f,0x89,0xf0,
+      0x3f,0xa5,0xf0,
+      0x3f,0x93,0xf0,
+      0x1f,0xc7,0xf0,
+      0x0f,0xef,0xf0,
+      0x0f,0xff,0xf0,
+      0x07,0xff,0xf0,
+  };
+  int x, y;
+  uint8 c = 0;
+  switch (size) {
+    case 0:
+      for (y = 0; y < 16; y++) {
+        for (x = 0; x < 20; x++) {
+          if ((x % 8) == 0) {
+            c = logo_20x16[(y * 3) + (x / 8)];
+          }
+          int pix = (c & (1 << (7 - (x % 8)))) ? 1 : 0;
+          sg12232c_set_pixel(ofsx + x, ofsy + y, pix);
+        }
+      }
+      break;
+    case 1:
+      for (y = 0; y < 24; y++) {
+        for (x = 0; x < 30; x++) {
+          if ((x % 8) == 0) {
+            c = logo_30x24[(y * 4) + (x / 8)];
+          }
+          int pix = (c & (1 << (7 - (x % 8)))) ? 1 : 0;
+          sg12232c_set_pixel(ofsx + x, ofsy + y, pix);
+        }
+      }
+      break;
+    case 2:
+      for (y = 0; y < 32; y++) {
+        for (x = 0; x < 40; x++) {
+          if ((x % 8) == 0) {
+            c = logo_40x32[(y * 5) + (x / 8)];
+          }
+          int pix = (c & (1 << (7 - (x % 8)))) ? 1 : 0;
+          sg12232c_set_pixel(ofsx + x, ofsy + y, pix);
+        }
+      }
+      break;
+  }
+}
+
+/* \e$B%9%l%C%I$+$i$NMW5a$r=hM}$9$k\e(B */
+static int lcddrv_command(char *p)
+{
+  int cmd = p[0];
+  switch (cmd) {
+  case LCDDRV_CMD_LCD_CLEAR:
+    sg12232c_clear();
+    break;
+  case LCDDRV_CMD_LCD_DRAW_BOX:
+    sg12232c_draw_box(p[1], p[2], p[3], p[4], p[5]);
+    break;
+  case LCDDRV_CMD_LCD_DRAW_LOGO:
+    draw_logo(p[1], p[2], p[3]);
+    break;
+  case LCDDRV_CMD_LCD_DRAW_TEXT:
+    sg12232c_draw_string(p[1], p[2], &p[3], 0);
+    break;
+  default:
+    break;
+  }
+  kz_kmfree(p);
+
+  return 0;
+}
+
+int driver_lcd(int argc, char *argv[])
+{
+  int size;
+  char *p;
+
+  sg12232c_init();
+
+  while (1) {
+    kz_recv(MSGBOX_ID_LCDDRIVE, &size, &p);
+    lcddrv_command(p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/driver_lcd.h b/firm/sample/sample1/os/driver_lcd.h
new file mode 100644 (file)
index 0000000..94895f7
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _LCDDRV_H_INCLUDED_
+#define _LCDDRV_H_INCLUDED_
+
+void lcddrv_clear(void);
+void lcddrv_draw_box(int x1, int y1, int x2, int y2, int on);
+void lcddrv_draw_logo(int x, int y, int size);
+void lcddrv_draw_text(int x, int y, char *str);
+
+int driver_lcd(int argc, char *argv[]);
+
+#endif
diff --git a/firm/sample/sample1/os/driver_led.c b/firm/sample/sample1/os/driver_led.c
new file mode 100644 (file)
index 0000000..533b4dd
--- /dev/null
@@ -0,0 +1,63 @@
+#include "driver_led.h"
+#include "led.h"
+#include "kozos.h"
+
+#define LEDDRV_CMD_LED_ON       'o' /* LED\e$B$NE@Et\e(B */
+#define LEDDRV_CMD_LED_OFF      'x' /* LED\e$B$N>CEt\e(B */
+#define LEDDRV_CMD_LED_TOGGLE   't' /* LED\e$B$N%H%0%k\e(B */
+
+void leddrv_write(int target, int state)
+{
+  char *p;
+  p = kz_kmalloc(2);
+  p[0] = state ? LEDDRV_CMD_LED_ON : LEDDRV_CMD_LED_OFF;
+  p[1] = '0' + target;
+  kz_send(MSGBOX_ID_LEDDRIVE, 2, p);
+}
+
+void leddrv_toggle(int target)
+{
+  char *p;
+  p = kz_kmalloc(2);
+  p[0] = LEDDRV_CMD_LED_TOGGLE;
+  p[1] = '0' + target;
+  kz_send(MSGBOX_ID_LEDDRIVE, 2, p);
+}
+
+/* \e$B%9%l%C%I$+$i$NMW5a$r=hM}$9$k\e(B */
+static int leddrv_command(char *p)
+{
+  int cmd = p[0];
+  int led = p[1] - '0';
+  switch (cmd) {
+  case LEDDRV_CMD_LED_ON:
+    led_write(led, LedOn);
+    break;
+  case LEDDRV_CMD_LED_OFF:
+    led_write(led, LedOff);
+    break;
+  case LEDDRV_CMD_LED_TOGGLE:
+    led_toggle(led);
+    break;
+  default:
+    break;
+  }
+  kz_kmfree(p);
+
+  return 0;
+}
+
+int driver_led(int argc, char *argv[])
+{
+  int size;
+  char *p;
+
+  led_init();
+
+  while (1) {
+    kz_recv(MSGBOX_ID_LEDDRIVE, &size, &p);
+    leddrv_command(p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/driver_led.h b/firm/sample/sample1/os/driver_led.h
new file mode 100644 (file)
index 0000000..4df8ce3
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _LEDDRV_H_INCLUDED_
+#define _LEDDRV_H_INCLUDED_
+
+void leddrv_write(int target, int state);
+void leddrv_toggle(int target);
+
+int driver_led(int argc, char *argv[]);
+
+#endif
diff --git a/firm/sample/sample1/os/driver_timer.c b/firm/sample/sample1/os/driver_timer.c
new file mode 100644 (file)
index 0000000..b9d698f
--- /dev/null
@@ -0,0 +1,141 @@
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "interrupt.h"
+#include "timer.h"
+#include "lib.h"
+#include "driver_timer.h"
+
+#define TIMERDRV_CMD_EXPIRE 'e' /* ¥¿¥¤¥ÞËþλ */
+#define TIMERDRV_CMD_START  's' /* ¥¿¥¤¥Þ¤Î¥¹¥¿¡¼¥È */
+
+struct timerbuf {
+  struct timerbuf *next;
+  kz_msgbox_id_t id; /* ¥¿¥¤¥ÞËþλ»þ¤Î¥á¥Ã¥»¡¼¥¸Á÷¿®Àè */
+  int msec;
+};
+
+static struct timerreg {
+  struct timerbuf *timers; /* ¥¿¥¤¥Þ¡¦¥Ð¥Ã¥Õ¥¡¤Î¥ê¥ó¥¯¥ê¥¹¥È */
+  int index; /* ÍøÍѤ¹¤ë¥¿¥¤¥Þ¤ÎÈÖ¹æ */
+} timerreg;
+
+void timerdrv_start(int msec)
+{
+    struct timerreq *req;
+    req = kz_kmalloc(sizeof(*req));
+    req->id = MSGBOX_ID_TIMEXPIRE;
+    req->msec = msec;
+    kz_send(MSGBOX_ID_TIMDRIVE, TIMERDRV_CMD_START, (char *)req);
+}
+
+void timerdrv_wait()
+{
+    kz_recv(MSGBOX_ID_TIMEXPIRE, NULL, NULL);
+}
+
+/*
+ * °Ê²¼¤Ï³ä¹þ¤ß¥Ï¥ó¥É¥é¤Ç¤¢¤ê¡¤ÈóƱ´ü¤Ç¸Æ¤Ð¤ì¤ë¤Î¤Ç¡¤¥é¥¤¥Ö¥é¥ê´Ø¿ô¤Ê¤É¤ò
+ * ¸Æ¤Ó½Ð¤¹¾ì¹ç¤Ë¤ÏÃí°Õ¤¬É¬Íס¥
+ * ´ðËܤȤ·¤Æ¡¤°Ê²¼¤Î¤¤¤º¤ì¤«¤ËÅö¤Æ¤Ï¤Þ¤ë´Ø¿ô¤·¤«¸Æ¤Ó½Ð¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * ¡¦ºÆÆþ²Äǽ¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤Ï̵¤¤´Ø¿ô¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤¬¤¢¤ë¤¬¡¤³ä¹þ¤ß¶Ø»ß¤Ç¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¡¥
+ * ¤Þ¤¿Èó¥³¥ó¥Æ¥­¥¹¥È¾õÂ֤ǸƤФì¤ë¤¿¤á¡¤¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ÏÍøÍѤ·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * (¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤òÍøÍѤ¹¤ë¤³¤È)
+ */
+static void timerdrv_intr(void)
+{
+  struct timerreg *tim = &timerreg;
+
+  if (timer_is_expired(tim->index)) { /* ¥¿¥¤¥Þ³ä¹þ¤ß */
+    timer_cancel(tim->index);
+    kx_send(MSGBOX_ID_TIMDRIVE, TIMERDRV_CMD_EXPIRE, NULL);
+  }
+}
+
+static int timerdrv_init(void)
+{
+  memset(&timerreg, 0, sizeof(timerreg));
+  timerreg.index = TIMER_DEFAULT_DEVICE;
+  return 0;
+}
+
+/* ¥¹¥ì¥Ã¥É¤«¤é¤ÎÍ×µá¤ò½èÍý¤¹¤ë */
+static int timerdrv_command(struct timerreg *tim, int cmd, char *p)
+{
+  struct timerbuf *tmbuf;
+  struct timerbuf **tmbufp;
+  struct timerreq *req;
+  int t, msec;
+
+  switch (cmd) {
+  case TIMERDRV_CMD_EXPIRE: /* ¥¿¥¤¥ÞËþλ */
+    tmbuf = tim->timers;
+    if (tmbuf) {
+      tim->timers = tmbuf->next;
+      kz_send(tmbuf->id, 0, NULL);
+      kz_kmfree(tmbuf);
+      if (tim->timers)
+       timer_start(tim->index, tim->timers->msec, 0);
+    }
+    break;
+
+  case TIMERDRV_CMD_START: /* ¥¿¥¤¥Þ¤Î¥¹¥¿¡¼¥È */
+    req = (struct timerreq *)p;
+
+    tmbuf = kz_kmalloc(sizeof(*tmbuf));
+    tmbuf->next = NULL;
+    tmbuf->id   = req->id;
+    tmbuf->msec = req->msec;
+
+    t = 0;
+    if (tim->timers) {
+      t = timer_gettime(tim->index);
+    }
+
+    for (tmbufp = &tim->timers;; tmbufp = &(*tmbufp)->next) {
+      if (*tmbufp == NULL) {
+       *tmbufp = tmbuf;
+       if (tmbufp == &tim->timers)
+         timer_start(tim->index, tim->timers->msec, 0);
+       break;
+      }
+      msec = (*tmbufp)->msec - t;
+      if (msec < 0) msec = 0;
+      if (tmbuf->msec < msec) {
+       (*tmbufp)->msec = msec - tmbuf->msec;
+       tmbuf->next = *tmbufp;
+       *tmbufp = tmbuf;
+       timer_start(tim->index, tim->timers->msec, 0);
+       break;
+      }
+      t = 0;
+      tmbuf->msec -= msec;
+    }
+
+    kz_kmfree(p);
+    break;
+
+  default:
+    break;
+  }
+
+  return 0;
+}
+
+int driver_timer(int argc, char *argv[])
+{
+  int cmd;
+  char *p;
+
+  timerdrv_init();
+  kz_setintr(SOFTVEC_TYPE_TIMINTR, timerdrv_intr); /* ³ä¹þ¤ß¥Ï¥ó¥É¥éÀßÄê */
+
+  while (1) {
+    kz_recv(MSGBOX_ID_TIMDRIVE, &cmd, &p);
+    timerdrv_command(&timerreg, cmd, p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/driver_timer.h b/firm/sample/sample1/os/driver_timer.h
new file mode 100644 (file)
index 0000000..dd44593
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _TIMERDRV_H_INCLUDED_
+#define _TIMERDRV_H_INCLUDED_
+
+#define TIMERDRV_DEVICE_NUM 1
+
+void timerdrv_start(int msec);
+void timerdrv_wait();
+
+struct timerreq {
+  kz_msgbox_id_t id; /* ¥¿¥¤¥ÞËþλ»þ¤Î¥á¥Ã¥»¡¼¥¸Á÷¿®Àè */
+  int msec;
+};
+
+int driver_timer(int argc, char *argv[]);
+
+#endif
diff --git a/firm/sample/sample1/os/integer.h b/firm/sample/sample1/os/integer.h
new file mode 100644 (file)
index 0000000..0e24bdb
--- /dev/null
@@ -0,0 +1,30 @@
+/*-------------------------------------------*/\r
+/* Integer type definitions for FatFs module */\r
+/*-------------------------------------------*/\r
+\r
+#ifndef _INTEGER\r
+#define _INTEGER\r
+\r
+#include "defines.h"\r
+\r
+/* These types must be 16-bit, 32-bit or larger integer */\r
+typedef int16       INT;\r
+typedef uint16      UINT;\r
+\r
+/* These types must be 8-bit integer */\r
+typedef int8        CHAR;\r
+typedef uint8       UCHAR;\r
+typedef uint8       BYTE;\r
+\r
+/* These types must be 16-bit integer */\r
+typedef int16       SHORT;\r
+typedef uint16      USHORT;\r
+typedef uint16      WORD;\r
+typedef uint16      WCHAR;\r
+\r
+/* These types must be 32-bit integer */\r
+typedef int32       LONG;\r
+typedef uint32      ULONG;\r
+typedef uint32      DWORD;\r
+\r
+#endif\r
diff --git a/firm/sample/sample1/os/interrupt.c b/firm/sample/sample1/os/interrupt.c
new file mode 100644 (file)
index 0000000..0a02225
--- /dev/null
@@ -0,0 +1,30 @@
+#include "defines.h"
+#include "intr.h"
+#include "interrupt.h"
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤Î½é´ü²½ */
+int softvec_init(void)
+{
+  int type;
+  for (type = 0; type < SOFTVEC_TYPE_NUM; type++)
+    softvec_setintr(type, NULL);
+  return 0;
+}
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÀßÄê */
+int softvec_setintr(softvec_type_t type, softvec_handler_t handler)
+{
+  SOFTVECS[type] = handler;
+  return 0;
+}
+
+/*
+ * ¶¦Ä̳ä¹þ¤ß¥Ï¥ó¥É¥é¡¥
+ * ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ò¸«¤Æ¡¤³Æ¥Ï¥ó¥É¥é¤Ëʬ´ô¤¹¤ë¡¥
+ */
+void interrupt(softvec_type_t type, unsigned long sp)
+{
+  softvec_handler_t handler = SOFTVECS[type];
+  if (handler)
+    handler(type, sp);
+}
diff --git a/firm/sample/sample1/os/interrupt.h b/firm/sample/sample1/os/interrupt.h
new file mode 100644 (file)
index 0000000..ce8df6e
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _INTERRUPT_H_INCLUDED_
+#define _INTERRUPT_H_INCLUDED_
+
+/* °Ê²¼¤Ï¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÇÄêµÁ¤·¤Æ¤¢¤ë¥·¥ó¥Ü¥ë */
+extern char softvec;
+#define SOFTVEC_ADDR (&softvec)
+
+typedef short softvec_type_t;
+
+typedef void (*softvec_handler_t)(softvec_type_t type, unsigned long sp);
+
+#define SOFTVECS ((softvec_handler_t *)SOFTVEC_ADDR)
+
+#define INTR_ENABLE  asm volatile ("andc.b #0x3f,ccr")
+#define INTR_DISABLE asm volatile ("orc.b #0xc0,ccr")
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤Î½é´ü²½ */
+int softvec_init(void);
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÀßÄê */
+int softvec_setintr(softvec_type_t type, softvec_handler_t handler);
+
+/* ¶¦Ä̳ä¹þ¤ß¥Ï¥ó¥É¥é */
+void interrupt(softvec_type_t type, unsigned long sp);
+
+#endif
diff --git a/firm/sample/sample1/os/intr.h b/firm/sample/sample1/os/intr.h
new file mode 100644 (file)
index 0000000..b44dbeb
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _INTR_H_INCLUDED_
+#define _INTR_H_INCLUDED_
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÄêµÁ */
+
+#define SOFTVEC_TYPE_NUM     6
+
+#define SOFTVEC_TYPE_SOFTERR 0
+#define SOFTVEC_TYPE_SYSCALL 1
+#define SOFTVEC_TYPE_SERINTR 2
+#define SOFTVEC_TYPE_TIMINTR 3
+#define SOFTVEC_TYPE_IR_EDGE 4
+#define SOFTVEC_TYPE_IR_TOVF 5
+
+#endif
diff --git a/firm/sample/sample1/os/kozos.c b/firm/sample/sample1/os/kozos.c
new file mode 100644 (file)
index 0000000..901896b
--- /dev/null
@@ -0,0 +1,578 @@
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "interrupt.h"
+#include "syscall.h"
+#include "memory.h"
+#include "lib.h"
+
+#define THREAD_NUM 12
+#define PRIORITY_NUM 16
+#define THREAD_NAME_SIZE 15
+
+/* ¥¹¥ì¥Ã¥É¡¦¥³¥ó¥Æ¥­¥¹¥È */
+typedef struct _kz_context {
+  uint32 sp; /* ¥¹¥¿¥Ã¥¯¡¦¥Ý¥¤¥ó¥¿ */
+} kz_context;
+
+/* ¥¿¥¹¥¯¡¦¥³¥ó¥È¥í¡¼¥ë¡¦¥Ö¥í¥Ã¥¯(TCB) */
+typedef struct _kz_thread {
+  struct _kz_thread *next;
+  char name[THREAD_NAME_SIZE + 1]; /* ¥¹¥ì¥Ã¥É̾ */
+  int priority;   /* Í¥ÀèÅÙ */
+  char *stack;    /* ¥¹¥¿¥Ã¥¯ */
+  uint32 flags;   /* ³Æ¼ï¥Õ¥é¥° */
+#define KZ_THREAD_FLAG_READY (1 << 0)
+
+  struct { /* ¥¹¥ì¥Ã¥É¤Î¥¹¥¿¡¼¥È¡¦¥¢¥Ã¥×(thread_init())¤ËÅϤ¹¥Ñ¥é¥á¡¼¥¿ */
+    kz_func_t func; /* ¥¹¥ì¥Ã¥É¤Î¥á¥¤¥ó´Ø¿ô */
+    int argc;       /* ¥¹¥ì¥Ã¥É¤Î¥á¥¤¥ó´Ø¿ô¤ËÅϤ¹ argc */
+    char **argv;    /* ¥¹¥ì¥Ã¥É¤Î¥á¥¤¥ó´Ø¿ô¤ËÅϤ¹ argv */
+  } init;
+
+  struct { /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ëÍѥХåե¡ */
+    kz_syscall_type_t type;
+    kz_syscall_param_t *param;
+  } syscall;
+
+  kz_context context; /* ¥³¥ó¥Æ¥­¥¹¥È¾ðÊó */
+} kz_thread;
+
+/* ¥á¥Ã¥»¡¼¥¸¡¦¥Ð¥Ã¥Õ¥¡ */
+typedef struct _kz_msgbuf {
+  struct _kz_msgbuf *next;
+  kz_thread *sender; /* ¥á¥Ã¥»¡¼¥¸¤òÁ÷¿®¤·¤¿¥¹¥ì¥Ã¥É */
+  struct { /* ¥á¥Ã¥»¡¼¥¸¤Î¥Ñ¥é¥á¡¼¥¿ÊݸÎΰè */
+    int size;
+    char *p;
+  } param;
+} kz_msgbuf;
+
+/* ¥á¥Ã¥»¡¼¥¸¡¦¥Ü¥Ã¥¯¥¹ */
+typedef struct _kz_msgbox {
+  kz_thread *receiver; /* ¼õ¿®ÂÔ¤Á¾õÂ֤Υ¹¥ì¥Ã¥É */
+  kz_msgbuf *head;
+  kz_msgbuf *tail;
+
+  /*
+   * H8¤Ï16¥Ó¥Ã¥ÈCPU¤Ê¤Î¤Ç¡¤32¥Ó¥Ã¥ÈÀ°¿ô¤ËÂФ·¤Æ¤Î¾è»»Ì¿Î᤬̵¤¤¡¥¤è¤Ã¤Æ
+   * ¹½Â¤ÂΤΥµ¥¤¥º¤¬£²¤Î³¬¾è¤Ë¤Ê¤Ã¤Æ¤¤¤Ê¤¤¤È¡¤¹½Â¤ÂΤÎÇÛÎó¤Î¥¤¥ó¥Ç¥Ã¥¯¥¹
+   * ·×»»¤Ç¾è»»¤¬»È¤ï¤ì¤Æ¡Ö___mulsi3¤¬Ìµ¤¤¡×¤Ê¤É¤Î¥ê¥ó¥¯¡¦¥¨¥é¡¼¤Ë¤Ê¤ë¾ì¹ç¤¬
+   * ¤¢¤ë¡¥(£²¤Î³¬¾è¤Ê¤é¤Ð¥·¥Õ¥È±é»»¤¬ÍøÍѤµ¤ì¤ë¤Î¤ÇÌäÂê¤Ï½Ð¤Ê¤¤)
+   * Âкö¤È¤·¤Æ¡¤¥µ¥¤¥º¤¬£²¤Î³¬¾è¤Ë¤Ê¤ë¤è¤¦¤Ë¥À¥ß¡¼¡¦¥á¥ó¥Ð¤ÇÄ´À°¤¹¤ë¡¥
+   * Â¾¹½Â¤ÂΤÇƱÍͤΥ¨¥é¡¼¤¬½Ð¤¿¾ì¹ç¤Ë¤Ï¡¤Æ±ÍͤÎÂнè¤ò¤¹¤ë¤³¤È¡¥
+   */
+  long dummy[1];
+} kz_msgbox;
+
+/* ¥¹¥ì¥Ã¥É¤Î¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼ */
+static struct {
+  kz_thread *head;
+  kz_thread *tail;
+} readyque[PRIORITY_NUM];
+
+static kz_thread *current; /* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É */
+static kz_thread threads[THREAD_NUM]; /* ¥¿¥¹¥¯¡¦¥³¥ó¥È¥í¡¼¥ë¡¦¥Ö¥í¥Ã¥¯ */
+static kz_handler_t handlers[SOFTVEC_TYPE_NUM]; /* ³ä¹þ¤ß¥Ï¥ó¥É¥é */
+static kz_msgbox msgboxes[MSGBOX_ID_NUM]; /* ¥á¥Ã¥»¡¼¥¸¡¦¥Ü¥Ã¥¯¥¹ */
+
+void dispatch(kz_context *context);
+
+/* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤«¤éÈ´¤­½Ð¤¹ */
+static int getcurrent(void)
+{
+  if (current == NULL) {
+    return -1;
+  }
+  if (!(current->flags & KZ_THREAD_FLAG_READY)) {
+    /* ¤¹¤Ç¤Ë̵¤¤¾ì¹ç¤Ï̵»ë */
+    return 1;
+  }
+
+  /* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É¤Ïɬ¤ºÀèƬ¤Ë¤¢¤ë¤Ï¤º¤Ê¤Î¤Ç¡¤ÀèƬ¤«¤éÈ´¤­½Ð¤¹ */
+  readyque[current->priority].head = current->next;
+  if (readyque[current->priority].head == NULL) {
+    readyque[current->priority].tail = NULL;
+  }
+  current->flags &= ~KZ_THREAD_FLAG_READY;
+  current->next = NULL;
+
+  return 0;
+}
+
+/* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤Ë·Ò¤²¤ë */
+static int putcurrent(void)
+{
+  if (current == NULL) {
+    return -1;
+  }
+  if (current->flags & KZ_THREAD_FLAG_READY) {
+    /* ¤¹¤Ç¤ËÍ­¤ë¾ì¹ç¤Ï̵»ë */
+    return 1;
+  }
+
+  /* ¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ÎËöÈø¤ËÀܳ¤¹¤ë */
+  if (readyque[current->priority].tail) {
+    readyque[current->priority].tail->next = current;
+  } else {
+    readyque[current->priority].head = current;
+  }
+  readyque[current->priority].tail = current;
+  current->flags |= KZ_THREAD_FLAG_READY;
+
+  return 0;
+}
+
+static void thread_end(void)
+{
+  kz_exit();
+}
+
+/* ¥¹¥ì¥Ã¥É¤Î¥¹¥¿¡¼¥È¡¦¥¢¥Ã¥× */
+static void thread_init(kz_thread *thp)
+{
+  /* ¥¹¥ì¥Ã¥É¤Î¥á¥¤¥ó´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹ */
+  thp->init.func(thp->init.argc, thp->init.argv);
+  thread_end();
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_run():¥¹¥ì¥Ã¥É¤Îµ¯Æ°) */
+static kz_thread_id_t thread_run(kz_func_t func, char *name, int priority,
+                                int stacksize, int argc, char *argv[])
+{
+  int i;
+  kz_thread *thp;
+  uint32 *sp;
+  extern char userstack; /* ¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÇÄêµÁ¤µ¤ì¤ë¥¹¥¿¥Ã¥¯Îΰè */
+  static char *thread_stack = &userstack;
+
+  /* ¶õ¤¤¤Æ¤¤¤ë¥¿¥¹¥¯¡¦¥³¥ó¥È¥í¡¼¥ë¡¦¥Ö¥í¥Ã¥¯¤ò¸¡º÷ */
+  for (i = 0; i < THREAD_NUM; i++) {
+    thp = &threads[i];
+    if (!thp->init.func) /* ¸«¤Ä¤«¤Ã¤¿ */
+      break;
+  }
+  if (i == THREAD_NUM) /* ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿ */
+    return -1;
+
+  memset(thp, 0, sizeof(*thp));
+
+  /* ¥¿¥¹¥¯¡¦¥³¥ó¥È¥í¡¼¥ë¡¦¥Ö¥í¥Ã¥¯(TCB)¤ÎÀßÄê */
+  strcpy(thp->name, name);
+  thp->next     = NULL;
+  thp->priority = priority;
+  thp->flags    = 0;
+
+  thp->init.func = func;
+  thp->init.argc = argc;
+  thp->init.argv = argv;
+
+  /* ¥¹¥¿¥Ã¥¯Îΰè¤ò³ÍÆÀ */
+  memset(thread_stack, 0, stacksize);
+  thread_stack += stacksize;
+
+  thp->stack = thread_stack; /* ¥¹¥¿¥Ã¥¯¤òÀßÄê */
+
+  /* ¥¹¥¿¥Ã¥¯¤Î½é´ü²½ */
+  sp = (uint32 *)thp->stack;
+  *(--sp) = (uint32)thread_end;
+
+  /*
+   * ¥×¥í¥°¥é¥à¡¦¥«¥¦¥ó¥¿¤òÀßÄꤹ¤ë¡¥
+   * ¥¹¥ì¥Ã¥É¤ÎÍ¥ÀèÅÙ¤¬¥¼¥í¤Î¾ì¹ç¤Ë¤Ï¡¤³ä¹þ¤ß¶Ø»ß¥¹¥ì¥Ã¥É¤È¤¹¤ë¡¥
+   */
+  *(--sp) = (uint32)thread_init | ((uint32)(priority ? 0 : 0xc0) << 24);
+
+  *(--sp) = 0; /* ER6 */
+  *(--sp) = 0; /* ER5 */
+  *(--sp) = 0; /* ER4 */
+  *(--sp) = 0; /* ER3 */
+  *(--sp) = 0; /* ER2 */
+  *(--sp) = 0; /* ER1 */
+
+  /* ¥¹¥ì¥Ã¥É¤Î¥¹¥¿¡¼¥È¡¦¥¢¥Ã¥×(thread_init())¤ËÅϤ¹°ú¿ô */
+  *(--sp) = (uint32)thp;  /* ER0 */
+
+  /* ¥¹¥ì¥Ã¥É¤Î¥³¥ó¥Æ¥­¥¹¥È¤òÀßÄê */
+  thp->context.sp = (uint32)sp;
+
+  /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ò¸Æ¤Ó½Ð¤·¤¿¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ËÌ᤹ */
+  putcurrent();
+
+  /* ¿·µ¬ºîÀ®¤·¤¿¥¹¥ì¥Ã¥É¤ò¡¤¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ËÀܳ¤¹¤ë */
+  current = thp;
+  putcurrent();
+
+  return (kz_thread_id_t)current;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_exit():¥¹¥ì¥Ã¥É¤Î½ªÎ») */
+static int thread_exit(void)
+{
+  /*
+   * ËÜÍè¤Ê¤é¥¹¥¿¥Ã¥¯¤â²òÊü¤·¤ÆºÆÍøÍѤǤ­¤ë¤è¤¦¤Ë¤¹¤Ù¤­¤À¤¬¾Êά¡¥
+   * ¤³¤Î¤¿¤á¡¤¥¹¥ì¥Ã¥É¤òÉÑÈˤËÀ¸À®¡¦¾Ãµî¤¹¤ë¤è¤¦¤Ê¤³¤È¤Ï¸½¾õ¤Ç¤Ç¤­¤Ê¤¤¡¥
+   */
+  puts(current->name);
+  puts(" EXIT.\n");
+  memset(current, 0, sizeof(*current));
+  return 0;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_wait():¥¹¥ì¥Ã¥É¤Î¼Â¹Ô¸¢Êü´þ) */
+static int thread_wait(void)
+{
+  putcurrent();
+  return 0;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_sleep():¥¹¥ì¥Ã¥É¤Î¥¹¥ê¡¼¥×) */
+static int thread_sleep(void)
+{
+  return 0;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_wakeup():¥¹¥ì¥Ã¥É¤Î¥¦¥§¥¤¥¯¡¦¥¢¥Ã¥×) */
+static int thread_wakeup(kz_thread_id_t id)
+{
+  /* ¥¦¥§¥¤¥¯¡¦¥¢¥Ã¥×¤ò¸Æ¤Ó½Ð¤·¤¿¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ËÌ᤹ */
+  putcurrent();
+
+  /* »ØÄꤵ¤ì¤¿¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ËÀܳ¤·¤Æ¥¦¥§¥¤¥¯¡¦¥¢¥Ã¥×¤¹¤ë */
+  current = (kz_thread *)id;
+  putcurrent();
+
+  return 0;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_getid():¥¹¥ì¥Ã¥ÉID¼èÆÀ) */
+static kz_thread_id_t thread_getid(void)
+{
+  putcurrent();
+  return (kz_thread_id_t)current;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_chpri():¥¹¥ì¥Ã¥É¤ÎÍ¥ÀèÅÙÊѹ¹) */
+static int thread_chpri(int priority)
+{
+  int old = current->priority;
+  if (priority >= 0)
+    current->priority = priority; /* Í¥ÀèÅÙÊѹ¹ */
+  putcurrent(); /* ¿·¤·¤¤Í¥ÀèÅ٤Υì¥Ç¥£¡¼¡¦¥­¥å¡¼¤Ë·Ò¤®Ä¾¤¹ */
+  return old;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_kmalloc():ưŪ¥á¥â¥ê³ÍÆÀ) */
+static void *thread_kmalloc(int size)
+{
+  putcurrent();
+  return kzmem_alloc(size);
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_kfree():¥á¥â¥ê²òÊü) */
+static int thread_kmfree(char *p)
+{
+  kzmem_free(p);
+  putcurrent();
+  return 0;
+}
+
+/* ¥á¥Ã¥»¡¼¥¸¤ÎÁ÷¿®½èÍý */
+static void sendmsg(kz_msgbox *mboxp, kz_thread *thp, int size, char *p)
+{
+  kz_msgbuf *mp;
+
+  /* ¥á¥Ã¥»¡¼¥¸¡¦¥Ð¥Ã¥Õ¥¡¤ÎºîÀ® */
+  mp = (kz_msgbuf *)kzmem_alloc(sizeof(*mp));
+  if (mp == NULL)
+    kz_sysdown();
+  mp->next       = NULL;
+  mp->sender     = thp;
+  mp->param.size = size;
+  mp->param.p    = p;
+
+  /* ¥á¥Ã¥»¡¼¥¸¡¦¥Ü¥Ã¥¯¥¹¤ÎËöÈø¤Ë¥á¥Ã¥»¡¼¥¸¤òÀܳ¤¹¤ë */
+  if (mboxp->tail) {
+    mboxp->tail->next = mp;
+  } else {
+    mboxp->head = mp;
+  }
+  mboxp->tail = mp;
+}
+
+/* ¥á¥Ã¥»¡¼¥¸¤Î¼õ¿®½èÍý */
+static void recvmsg(kz_msgbox *mboxp)
+{
+  kz_msgbuf *mp;
+  kz_syscall_param_t *p;
+
+  /* ¥á¥Ã¥»¡¼¥¸¡¦¥Ü¥Ã¥¯¥¹¤ÎÀèƬ¤Ë¤¢¤ë¥á¥Ã¥»¡¼¥¸¤òÈ´¤­½Ð¤¹ */
+  mp = mboxp->head;
+  mboxp->head = mp->next;
+  if (mboxp->head == NULL)
+    mboxp->tail = NULL;
+  mp->next = NULL;
+
+  /* ¥á¥Ã¥»¡¼¥¸¤ò¼õ¿®¤¹¤ë¥¹¥ì¥Ã¥É¤ËÊÖ¤¹ÃͤòÀßÄꤹ¤ë */
+  p = mboxp->receiver->syscall.param;
+  p->un.recv.ret = (kz_thread_id_t)mp->sender;
+  if (p->un.recv.sizep)
+    *(p->un.recv.sizep) = mp->param.size;
+  if (p->un.recv.pp)
+    *(p->un.recv.pp) = mp->param.p;
+
+  /* ¼õ¿®ÂÔ¤Á¥¹¥ì¥Ã¥É¤Ï¤¤¤Ê¤¯¤Ê¤Ã¤¿¤Î¤Ç¡¤NULL¤ËÌ᤹ */
+  mboxp->receiver = NULL;
+
+  /* ¥á¥Ã¥»¡¼¥¸¡¦¥Ð¥Ã¥Õ¥¡¤Î²òÊü */
+  kzmem_free(mp);
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_send():¥á¥Ã¥»¡¼¥¸Á÷¿®) */
+static int thread_send(kz_msgbox_id_t id, int size, char *p)
+{
+  kz_msgbox *mboxp = &msgboxes[id];
+
+  putcurrent();
+  sendmsg(mboxp, current, size, p); /* ¥á¥Ã¥»¡¼¥¸¤ÎÁ÷¿®½èÍý */
+
+  /* ¼õ¿®ÂÔ¤Á¥¹¥ì¥Ã¥É¤¬Â¸ºß¤·¤Æ¤¤¤ë¾ì¹ç¤Ë¤Ï¼õ¿®½èÍý¤ò¹Ô¤¦ */
+  if (mboxp->receiver) {
+    current = mboxp->receiver; /* ¼õ¿®ÂÔ¤Á¥¹¥ì¥Ã¥É */
+    recvmsg(mboxp); /* ¥á¥Ã¥»¡¼¥¸¤Î¼õ¿®½èÍý */
+    putcurrent(); /* ¼õ¿®¤Ë¤è¤êÆ°ºî²Äǽ¤Ë¤Ê¤Ã¤¿¤Î¤Ç¡¤¥Ö¥í¥Ã¥¯²ò½ü¤¹¤ë */
+  }
+
+  return size;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_recv():¥á¥Ã¥»¡¼¥¸¼õ¿®) */
+static kz_thread_id_t thread_recv(kz_msgbox_id_t id, int *sizep, char **pp)
+{
+  kz_msgbox *mboxp = &msgboxes[id];
+
+  if (mboxp->receiver) /* Â¾¤Î¥¹¥ì¥Ã¥É¤¬¤¹¤Ç¤Ë¼õ¿®ÂÔ¤Á¤·¤Æ¤¤¤ë */
+    kz_sysdown();
+
+  mboxp->receiver = current; /* ¼õ¿®ÂÔ¤Á¥¹¥ì¥Ã¥É¤ËÀßÄê */
+
+  if (mboxp->head == NULL) {
+    /*
+     * ¥á¥Ã¥»¡¼¥¸¡¦¥Ü¥Ã¥¯¥¹¤Ë¥á¥Ã¥»¡¼¥¸¤¬Ìµ¤¤¤Î¤Ç¡¤¥¹¥ì¥Ã¥É¤ò
+     * ¥¹¥ê¡¼¥×¤µ¤»¤ë¡¥(¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤¬¥Ö¥í¥Ã¥¯¤¹¤ë)
+     */
+    return -1;
+  }
+
+  recvmsg(mboxp); /* ¥á¥Ã¥»¡¼¥¸¤Î¼õ¿®½èÍý */
+  putcurrent(); /* ¥á¥Ã¥»¡¼¥¸¤ò¼õ¿®¤Ç¤­¤¿¤Î¤Ç¡¤¥ì¥Ç¥£¡¼¾õÂ֤ˤ¹¤ë */
+
+  return current->syscall.param->un.recv.ret;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý(kz_setintr():³ä¹þ¤ß¥Ï¥ó¥É¥éÅÐÏ¿) */
+static int thread_setintr(softvec_type_t type, kz_handler_t handler)
+{
+  static void thread_intr(softvec_type_t type, unsigned long sp);
+
+  /*
+   * ³ä¹þ¤ß¤ò¼õ¤±ÉÕ¤±¤ë¤¿¤á¤Ë¡¤¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤Ë
+   * OS¤Î³ä¹þ¤ß½èÍý¤ÎÆþ¸ý¤È¤Ê¤ë´Ø¿ô¤òÅÐÏ¿¤¹¤ë¡¥
+   */
+  softvec_setintr(type, thread_intr);
+
+  handlers[type] = handler; /* OS¦¤«¤é¸Æ¤Ó½Ð¤¹³ä¹þ¤ß¥Ï¥ó¥É¥é¤òÅÐÏ¿ */
+  putcurrent();
+
+  return 0;
+}
+
+static void call_functions(kz_syscall_type_t type, kz_syscall_param_t *p)
+{
+  /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î¼Â¹ÔÃæ¤Ëcurrent¤¬½ñ¤­´¹¤ï¤ë¤Î¤ÇÃí°Õ */
+  switch (type) {
+  case KZ_SYSCALL_TYPE_RUN: /* kz_run() */
+    p->un.run.ret = thread_run(p->un.run.func, p->un.run.name,
+                              p->un.run.priority, p->un.run.stacksize,
+                              p->un.run.argc, p->un.run.argv);
+    break;
+  case KZ_SYSCALL_TYPE_EXIT: /* kz_exit() */
+    /* TCB¤¬¾Ãµî¤µ¤ì¤ë¤Î¤Ç¡¤Ìá¤êÃͤò½ñ¤­¹þ¤ó¤Ç¤Ï¤¤¤±¤Ê¤¤ */
+    thread_exit();
+    break;
+  case KZ_SYSCALL_TYPE_WAIT: /* kz_wait() */
+    p->un.wait.ret = thread_wait();
+    break;
+  case KZ_SYSCALL_TYPE_SLEEP: /* kz_sleep() */
+    p->un.sleep.ret = thread_sleep();
+    break;
+  case KZ_SYSCALL_TYPE_WAKEUP: /* kz_wakeup() */
+    p->un.wakeup.ret = thread_wakeup(p->un.wakeup.id);
+    break;
+  case KZ_SYSCALL_TYPE_GETID: /* kz_getid() */
+    p->un.getid.ret = thread_getid();
+    break;
+  case KZ_SYSCALL_TYPE_CHPRI: /* kz_chpri() */
+    p->un.chpri.ret = thread_chpri(p->un.chpri.priority);
+    break;
+  case KZ_SYSCALL_TYPE_KMALLOC: /* kz_kmalloc() */
+    p->un.kmalloc.ret = thread_kmalloc(p->un.kmalloc.size);
+    break;
+  case KZ_SYSCALL_TYPE_KMFREE: /* kz_kmfree() */
+    p->un.kmfree.ret = thread_kmfree(p->un.kmfree.p);
+    break;
+  case KZ_SYSCALL_TYPE_SEND: /* kz_send() */
+    p->un.send.ret = thread_send(p->un.send.id,
+                                p->un.send.size, p->un.send.p);
+    break;
+  case KZ_SYSCALL_TYPE_RECV: /* kz_recv() */
+    p->un.recv.ret = thread_recv(p->un.recv.id,
+                                p->un.recv.sizep, p->un.recv.pp);
+    break;
+  case KZ_SYSCALL_TYPE_SETINTR: /* kz_setintr() */
+    p->un.setintr.ret = thread_setintr(p->un.setintr.type,
+                                      p->un.setintr.handler);
+    break;
+  default:
+    break;
+  }
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î½èÍý */
+static void syscall_proc(kz_syscall_type_t type, kz_syscall_param_t *p)
+{
+  /*
+   * ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ò¸Æ¤Ó½Ð¤·¤¿¥¹¥ì¥Ã¥É¤ò¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤«¤é
+   * ³°¤·¤¿¾õÂ֤ǽèÍý´Ø¿ô¤ò¸Æ¤Ó½Ð¤¹¡¥¤³¤Î¤¿¤á¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ò
+   * ¸Æ¤Ó½Ð¤·¤¿¥¹¥ì¥Ã¥É¤ò¤½¤Î¤Þ¤ÞÆ°ºî·Ñ³¤µ¤»¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤
+   * ½èÍý´Ø¿ô¤ÎÆâÉô¤Ç putcurrent() ¤ò¹Ô¤¦É¬Íפ¬¤¢¤ë¡¥
+   */
+  getcurrent();
+  call_functions(type, p);
+}
+
+/* ¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤Î½èÍý */
+static void srvcall_proc(kz_syscall_type_t type, kz_syscall_param_t *p)
+{
+  /*
+   * ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤È¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤Î½èÍý´Ø¿ô¤ÎÆâÉô¤Ç¡¤
+   * ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤Î¼Â¹Ô¤·¤¿¥¹¥ì¥Ã¥ÉID¤òÆÀ¤ë¤¿¤á¤Ë current ¤ò
+   * »²¾È¤·¤Æ¤¤¤ëÉôʬ¤¬¤¢¤ê(¤¿¤È¤¨¤Ð thread_send() ¤Ê¤É)¡¤
+   * current ¤¬»Ä¤Ã¤Æ¤¤¤ë¤È¸íÆ°ºî¤¹¤ë¤¿¤á NULL ¤ËÀßÄꤹ¤ë¡¥
+   * ¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤Ï thread_intrvec() ÆâÉô¤Î³ä¹þ¤ß¥Ï¥ó¥É¥é¸Æ¤Ó½Ð¤·¤Î
+   * ±äĹ¤Ç¸Æ¤Ð¤ì¤Æ¤¤¤ë¤Ï¤º¤Ç¤Ê¤Î¤Ç¡¤¸Æ¤Ó½Ð¤·¸å¤Ë thread_intrvec() ¤Ç
+   * ¥¹¥±¥¸¥å¡¼¥ê¥ó¥°½èÍý¤¬¹Ô¤ï¤ì¡¤current ¤ÏºÆÀßÄꤵ¤ì¤ë¡¥
+   */
+  current = NULL;
+  call_functions(type, p);
+}
+
+/* ¥¹¥ì¥Ã¥É¤Î¥¹¥±¥¸¥å¡¼¥ê¥ó¥° */
+static void schedule(void)
+{
+  int i;
+
+  /*
+   * Í¥Àè½ç°Ì¤Î¹â¤¤½ç(Í¥ÀèÅ٤οôÃͤµ¤¤½ç)¤Ë¥ì¥Ç¥£¡¼¡¦¥­¥å¡¼¤ò¸«¤Æ¡¤
+   * Æ°ºî²Äǽ¤Ê¥¹¥ì¥Ã¥É¤ò¸¡º÷¤¹¤ë¡¥
+   */
+  for (i = 0; i < PRIORITY_NUM; i++) {
+    if (readyque[i].head) /* ¸«¤Ä¤«¤Ã¤¿ */
+      break;
+  }
+  if (i == PRIORITY_NUM) /* ¸«¤Ä¤«¤é¤Ê¤«¤Ã¤¿ */
+    kz_sysdown();
+
+  current = readyque[i].head; /* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É¤ËÀßÄꤹ¤ë */
+}
+
+static void syscall_intr(void)
+{
+  syscall_proc(current->syscall.type, current->syscall.param);
+}
+
+static void softerr_intr(void)
+{
+  puts(current->name);
+  puts(" DOWN.\n");
+  getcurrent(); /* ¥ì¥Ç¥£¡¼¥­¥å¡¼¤«¤é³°¤¹ */
+  thread_exit(); /* ¥¹¥ì¥Ã¥É½ªÎ»¤¹¤ë */
+}
+
+/* ³ä¹þ¤ß½èÍý¤ÎÆþ¸ý´Ø¿ô */
+static void thread_intr(softvec_type_t type, unsigned long sp)
+{
+  /* ¥«¥ì¥ó¥È¡¦¥¹¥ì¥Ã¥É¤Î¥³¥ó¥Æ¥­¥¹¥È¤òÊݸ¤¹¤ë */
+  current->context.sp = sp;
+
+  /*
+   * ³ä¹þ¤ß¤´¤È¤Î½èÍý¤ò¼Â¹Ô¤¹¤ë¡¥
+   * SOFTVEC_TYPE_SYSCALL, SOFTVEC_TYPE_SOFTERR ¤Î¾ì¹ç¤Ï
+   * syscall_intr(), softerr_intr() ¤¬¥Ï¥ó¥É¥é¤ËÅÐÏ¿¤µ¤ì¤Æ¤¤¤ë¤Î¤Ç¡¤
+   * ¤½¤ì¤é¤¬¼Â¹Ô¤µ¤ì¤ë¡¥
+   * ¤½¤ì°Ê³°¤Î¾ì¹ç¤Ï¡¤kz_setintr()¤Ë¤è¤Ã¤Æ¥æ¡¼¥¶ÅÐÏ¿¤µ¤ì¤¿¥Ï¥ó¥É¥é¤¬
+   * ¼Â¹Ô¤µ¤ì¤ë¡¥
+   */
+  if (handlers[type])
+    handlers[type]();
+
+  schedule(); /* ¥¹¥ì¥Ã¥É¤Î¥¹¥±¥¸¥å¡¼¥ê¥ó¥° */
+
+  /*
+   * ¥¹¥ì¥Ã¥É¤Î¥Ç¥£¥¹¥Ñ¥Ã¥Á
+   * (dispatch()´Ø¿ô¤ÎËÜÂΤÏstartup.s¤Ë¤¢¤ê¡¤¥¢¥»¥ó¥Ö¥é¤Çµ­½Ò¤µ¤ì¤Æ¤¤¤ë)
+   */
+  dispatch(&current->context);
+  /* ¤³¤³¤Ë¤ÏÊ֤äƤ³¤Ê¤¤ */
+}
+
+void kz_start(kz_func_t func, char *name, int priority, int stacksize,
+             int argc, char *argv[])
+{
+  kzmem_init(); /* Æ°Åª¥á¥â¥ê¤Î½é´ü²½ */
+
+  /*
+   * °Ê¹ß¤Ç¸Æ¤Ó½Ð¤¹¥¹¥ì¥Ã¥É´ØÏ¢¤Î¥é¥¤¥Ö¥é¥ê´Ø¿ô¤ÎÆâÉô¤Ç current ¤ò
+   * ¸«¤Æ¤¤¤ë¾ì¹ç¤¬¤¢¤ë¤Î¤Ç¡¤current ¤ò NULL ¤Ë½é´ü²½¤·¤Æ¤ª¤¯¡¥
+   */
+  current = NULL;
+
+  memset(readyque, 0, sizeof(readyque));
+  memset(threads,  0, sizeof(threads));
+  memset(handlers, 0, sizeof(handlers));
+  memset(msgboxes, 0, sizeof(msgboxes));
+
+  /* ³ä¹þ¤ß¥Ï¥ó¥É¥é¤ÎÅÐÏ¿ */
+  thread_setintr(SOFTVEC_TYPE_SYSCALL, syscall_intr); /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë */
+  thread_setintr(SOFTVEC_TYPE_SOFTERR, softerr_intr); /* ¥À¥¦¥óÍ×°øȯÀ¸ */
+
+  /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ëȯ¹ÔÉԲĤʤΤÇľÀÜ´Ø¿ô¤ò¸Æ¤Ó½Ð¤·¤Æ¥¹¥ì¥Ã¥ÉºîÀ®¤¹¤ë */
+  current = (kz_thread *)thread_run(func, name, priority, stacksize,
+                                   argc, argv);
+
+  /* ºÇ½é¤Î¥¹¥ì¥Ã¥É¤òµ¯Æ° */
+  dispatch(&current->context);
+
+  /* ¤³¤³¤Ë¤ÏÊ֤äƤ³¤Ê¤¤ */
+}
+
+void kz_sysdown(void)
+{
+  puts("system error!\n");
+  while (1)
+    ;
+}
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¸Æ¤Ó½Ð¤·Íѥ饤¥Ö¥é¥ê´Ø¿ô */
+void kz_syscall(kz_syscall_type_t type, kz_syscall_param_t *param)
+{
+  current->syscall.type  = type;
+  current->syscall.param = param;
+  asm volatile ("trapa #0"); /* ¥È¥é¥Ã¥×³ä¹þ¤ßȯ¹Ô */
+}
+
+/* ¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¸Æ¤Ó½Ð¤·Íѥ饤¥Ö¥é¥ê´Ø¿ô */
+void kz_srvcall(kz_syscall_type_t type, kz_syscall_param_t *param)
+{
+  srvcall_proc(type, param);
+}
diff --git a/firm/sample/sample1/os/kozos.h b/firm/sample/sample1/os/kozos.h
new file mode 100644 (file)
index 0000000..e36eefa
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _KOZOS_H_INCLUDED_
+#define _KOZOS_H_INCLUDED_
+
+#include "defines.h"
+#include "interrupt.h"
+#include "syscall.h"
+#include "driver.h"
+#include "task.h"
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë */
+kz_thread_id_t kz_run(kz_func_t func, char *name, int priority, int stacksize,
+                     int argc, char *argv[]);
+void kz_exit(void);
+int kz_wait(void);
+int kz_sleep(void);
+int kz_wakeup(kz_thread_id_t id);
+kz_thread_id_t kz_getid(void);
+int kz_chpri(int priority);
+void *kz_kmalloc(int size);
+int kz_kmfree(void *p);
+int kz_send(kz_msgbox_id_t id, int size, char *p);
+kz_thread_id_t kz_recv(kz_msgbox_id_t id, int *sizep, char **pp);
+int kz_setintr(softvec_type_t type, kz_handler_t handler);
+
+/* ¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë */
+int kx_wakeup(kz_thread_id_t id);
+void *kx_kmalloc(int size);
+int kx_kmfree(void *p);
+int kx_send(kz_msgbox_id_t id, int size, char *p);
+
+/* ¥é¥¤¥Ö¥é¥ê´Ø¿ô */
+void kz_start(kz_func_t func, char *name, int priority, int stacksize,
+             int argc, char *argv[]);
+void kz_sysdown(void);
+void kz_syscall(kz_syscall_type_t type, kz_syscall_param_t *param);
+void kz_srvcall(kz_syscall_type_t type, kz_syscall_param_t *param);
+
+#endif
diff --git a/firm/sample/sample1/os/ld.scr b/firm/sample/sample1/os/ld.scr
new file mode 100644 (file)
index 0000000..f1a2f15
--- /dev/null
@@ -0,0 +1,70 @@
+OUTPUT_FORMAT("elf32-h8300")
+OUTPUT_ARCH(h8300h)
+ENTRY("_start")
+
+MEMORY
+{
+       /* DRAM (2MB) */
+       dramall(rwx)    : o = 0x400000, l = 0x200000 /* 2MB */
+       ram(rwx)        : o = 0x400000 + 0x100, l = 0x200000 - 0x100
+
+       /* internal RAM (16KB) */
+       ramall(rwx)     : o = 0xffbf20, l = 0x004000 /* 16KB */
+       softvec(rw)     : o = 0xffbf20, l = 0x000040 /* top of RAM */
+       userstack(rw)   : o = 0xffc000, l = 0x003f00
+       bootstack(rw)   : o = 0xffff00, l = 0x000000
+       intrstack(rw)   : o = 0xffff00, l = 0x000000 /* end of RAM */
+}
+
+SECTIONS
+{
+       .softvec : {
+               _softvec = .;
+       } > softvec
+
+       .text : {
+               _text_start = . ;
+               *(.text)
+               _etext = . ;
+       } > ram
+
+       .rodata : {
+               _rodata_start = . ;
+               *(.strings)
+               *(.rodata)
+               *(.rodata.*)
+               _erodata = . ;
+       } > ram
+
+       .data : {
+               _data_start = . ;
+               *(.data)
+               _edata = . ;
+       } > ram
+
+       .bss : {
+               _bss_start = . ;
+               *(.bss)
+               *(COMMON)
+               _ebss = . ;
+       } > ram
+
+       . = ALIGN(4);
+       _end = . ;
+
+       .freearea : {
+               _freearea = .;
+       } > ram
+
+       .userstack : {
+               _userstack = .;
+       } > userstack
+
+       .bootstack : {
+               _bootstack = .;
+       } > bootstack
+
+       .intrstack : {
+               _intrstack = .;
+       } > intrstack
+}
diff --git a/firm/sample/sample1/os/led.c b/firm/sample/sample1/os/led.c
new file mode 100644 (file)
index 0000000..c188e38
--- /dev/null
@@ -0,0 +1,92 @@
+#include "led.h"
+#include "defines.h"
+#include "portconf.h"
+
+int led_init(void)
+{
+  volatile uint8 mask = PORTCONF_PABIT_LED1 | PORTCONF_PABIT_LED2 | PORTCONF_PABIT_LEDG | PORTCONF_PABIT_LEDR;
+
+  /*
+   * ¥Ý¡¼¥È¥Ç¥£¥ì¥¯¥·¥ç¥ó¤òÀßÄꤹ¤ëÁ°¤Ë¥Ç¡¼¥¿¥ì¥¸¥¹¥¿¤ò½é´ü²½¤¹¤ë¡£
+   * ÉéÏÀÍý¤Ê¤Î¤Ç¡¢½é´üÃͤΥ¼¥í¤À¤È½ÐÎϤˤ·¤¿»þÅÀ¤ÇÅÀÅô¾õÂ֤Ȥʤ롣
+   */
+  *PORTCONF_PADR |= mask;
+
+  /*
+   * ¥Ý¡¼¥ÈA¤Î¥Ó¥Ã¥È2,3,6,7¤Ï½ÐÎϥݡ¼¥È¤È¤·¤ÆÀßÄꤹ¤ë¡£
+   *
+   * ¥Ç¡¼¥¿¥Ç¥£¥ì¥¯¥·¥ç¥ó¥ì¥¸¥¹¥¿¤ÏWrite Only¤Ê¤Î¤Ç¡¢
+   * Â¾¤Î¥Ó¥Ã¥È¤ÎÀßÄ꤬ɬÍפˤʤä¿»þÅÀ¤Ç¡¢
+   * ¥Ý¡¼¥ÈÆþ½ÐÎÏÀßÄê¤ò¤Þ¤È¤á¤Æ´ÉÍý¤¹¤ë¤è¤¦¤Ê
+   * ²¿¤é¤«¤ÎÂкö¤¬É¬ÍפȤʤë¤À¤í¤¦¡£
+   */
+  *PORTCONF_PADDR = 0xCC;
+
+  return 0;
+}
+
+int led_write(led_target_t target, led_state_t state)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = PORTCONF_PABIT_LED1;
+      break;
+    case Led2:
+      mask = PORTCONF_PABIT_LED2;
+      break;
+    case LedG:
+      mask = PORTCONF_PABIT_LEDG;
+      break;
+    case LedR:
+      mask = PORTCONF_PABIT_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  switch (state) {
+    case LedOn:
+      *PORTCONF_PADR &= ~mask;
+      break;
+    case LedOff:
+      *PORTCONF_PADR |= mask;
+      break;
+    default:
+      return -1;
+  }
+
+  return 0;
+}
+
+int led_toggle(led_target_t target)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = PORTCONF_PABIT_LED1;
+      break;
+    case Led2:
+      mask = PORTCONF_PABIT_LED2;
+      break;
+    case LedG:
+      mask = PORTCONF_PABIT_LEDG;
+      break;
+    case LedR:
+      mask = PORTCONF_PABIT_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  if (*PORTCONF_PADR & mask) {
+    *PORTCONF_PADR &= ~mask;
+  } else {
+    *PORTCONF_PADR |= mask;
+  }
+
+  return 0;
+}
+
diff --git a/firm/sample/sample1/os/led.h b/firm/sample/sample1/os/led.h
new file mode 100644 (file)
index 0000000..cd12388
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef _LED_H_INCLUDED_
+#define _LED_H_INCLUDED_
+
+typedef enum {
+  Led1,
+  Led2,
+  LedG,
+  LedR,
+} led_target_t;
+
+typedef enum {
+  LedOn,
+  LedOff,
+} led_state_t;
+
+int led_init(void);
+int led_write(led_target_t target, led_state_t state);
+int led_toggle(led_target_t target);
+
+#endif
+
diff --git a/firm/sample/sample1/os/lib.c b/firm/sample/sample1/os/lib.c
new file mode 100644 (file)
index 0000000..04a6afb
--- /dev/null
@@ -0,0 +1,135 @@
+#include "defines.h"
+#include "serial.h"
+#include "lib.h"
+
+void *memset(void *b, int c, long len)
+{
+  char *p;
+  for (p = b; len > 0; len--)
+    *(p++) = c;
+  return b;
+}
+
+void *memcpy(void *dst, const void *src, long len)
+{
+  char *d = dst;
+  const char *s = src;
+  for (; len > 0; len--)
+    *(d++) = *(s++);
+  return dst;
+}
+
+int memcmp(const void *b1, const void *b2, long len)
+{
+  const char *p1 = b1, *p2 = b2;
+  for (; len > 0; len--) {
+    if (*p1 != *p2)
+      return (*p1 > *p2) ? 1 : -1;
+    p1++;
+    p2++;
+  }
+  return 0;
+}
+
+int strlen(const char *s)
+{
+  int len;
+  for (len = 0; *s; s++, len++)
+    ;
+  return len;
+}
+
+char *strcpy(char *dst, const char *src)
+{
+  char *d = dst;
+  for (;; dst++, src++) {
+    *dst = *src;
+    if (!*src) break;
+  }
+  return d;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+  while (*s1 || *s2) {
+    if (*s1 != *s2)
+      return (*s1 > *s2) ? 1 : -1;
+    s1++;
+    s2++;
+  }
+  return 0;
+}
+
+int strncmp(const char *s1, const char *s2, int len)
+{
+  while ((*s1 || *s2) && (len > 0)) {
+    if (*s1 != *s2)
+      return (*s1 > *s2) ? 1 : -1;
+    s1++;
+    s2++;
+    len--;
+  }
+  return 0;
+}
+
+/* £±Ê¸»úÁ÷¿® */
+int putc(unsigned char c)
+{
+  if (c == '\n')
+    serial_send_byte(SERIAL_DEFAULT_DEVICE, '\r');
+  return serial_send_byte(SERIAL_DEFAULT_DEVICE, c);
+}
+
+/* £±Ê¸»ú¼õ¿® */
+unsigned char getc(void)
+{
+  unsigned char c = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+  c = (c == '\r') ? '\n' : c;
+  putc(c); /* ¥¨¥³¡¼¡¦¥Ð¥Ã¥¯ */
+  return c;
+}
+
+/* Ê¸»úÎóÁ÷¿® */
+int puts(unsigned char *str)
+{
+  while (*str)
+    putc(*(str++));
+  return 0;
+}
+
+/* Ê¸»úÎó¼õ¿® */
+int gets(unsigned char *buf)
+{
+  int i = 0;
+  unsigned char c;
+  do {
+    c = getc();
+    if (c == '\n')
+      c = '\0';
+    buf[i++] = c;
+  } while (c);
+  return i - 1;
+}
+
+/* ¿ôÃͤÎ16¿Êɽ¼¨ */
+int putxval(unsigned long value, int column)
+{
+  char buf[9];
+  char *p;
+
+  p = buf + sizeof(buf) - 1;
+  *(p--) = '\0';
+
+  if (!value && !column)
+    column++;
+
+  while (value || column) {
+    *(p--) = "0123456789abcdef"[value & 0xf];
+    value >>= 4;
+    if (column) column--;
+  }
+
+  puts(p + 1);
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/lib.h b/firm/sample/sample1/os/lib.h
new file mode 100644 (file)
index 0000000..54009be
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _LIB_H_INCLUDED_
+#define _LIB_H_INCLUDED_
+
+void *memset(void *b, int c, long len);
+void *memcpy(void *dst, const void *src, long len);
+int memcmp(const void *b1, const void *b2, long len);
+int strlen(const char *s);
+char *strcpy(char *dst, const char *src);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, int len);
+
+int putc(unsigned char c);    /* £±Ê¸»úÁ÷¿® */
+unsigned char getc(void);     /* £±Ê¸»ú¼õ¿® */
+int puts(unsigned char *str); /* Ê¸»úÎóÁ÷¿® */
+int gets(unsigned char *buf); /* Ê¸»úÎó¼õ¿® */
+int putxval(unsigned long value, int column); /* ¿ôÃͤÎ16¿Êɽ¼¨ */
+
+#endif
diff --git a/firm/sample/sample1/os/logo_20x16.bmp b/firm/sample/sample1/os/logo_20x16.bmp
new file mode 100644 (file)
index 0000000..31bca11
Binary files /dev/null and b/firm/sample/sample1/os/logo_20x16.bmp differ
diff --git a/firm/sample/sample1/os/logo_30x24.bmp b/firm/sample/sample1/os/logo_30x24.bmp
new file mode 100644 (file)
index 0000000..94fea69
Binary files /dev/null and b/firm/sample/sample1/os/logo_30x24.bmp differ
diff --git a/firm/sample/sample1/os/logo_40x32.bmp b/firm/sample/sample1/os/logo_40x32.bmp
new file mode 100644 (file)
index 0000000..52c765c
Binary files /dev/null and b/firm/sample/sample1/os/logo_40x32.bmp differ
diff --git a/firm/sample/sample1/os/main.c b/firm/sample/sample1/os/main.c
new file mode 100644 (file)
index 0000000..da52727
--- /dev/null
@@ -0,0 +1,38 @@
+#include "defines.h"
+#include "kozos.h"
+#include "interrupt.h"
+#include "lib.h"
+
+/* ¥·¥¹¥Æ¥à¡¦¥¿¥¹¥¯¤È¥æ¡¼¥¶¡¦¥¿¥¹¥¯¤Îµ¯Æ° */
+static int start_threads(int argc, char *argv[])
+{
+  kz_run(driver_console,    "dConsole",      1, 0x200, 0, NULL);
+  kz_run(driver_timer,      "dTimer",        2, 0x200, 0, NULL);
+  kz_run(driver_led,        "dLed",          3, 0x200, 0, NULL);
+  kz_run(driver_lcd,        "dLcd",          4, 0x200, 0, NULL);
+  kz_run(driver_audio,      "dAudio",        5, 0x200, 0, NULL);
+  kz_run(task_command,      "tCommand",      6, 0x200, 0, NULL);
+  kz_run(task_userinput,    "tUserinput",    7, 0x200, 0, NULL);
+  kz_run(task_ir,           "tIr",           8, 0x200, 0, NULL);
+
+  kz_chpri(15); /* Í¥Àè½ç°Ì¤ò²¼¤²¤Æ¡¤¥¢¥¤¥É¥ë¥¹¥ì¥Ã¥É¤Ë°Ü¹Ô¤¹¤ë */
+  INTR_ENABLE; /* ³ä¹þ¤ßÍ­¸ú¤Ë¤¹¤ë */
+  while (1) {
+    asm volatile ("sleep"); /* ¾ÊÅÅÎϥ⡼¥É¤Ë°Ü¹Ô */
+  }
+
+  return 0;
+}
+
+int main(void)
+{
+  INTR_DISABLE; /* ³ä¹þ¤ß̵¸ú¤Ë¤¹¤ë */
+
+  puts("kozos boot succeed!\n");
+
+  /* OS¤ÎÆ°ºî³«»Ï */
+  kz_start(start_threads, "idle", 0, 0x100, 0, NULL);
+  /* ¤³¤³¤Ë¤ÏÌá¤Ã¤Æ¤³¤Ê¤¤ */
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/memory.c b/firm/sample/sample1/os/memory.c
new file mode 100644 (file)
index 0000000..75925d0
--- /dev/null
@@ -0,0 +1,117 @@
+#include "defines.h"
+#include "kozos.h"
+#include "lib.h"
+#include "memory.h"
+
+/*
+ * ¥á¥â¥ê¡¦¥Ö¥í¥Ã¥¯¹½Â¤ÂÎ
+ * (³ÍÆÀ¤µ¤ì¤¿³ÆÎΰè¤Ï¡¤ÀèƬ¤Ë°Ê²¼¤Î¹½Â¤ÂΤò»ý¤Ã¤Æ¤¤¤ë)
+ */
+typedef struct _kzmem_block {
+  struct _kzmem_block *next;
+  int size;
+} kzmem_block;
+
+/* ¥á¥â¥ê¡¦¥×¡¼¥ë */
+typedef struct _kzmem_pool {
+  int size;
+  int num;
+  kzmem_block *free;
+} kzmem_pool;
+
+/* ¥á¥â¥ê¡¦¥×¡¼¥ë¤ÎÄêµÁ(¸Ä¡¹¤Î¥µ¥¤¥º¤È¸Ä¿ô) */
+static kzmem_pool pool[] = {
+  { 16, 8, NULL }, { 32, 8, NULL }, { 64, 4, NULL },
+};
+
+#define MEMORY_AREA_NUM (sizeof(pool) / sizeof(*pool))
+
+/* ¥á¥â¥ê¡¦¥×¡¼¥ë¤Î½é´ü²½ */
+static int kzmem_init_pool(kzmem_pool *p)
+{
+  int i;
+  kzmem_block *mp;
+  kzmem_block **mpp;
+  extern char freearea; /* ¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÇÄêµÁ¤µ¤ì¤ë¶õ¤­Îΰè */
+  static char *area = &freearea;
+
+  mp = (kzmem_block *)area;
+
+  /* ¸Ä¡¹¤ÎÎΰè¤ò¤¹¤Ù¤Æ²òÊüºÑ¤ß¥ê¥ó¥¯¥ê¥¹¥È¤Ë·Ò¤° */
+  mpp = &p->free;
+  for (i = 0; i < p->num; i++) {
+    *mpp = mp;
+    memset(mp, 0, sizeof(*mp));
+    mp->size = p->size;
+    mpp = &(mp->next);
+    mp = (kzmem_block *)((char *)mp + p->size);
+    area += p->size;
+  }
+
+  return 0;
+}
+
+/* Æ°Åª¥á¥â¥ê¤Î½é´ü²½ */
+int kzmem_init(void)
+{
+  int i;
+  for (i = 0; i < MEMORY_AREA_NUM; i++) {
+    kzmem_init_pool(&pool[i]); /* ³Æ¥á¥â¥ê¡¦¥×¡¼¥ë¤ò½é´ü²½¤¹¤ë */
+  }
+  return 0;
+}
+
+/* Æ°Åª¥á¥â¥ê¤Î³ÍÆÀ */
+void *kzmem_alloc(int size)
+{
+  int i;
+  kzmem_block *mp;
+  kzmem_pool *p;
+
+  for (i = 0; i < MEMORY_AREA_NUM; i++) {
+    p = &pool[i];
+    if (size <= p->size - sizeof(kzmem_block)) {
+      if (p->free == NULL) { /* ²òÊüºÑ¤ßÎΰ褬̵¤¤(¥á¥â¥ê¡¦¥Ö¥í¥Ã¥¯ÉÔ­) */
+       kz_sysdown();
+       return NULL;
+      }
+      /* ²òÊüºÑ¤ß¥ê¥ó¥¯¥ê¥¹¥È¤«¤éÎΰè¤ò¼èÆÀ¤¹¤ë */
+      mp = p->free;
+      p->free = p->free->next;
+      mp->next = NULL;
+
+      /*
+       * ¼ÂºÝ¤ËÍøÍѲÄǽ¤ÊÎΰè¤Ï¡¤¥á¥â¥ê¡¦¥Ö¥í¥Ã¥¯¹½Â¤ÂΤÎľ¸å¤ÎÎΰè¤Ë
+       * ¤Ê¤ë¤Î¤Ç¡¤Ä¾¸å¤Î¥¢¥É¥ì¥¹¤òÊÖ¤¹¡¥
+       */
+      return mp + 1;
+    }
+  }
+
+  /* »ØÄꤵ¤ì¤¿¥µ¥¤¥º¤ÎÎΰè¤ò³ÊǼ¤Ç¤­¤ë¥á¥â¥ê¡¦¥×¡¼¥ë¤¬Ìµ¤¤ */
+  kz_sysdown();
+  return NULL;
+}
+
+/* ¥á¥â¥ê¤Î²òÊü */
+void kzmem_free(void *mem)
+{
+  int i;
+  kzmem_block *mp;
+  kzmem_pool *p;
+
+  /* Îΰè¤ÎľÁ°¤Ë¤¢¤ë(¤Ï¤º¤Î)¥á¥â¥ê¡¦¥Ö¥í¥Ã¥¯¹½Â¤ÂΤò¼èÆÀ */
+  mp = ((kzmem_block *)mem - 1);
+
+  for (i = 0; i < MEMORY_AREA_NUM; i++) {
+    p = &pool[i];
+    if (mp->size == p->size) {
+      /* Îΰè¤ò²òÊüºÑ¤ß¥ê¥ó¥¯¥ê¥¹¥È¤ËÌ᤹ */
+      mp->next = p->free;
+      p->free = mp;
+      return;
+    }
+  }
+
+  kz_sysdown();
+}
diff --git a/firm/sample/sample1/os/memory.h b/firm/sample/sample1/os/memory.h
new file mode 100644 (file)
index 0000000..260b191
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _KOZOS_MEMORY_H_INCLUDED_
+#define _KOZOS_MEMORY_H_INCLUDED_
+
+int kzmem_init(void);        /* Æ°Åª¥á¥â¥ê¤Î½é´ü²½ */
+void *kzmem_alloc(int size); /* Æ°Åª¥á¥â¥ê¤Î³ÍÆÀ */
+void kzmem_free(void *mem);  /* ¥á¥â¥ê¤Î²òÊü */
+
+#endif
diff --git a/firm/sample/sample1/os/mmc.c b/firm/sample/sample1/os/mmc.c
new file mode 100644 (file)
index 0000000..4a2d4aa
--- /dev/null
@@ -0,0 +1,390 @@
+/*------------------------------------------------------------------------/\r
+/  Bitbanging MMCv3/SDv1/SDv2 (in SPI mode) control module for PFF\r
+/-------------------------------------------------------------------------/\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * This software is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/--------------------------------------------------------------------------/\r
+ Features:\r
+\r
+ * Very Easy to Port\r
+   It uses only 4-6 bit of GPIO port. No interrupt, no SPI port is used.\r
+\r
+ * Platform Independent\r
+   You need to modify only a few macros to control GPIO ports.\r
+\r
+/-------------------------------------------------------------------------*/\r
+\r
+\r
+#include "diskio.h"\r
+\r
+#define H8_3069F_P4DR   ((volatile uint8 *)0xFFFFD3)\r
+#define H8_3069F_PBDR   ((volatile uint8 *)0xFFFFDA)\r
+\r
+#define PB_BIT_SCLK     (1 << 5)\r
+#define PB_BIT_MOSI     (1 << 6)\r
+#define PB_BIT_MISO     (1 << 7)\r
+#define P4_BIT_CS       (1 << 0)\r
+\r
+/*-------------------------------------------------------------------------*/\r
+/* Platform dependent macros and functions needed to be modified           */\r
+/*-------------------------------------------------------------------------*/\r
+\r
+#define INIT_PORT()    do { } while (0)    /* Initialize MMC control port (CS/CLK/DI:output, DO:input) */\r
+#define DLY_US(n)      do { volatile uint32 dlycnt; for (dlycnt = 0; dlycnt < (n) * 10; dlycnt++) {} } while (0)    /* Delay n microseconds */\r
+#define FORWARD(d)     do { } while (0)    /* Data in-time processing function (depends on the project) */\r
+\r
+#define CS_H()         do { *H8_3069F_P4DR |=  P4_BIT_CS; } while (0)      /* Set MMC CS "high" */\r
+#define CS_L()         do { *H8_3069F_P4DR &= ~P4_BIT_CS; } while (0)      /* Set MMC CS "low" */\r
+#define CK_H()         do { *H8_3069F_PBDR |=  PB_BIT_SCLK; } while (0)    /* Set MMC SCLK "high" */\r
+#define CK_L()         do { *H8_3069F_PBDR &= ~PB_BIT_SCLK; } while (0)    /* Set MMC SCLK "low" */\r
+#define DI_H()         do { *H8_3069F_PBDR |=  PB_BIT_MOSI; } while (0)    /* Set MMC DI "high" */\r
+#define DI_L()         do { *H8_3069F_PBDR &= ~PB_BIT_MOSI; } while (0)    /* Set MMC DI "low" */\r
+#define DO             ((*H8_3069F_PBDR & PB_BIT_MISO) ? 1 : 0)            /* Get MMC DO value (high:true, low:false) */\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Module Private Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+/* Definitions for MMC/SDC command */\r
+#define CMD0   (0x40+0)        /* GO_IDLE_STATE */\r
+#define CMD1   (0x40+1)        /* SEND_OP_COND (MMC) */\r
+#define        ACMD41  (0xC0+41)       /* SEND_OP_COND (SDC) */\r
+#define CMD8   (0x40+8)        /* SEND_IF_COND */\r
+#define CMD16  (0x40+16)       /* SET_BLOCKLEN */\r
+#define CMD17  (0x40+17)       /* READ_SINGLE_BLOCK */\r
+#define CMD24  (0x40+24)       /* WRITE_BLOCK */\r
+#define CMD55  (0x40+55)       /* APP_CMD */\r
+#define CMD58  (0x40+58)       /* READ_OCR */\r
+\r
+/* Card type flags (CardType) */\r
+#define CT_MMC                         0x01    /* MMC ver 3 */\r
+#define CT_SD1                         0x02    /* SD ver 1 */\r
+#define CT_SD2                         0x04    /* SD ver 2 */\r
+#define CT_SDC                         (CT_SD1|CT_SD2) /* SD */\r
+#define CT_BLOCK                       0x08    /* Block addressing */\r
+\r
+\r
+\r
+static\r
+BYTE CardType;                 /* b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing */\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Transmit a byte to the MMC (bitbanging)                               */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void xmit_mmc (\r
+       BYTE d                  /* Data to be sent */\r
+)\r
+{\r
+       if (d & 0x80) DI_H(); else DI_L();      /* bit7 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x40) DI_H(); else DI_L();      /* bit6 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x20) DI_H(); else DI_L();      /* bit5 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x10) DI_H(); else DI_L();      /* bit4 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x08) DI_H(); else DI_L();      /* bit3 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x04) DI_H(); else DI_L();      /* bit2 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x02) DI_H(); else DI_L();      /* bit1 */\r
+       CK_H(); CK_L();\r
+       if (d & 0x01) DI_H(); else DI_L();      /* bit0 */\r
+       CK_H(); CK_L();\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Receive a byte from the MMC (bitbanging)                              */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE rcvr_mmc (void)\r
+{\r
+       BYTE r;\r
+\r
+\r
+       DI_H(); /* Send 0xFF */\r
+\r
+       r = 0;   if (DO) r++;   /* bit7 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit6 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit5 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit4 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit3 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit2 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit1 */\r
+       CK_H(); CK_L();\r
+       r <<= 1; if (DO) r++;   /* bit0 */\r
+       CK_H(); CK_L();\r
+\r
+       return r;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Skip bytes on the MMC (bitbanging)                                    */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void skip_mmc (\r
+       WORD n          /* Number of bytes to skip */\r
+)\r
+{\r
+       DI_H(); /* Send 0xFF */\r
+\r
+       do {\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+               CK_H(); CK_L();\r
+       } while (--n);\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Deselect the card and release SPI bus                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+void release_spi (void)\r
+{\r
+       CS_H();\r
+       rcvr_mmc();\r
+}\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Send a command packet to MMC                                          */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE send_cmd (\r
+       BYTE cmd,               /* Command byte */\r
+       DWORD arg               /* Argument */\r
+)\r
+{\r
+       BYTE n, res;\r
+\r
+\r
+       if (cmd & 0x80) {       /* ACMD<n> is the command sequense of CMD55-CMD<n> */\r
+               cmd &= 0x7F;\r
+               res = send_cmd(CMD55, 0);\r
+               if (res > 1) return res;\r
+       }\r
+\r
+       /* Select the card */\r
+       CS_H(); rcvr_mmc();\r
+       CS_L(); rcvr_mmc();\r
+\r
+       /* Send a command packet */\r
+       xmit_mmc(cmd);                                  /* Start + Command index */\r
+       xmit_mmc((BYTE)(arg >> 24));    /* Argument[31..24] */\r
+       xmit_mmc((BYTE)(arg >> 16));    /* Argument[23..16] */\r
+       xmit_mmc((BYTE)(arg >> 8));             /* Argument[15..8] */\r
+       xmit_mmc((BYTE)arg);                    /* Argument[7..0] */\r
+       n = 0x01;                                               /* Dummy CRC + Stop */\r
+       if (cmd == CMD0) n = 0x95;              /* Valid CRC for CMD0(0) */\r
+       if (cmd == CMD8) n = 0x87;              /* Valid CRC for CMD8(0x1AA) */\r
+       xmit_mmc(n);\r
+\r
+       /* Receive a command response */\r
+       n = 10;                                                         /* Wait for a valid response in timeout of 10 attempts */\r
+       do {\r
+               res = rcvr_mmc();\r
+       } while ((res & 0x80) && --n);\r
+\r
+       return res;                     /* Return with the response value */\r
+}\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Public Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Initialize Disk Drive                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+DSTATUS disk_initialize (void)\r
+{\r
+       BYTE n, cmd, ty, buf[4];\r
+       UINT tmr;\r
+\r
+\r
+       INIT_PORT();\r
+\r
+       CS_H();\r
+       skip_mmc(10);                   /* Dummy clocks */\r
+\r
+       ty = 0;\r
+       if (send_cmd(CMD0, 0) == 1) {                   /* Enter Idle state */\r
+               if (send_cmd(CMD8, 0x1AA) == 1) {       /* SDv2 */\r
+                       for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();    /* Get trailing return value of R7 resp */\r
+                       if (buf[2] == 0x01 && buf[3] == 0xAA) {                 /* The card can work at vdd range of 2.7-3.6V */\r
+                               for (tmr = 1000; tmr; tmr--) {                          /* Wait for leaving idle state (ACMD41 with HCS bit) */\r
+                                       if (send_cmd(ACMD41, 1UL << 30) == 0) break;\r
+                                       DLY_US(1000);\r
+                               }\r
+                               if (tmr && send_cmd(CMD58, 0) == 0) {           /* Check CCS bit in the OCR */\r
+                                       for (n = 0; n < 4; n++) buf[n] = rcvr_mmc();\r
+                                       ty = (buf[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;      /* SDv2 (HC or SC) */\r
+                               }\r
+                       }\r
+               } else {                                                        /* SDv1 or MMCv3 */\r
+                       if (send_cmd(ACMD41, 0) <= 1)   {\r
+                               ty = CT_SD1; cmd = ACMD41;      /* SDv1 */\r
+                       } else {\r
+                               ty = CT_MMC; cmd = CMD1;        /* MMCv3 */\r
+                       }\r
+                       for (tmr = 1000; tmr; tmr--) {                  /* Wait for leaving idle state */\r
+                               if (send_cmd(ACMD41, 0) == 0) break;\r
+                               DLY_US(1000);\r
+                       }\r
+                       if (!tmr || send_cmd(CMD16, 512) != 0)                  /* Set R/W block length to 512 */\r
+                               ty = 0;\r
+               }\r
+       }\r
+       CardType = ty;\r
+       release_spi();\r
+\r
+       return ty ? 0 : STA_NOINIT;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read partial sector                                                   */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+DRESULT disk_readp (\r
+       BYTE *buff,             /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */\r
+       DWORD lba,              /* Sector number (LBA) */\r
+       WORD ofs,               /* Byte offset to read from (0..511) */\r
+       WORD cnt                /* Number of bytes to read (ofs + cnt mus be <= 512) */\r
+)\r
+{\r
+       DRESULT res;\r
+       BYTE d;\r
+       WORD bc, tmr;\r
+\r
+\r
+       if (!(CardType & CT_BLOCK)) lba *= 512;         /* Convert to byte address if needed */\r
+\r
+       res = RES_ERROR;\r
+       if (send_cmd(CMD17, lba) == 0) {                /* READ_SINGLE_BLOCK */\r
+\r
+               tmr = 1000;\r
+               do {                                                    /* Wait for data packet in timeout of 100ms */\r
+                       DLY_US(100);\r
+                       d = rcvr_mmc();\r
+               } while (d == 0xFF && --tmr);\r
+\r
+               if (d == 0xFE) {                                /* A data packet arrived */\r
+                       bc = 514 - ofs - cnt;\r
+\r
+                       /* Skip leading bytes */\r
+                       if (ofs) skip_mmc(ofs);\r
+\r
+                       /* Receive a part of the sector */\r
+                       if (buff) {     /* Store data to the memory */\r
+                               do\r
+                                       *buff++ = rcvr_mmc();\r
+                               while (--cnt);\r
+                       } else {        /* Forward data to the outgoing stream */\r
+                               do {\r
+                                       d = rcvr_mmc();\r
+                                       FORWARD(d);\r
+                               } while (--cnt);\r
+                       }\r
+\r
+                       /* Skip trailing bytes and CRC */\r
+                       skip_mmc(bc);\r
+\r
+                       res = RES_OK;\r
+               }\r
+       }\r
+\r
+       release_spi();\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Write partial sector                                                  */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_WRITE\r
+\r
+DRESULT disk_writep (\r
+       const BYTE *buff,       /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */\r
+       DWORD sa                        /* Number of bytes to send, Sector number (LBA) or zero */\r
+)\r
+{\r
+       DRESULT res;\r
+       WORD bc, tmr;\r
+       static WORD wc;\r
+\r
+\r
+       res = RES_ERROR;\r
+\r
+       if (buff) {             /* Send data bytes */\r
+               bc = (WORD)sa;\r
+               while (bc && wc) {              /* Send data bytes to the card */\r
+                       xmit_mmc(*buff++);\r
+                       wc--; bc--;\r
+               }\r
+               res = RES_OK;\r
+       } else {\r
+               if (sa) {       /* Initiate sector write process */\r
+                       if (!(CardType & CT_BLOCK)) sa *= 512;  /* Convert to byte address if needed */\r
+                       if (send_cmd(CMD24, sa) == 0) {                 /* WRITE_SINGLE_BLOCK */\r
+                               xmit_mmc(0xFF); xmit_mmc(0xFE);         /* Data block header */\r
+                               wc = 512;                                                       /* Set byte counter */\r
+                               res = RES_OK;\r
+                       }\r
+               } else {        /* Finalize sector write process */\r
+                       bc = wc + 2;\r
+                       while (bc--) xmit_mmc(0);       /* Fill left bytes and CRC with zeros */\r
+                       if ((rcvr_mmc() & 0x1F) == 0x05) {      /* Receive data resp and wait for end of write process in timeout of 300ms */\r
+                               for (tmr = 10000; rcvr_mmc() != 0xFF && tmr; tmr--)     /* Wait for ready (max 1000ms) */\r
+                                       DLY_US(100);\r
+                               if (tmr) res = RES_OK;\r
+                       }\r
+                       release_spi();\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+#endif\r
diff --git a/firm/sample/sample1/os/pff.c b/firm/sample/sample1/os/pff.c
new file mode 100644 (file)
index 0000000..802e8a3
--- /dev/null
@@ -0,0 +1,1114 @@
+/*----------------------------------------------------------------------------/\r
+/  Petit FatFs - FAT file system module  R0.02a                (C)ChaN, 2010\r
+/-----------------------------------------------------------------------------/\r
+/ Petit FatFs module is an open source software to implement FAT file system to\r
+/ small embedded systems. This is a free software and is opened for education,\r
+/ research and commercial developments under license policy of following trems.\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/-----------------------------------------------------------------------------/\r
+/ Jun 15,'09  R0.01a  First release. (Branched from FatFs R0.07b.)\r
+/\r
+/ Dec 14,'09  R0.02   Added multiple code page support.\r
+/                     Added write funciton.\r
+/                     Changed stream read mode interface.\r
+/ Dec 07,'10  R0.02a  Added some configuration options.\r
+/                     Fixed fails to open objects with DBCS character.\r
+/----------------------------------------------------------------------------*/\r
+\r
+#include "pff.h"               /* Petit FatFs configurations and declarations */\r
+#include "diskio.h"            /* Declarations of low level disk I/O functions */\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Module Private Definitions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+#if _FS_FAT32\r
+#define LD_CLUST(dir)  (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))\r
+#else\r
+#define LD_CLUST(dir)  LD_WORD(dir+DIR_FstClusLO)\r
+#endif\r
+\r
+\r
+/*--------------------------------------------------------*/\r
+/* DBCS code ranges and SBCS extend char conversion table */\r
+\r
+#if _CODE_PAGE == 932  /* Japanese Shift-JIS */\r
+#define _DF1S  0x81    /* DBC 1st byte range 1 start */\r
+#define _DF1E  0x9F    /* DBC 1st byte range 1 end */\r
+#define _DF2S  0xE0    /* DBC 1st byte range 2 start */\r
+#define _DF2E  0xFC    /* DBC 1st byte range 2 end */\r
+#define _DS1S  0x40    /* DBC 2nd byte range 1 start */\r
+#define _DS1E  0x7E    /* DBC 2nd byte range 1 end */\r
+#define _DS2S  0x80    /* DBC 2nd byte range 2 start */\r
+#define _DS2E  0xFC    /* DBC 2nd byte range 2 end */\r
+\r
+#elif _CODE_PAGE == 936        /* Simplified Chinese GBK */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x40\r
+#define _DS1E  0x7E\r
+#define _DS2S  0x80\r
+#define _DS2E  0xFE\r
+\r
+#elif _CODE_PAGE == 949        /* Korean */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x41\r
+#define _DS1E  0x5A\r
+#define _DS2S  0x61\r
+#define _DS2E  0x7A\r
+#define _DS3S  0x81\r
+#define _DS3E  0xFE\r
+\r
+#elif _CODE_PAGE == 950        /* Traditional Chinese Big5 */\r
+#define _DF1S  0x81\r
+#define _DF1E  0xFE\r
+#define _DS1S  0x40\r
+#define _DS1E  0x7E\r
+#define _DS2S  0xA1\r
+#define _DS2E  0xFE\r
+\r
+#elif _CODE_PAGE == 437        /* U.S. (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 720        /* Arabic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 737        /* Greek (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \\r
+                               0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 775        /* Baltic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 850        /* Multilingual Latin 1 (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 852        /* Latin 2 (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 855        /* Cyrillic (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \\r
+                               0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \\r
+                               0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 857        /* Turkish (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 858        /* Multilingual Latin 1 + Euro (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 862        /* Hebrew (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 866        /* Russian (OEM) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 874        /* Thai (OEM, Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \\r
+                               0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF}\r
+\r
+#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1253 /* Greek (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \\r
+                               0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF}\r
+\r
+#elif _CODE_PAGE == 1254 /* Turkish (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1256 /* Arabic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1257 /* Baltic (Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \\r
+                               0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF}\r
+\r
+#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */\r
+#define _DF1S  0\r
+#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \\r
+                               0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \\r
+                               0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F}\r
+\r
+#elif _CODE_PAGE == 1  /* ASCII (for only non-LFN cfg) */\r
+#define _DF1S  0\r
+\r
+#else\r
+#error Unknown code page\r
+\r
+#endif\r
+\r
+\r
+\r
+/* Character code support macros */\r
+\r
+#define IsUpper(c)     (((c)>='A')&&((c)<='Z'))\r
+#define IsLower(c)     (((c)>='a')&&((c)<='z'))\r
+\r
+#if _DF1S              /* DBCS configuration */\r
+\r
+#ifdef _DF2S   /* Two 1st byte areas */\r
+#define IsDBCS1(c)     (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))\r
+#else                  /* One 1st byte area */\r
+#define IsDBCS1(c)     ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)\r
+#endif\r
+\r
+#ifdef _DS3S   /* Three 2nd byte areas */\r
+#define IsDBCS2(c)     (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))\r
+#else                  /* Two 2nd byte areas */\r
+#define IsDBCS2(c)     (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))\r
+#endif\r
+\r
+#else                  /* SBCS configuration */\r
+\r
+#define IsDBCS1(c)     0\r
+#define IsDBCS2(c)     0\r
+\r
+#endif /* _DF1S */\r
+\r
+\r
+/* FatFs refers the members in the FAT structures with byte offset instead\r
+/ of structure member because there are incompatibility of the packing option\r
+/ between various compilers. */\r
+\r
+#define BS_jmpBoot                     0\r
+#define BS_OEMName                     3\r
+#define BPB_BytsPerSec         11\r
+#define BPB_SecPerClus         13\r
+#define BPB_RsvdSecCnt         14\r
+#define BPB_NumFATs                    16\r
+#define BPB_RootEntCnt         17\r
+#define BPB_TotSec16           19\r
+#define BPB_Media                      21\r
+#define BPB_FATSz16                    22\r
+#define BPB_SecPerTrk          24\r
+#define BPB_NumHeads           26\r
+#define BPB_HiddSec                    28\r
+#define BPB_TotSec32           32\r
+#define BS_55AA                                510\r
+\r
+#define BS_DrvNum                      36\r
+#define BS_BootSig                     38\r
+#define BS_VolID                       39\r
+#define BS_VolLab                      43\r
+#define BS_FilSysType          54\r
+\r
+#define BPB_FATSz32                    36\r
+#define BPB_ExtFlags           40\r
+#define BPB_FSVer                      42\r
+#define BPB_RootClus           44\r
+#define BPB_FSInfo                     48\r
+#define BPB_BkBootSec          50\r
+#define BS_DrvNum32                    64\r
+#define BS_BootSig32           66\r
+#define BS_VolID32                     67\r
+#define BS_VolLab32                    71\r
+#define BS_FilSysType32                82\r
+\r
+#define MBR_Table                      446\r
+\r
+#define        DIR_Name                        0\r
+#define        DIR_Attr                        11\r
+#define        DIR_NTres                       12\r
+#define        DIR_CrtTime                     14\r
+#define        DIR_CrtDate                     16\r
+#define        DIR_FstClusHI           20\r
+#define        DIR_WrtTime                     22\r
+#define        DIR_WrtDate                     24\r
+#define        DIR_FstClusLO           26\r
+#define        DIR_FileSize            28\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Private Functions\r
+\r
+---------------------------------------------------------------------------*/\r
+\r
+\r
+static\r
+FATFS *FatFs;  /* Pointer to the file system object (logical drive) */\r
+\r
+\r
+/* Fill memory */\r
+static\r
+void mem_set (void* dst, int val, int cnt) {\r
+       char *d = (char*)dst;\r
+       while (cnt--) *d++ = (char)val;\r
+}\r
+\r
+/* Compare memory to memory */\r
+static\r
+int mem_cmp (const void* dst, const void* src, int cnt) {\r
+       const char *d = (const char *)dst, *s = (const char *)src;\r
+       int r = 0;\r
+       while (cnt-- && (r = *d++ - *s++) == 0) ;\r
+       return r;\r
+}\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* FAT access - Read value of a FAT entry                                */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+CLUST get_fat (        /* 1:IO error, Else:Cluster status */\r
+       CLUST clst      /* Cluster# to get the link information */\r
+)\r
+{\r
+       WORD wc, bc, ofs;\r
+       BYTE buf[4];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (clst < 2 || clst >= fs->n_fatent)   /* Range check */\r
+               return 1;\r
+\r
+       switch (fs->fs_type) {\r
+#if _FS_FAT12\r
+       case FS_FAT12 :\r
+               bc = (WORD)clst; bc += bc / 2;\r
+               ofs = bc % 512; bc /= 512;\r
+               if (ofs != 511) {\r
+                       if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;\r
+               } else {\r
+                       if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;\r
+                       if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;\r
+               }\r
+               wc = LD_WORD(buf);\r
+               return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);\r
+#endif\r
+       case FS_FAT16 :\r
+               if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;\r
+               return LD_WORD(buf);\r
+#if _FS_FAT32\r
+       case FS_FAT32 :\r
+               if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;\r
+               return LD_DWORD(buf) & 0x0FFFFFFF;\r
+#endif\r
+       }\r
+\r
+       return 1;       /* An error occured at the disk I/O layer */\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Get sector# from cluster#                                             */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+DWORD clust2sect (     /* !=0: Sector number, 0: Failed - invalid cluster# */\r
+       CLUST clst              /* Cluster# to be converted */\r
+)\r
+{\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       clst -= 2;\r
+       if (clst >= (fs->n_fatent - 2)) return 0;               /* Invalid cluster# */\r
+       return (DWORD)clst * fs->csize + fs->database;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Rewind directory index                           */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_rewind (\r
+       DIR *dj                 /* Pointer to directory object */\r
+)\r
+{\r
+       CLUST clst;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       dj->index = 0;\r
+       clst = dj->sclust;\r
+       if (clst == 1 || clst >= fs->n_fatent)  /* Check start cluster range */\r
+               return FR_DISK_ERR;\r
+       if (_FS_FAT32 && !clst && fs->fs_type == FS_FAT32)      /* Replace cluster# 0 with root cluster# if in FAT32 */\r
+               clst = (CLUST)fs->dirbase;\r
+       dj->clust = clst;                                               /* Current cluster */\r
+       dj->sect = clst ? clust2sect(clst) : fs->dirbase;       /* Current sector */\r
+\r
+       return FR_OK;   /* Seek succeeded */\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Move directory index next                        */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_next (     /* FR_OK:Succeeded, FR_NO_FILE:End of table */\r
+       DIR *dj                 /* Pointer to directory object */\r
+)\r
+{\r
+       CLUST clst;\r
+       WORD i;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       i = dj->index + 1;\r
+       if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */\r
+               return FR_NO_FILE;\r
+\r
+       if (!(i % 16)) {                /* Sector changed? */\r
+               dj->sect++;                     /* Next sector */\r
+\r
+               if (dj->clust == 0) {   /* Static table */\r
+                       if (i >= fs->n_rootdir) /* Report EOT when end of table */\r
+                               return FR_NO_FILE;\r
+               }\r
+               else {                                  /* Dynamic table */\r
+                       if (((i / 16) & (fs->csize-1)) == 0) {  /* Cluster changed? */\r
+                               clst = get_fat(dj->clust);              /* Get next cluster */\r
+                               if (clst <= 1) return FR_DISK_ERR;\r
+                               if (clst >= fs->n_fatent)               /* When it reached end of dynamic table */\r
+                                       return FR_NO_FILE;                      /* Report EOT */\r
+                               dj->clust = clst;                               /* Initialize data for new cluster */\r
+                               dj->sect = clust2sect(clst);\r
+                       }\r
+               }\r
+       }\r
+\r
+       dj->index = i;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Directory handling - Find an object in the directory                  */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT dir_find (\r
+       DIR *dj,                /* Pointer to the directory object linked to the file name */\r
+       BYTE *dir               /* 32-byte working buffer */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE c;\r
+\r
+\r
+       res = dir_rewind(dj);                   /* Rewind directory object */\r
+       if (res != FR_OK) return res;\r
+\r
+       do {\r
+               res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
+                       ? FR_DISK_ERR : FR_OK;\r
+               if (res != FR_OK) break;\r
+               c = dir[DIR_Name];      /* First character */\r
+               if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
+               if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */\r
+                       break;\r
+               res = dir_next(dj);                                     /* Next entry */\r
+       } while (res == FR_OK);\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read an object from the directory                                     */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+static\r
+FRESULT dir_read (\r
+       DIR *dj,                /* Pointer to the directory object to store read object name */\r
+       BYTE *dir               /* 32-byte working buffer */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE a, c;\r
+\r
+\r
+       res = FR_NO_FILE;\r
+       while (dj->sect) {\r
+               res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
+                       ? FR_DISK_ERR : FR_OK;\r
+               if (res != FR_OK) break;\r
+               c = dir[DIR_Name];\r
+               if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
+               a = dir[DIR_Attr] & AM_MASK;\r
+               if (c != 0xE5 && c != '.' && !(a & AM_VOL))     /* Is it a valid entry? */\r
+                       break;\r
+               res = dir_next(dj);                     /* Next entry */\r
+               if (res != FR_OK) break;\r
+       }\r
+\r
+       if (res != FR_OK) dj->sect = 0;\r
+\r
+       return res;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Pick a segment and create the object name in directory form           */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+#ifdef _EXCVT\r
+       static const BYTE cvt[] = _EXCVT;\r
+#endif\r
+\r
+static\r
+FRESULT create_name (\r
+       DIR *dj,                        /* Pointer to the directory object */\r
+       const char **path       /* Pointer to pointer to the segment in the path string */\r
+)\r
+{\r
+       BYTE c, d, ni, si, i, *sfn;\r
+       const char *p;\r
+\r
+       /* Create file name in directory form */\r
+       sfn = dj->fn;\r
+       mem_set(sfn, ' ', 11);\r
+       si = i = 0; ni = 8;\r
+       p = *path;\r
+       for (;;) {\r
+               c = p[si++];\r
+               if (c <= ' ' || c == '/') break;        /* Break on end of segment */\r
+               if (c == '.' || i >= ni) {\r
+                       if (ni != 8 || c != '.') break;\r
+                       i = 8; ni = 11;\r
+                       continue;\r
+               }\r
+#ifdef _EXCVT\r
+               if (c >= 0x80)                                  /* To upper extended char (SBCS) */\r
+                       c = cvt[c - 0x80];\r
+#endif\r
+               if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */\r
+                       d = p[si++];                            /* Get 2nd byte */\r
+                       sfn[i++] = c;\r
+                       sfn[i++] = d;\r
+               } else {                                                /* Single byte code */\r
+                       if (IsLower(c)) c -= 0x20;      /* toupper */\r
+                       sfn[i++] = c;\r
+               }\r
+       }\r
+       *path = &p[si];                                         /* Rerurn pointer to the next segment */\r
+\r
+       sfn[11] = (c <= ' ') ? 1 : 0;           /* Set last segment flag if end of path */\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Get file information from directory entry                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+static\r
+void get_fileinfo (            /* No return code */\r
+       DIR *dj,                        /* Pointer to the directory object */\r
+       BYTE *dir,                      /* 32-byte working buffer */\r
+       FILINFO *fno            /* Pointer to store the file information */\r
+)\r
+{\r
+       BYTE i, c;\r
+       char *p;\r
+\r
+\r
+       p = fno->fname;\r
+       if (dj->sect) {\r
+               for (i = 0; i < 8; i++) {       /* Copy file name body */\r
+                       c = dir[i];\r
+                       if (c == ' ') break;\r
+                       if (c == 0x05) c = 0xE5;\r
+                       *p++ = c;\r
+               }\r
+               if (dir[8] != ' ') {            /* Copy file name extension */\r
+                       *p++ = '.';\r
+                       for (i = 8; i < 11; i++) {\r
+                               c = dir[i];\r
+                               if (c == ' ') break;\r
+                               *p++ = c;\r
+                       }\r
+               }\r
+               fno->fattrib = dir[DIR_Attr];                           /* Attribute */\r
+               fno->fsize = LD_DWORD(dir+DIR_FileSize);        /* Size */\r
+               fno->fdate = LD_WORD(dir+DIR_WrtDate);          /* Date */\r
+               fno->ftime = LD_WORD(dir+DIR_WrtTime);          /* Time */\r
+       }\r
+       *p = 0;\r
+}\r
+#endif /* _USE_DIR */\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Follow a file path                                                    */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+FRESULT follow_path (  /* FR_OK(0): successful, !=0: error code */\r
+       DIR *dj,                        /* Directory object to return last directory and found object */\r
+       BYTE *dir,                      /* 32-byte working buffer */\r
+       const char *path        /* Full-path string to find a file or directory */\r
+)\r
+{\r
+       FRESULT res;\r
+\r
+\r
+       while (*path == ' ') path++;            /* Skip leading spaces */\r
+       if (*path == '/') path++;                       /* Strip heading separator */\r
+       dj->sclust = 0;                                         /* Set start directory (always root dir) */\r
+\r
+       if ((BYTE)*path <= ' ') {                       /* Null path means the root directory */\r
+               res = dir_rewind(dj);\r
+               dir[0] = 0;\r
+\r
+       } else {                                                        /* Follow path */\r
+               for (;;) {\r
+                       res = create_name(dj, &path);   /* Get a segment */\r
+                       if (res != FR_OK) break;\r
+                       res = dir_find(dj, dir);                /* Find it */\r
+                       if (res != FR_OK) {                             /* Could not find the object */\r
+                               if (res == FR_NO_FILE && !*(dj->fn+11))\r
+                                       res = FR_NO_PATH;\r
+                               break;\r
+                       }\r
+                       if (*(dj->fn+11)) break;                /* Last segment match. Function completed. */\r
+                       if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */\r
+                               res = FR_NO_PATH; break;\r
+                       }\r
+                       dj->sclust = LD_CLUST(dir);\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Check a sector if it is an FAT boot record                            */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+static\r
+BYTE check_fs (        /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */\r
+       BYTE *buf,      /* Working buffer */\r
+       DWORD sect      /* Sector# (lba) to check if it is an FAT boot record or not */\r
+)\r
+{\r
+       if (disk_readp(buf, sect, 510, 2))              /* Read the boot sector */\r
+               return 3;\r
+       if (LD_WORD(buf) != 0xAA55)                             /* Check record signature */\r
+               return 2;\r
+\r
+       if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */\r
+               return 0;\r
+       if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)  /* Check FAT32 */\r
+               return 0;\r
+       return 1;\r
+}\r
+\r
+\r
+\r
+\r
+/*--------------------------------------------------------------------------\r
+\r
+   Public Functions\r
+\r
+--------------------------------------------------------------------------*/\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Mount/Unmount a Locical Drive                                         */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_mount (\r
+       FATFS *fs               /* Pointer to new file system object (NULL: Unmount) */\r
+)\r
+{\r
+       BYTE fmt, buf[36];\r
+       DWORD bsect, fsize, tsect, mclst;\r
+\r
+\r
+       FatFs = 0;\r
+       if (!fs) return FR_OK;                          /* Unregister fs object */\r
+\r
+       if (disk_initialize() & STA_NOINIT)     /* Check if the drive is ready or not */\r
+               return FR_NOT_READY;\r
+\r
+       /* Search FAT partition on the drive */\r
+       bsect = 0;\r
+       fmt = check_fs(buf, bsect);                     /* Check sector 0 as an SFD format */\r
+       if (fmt == 1) {                                         /* Not an FAT boot record, it may be FDISK format */\r
+               /* Check a partition listed in top of the partition table */\r
+               if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */\r
+                       fmt = 3;\r
+               } else {\r
+                       if (buf[4]) {                                   /* Is the partition existing? */\r
+                               bsect = LD_DWORD(&buf[8]);      /* Partition offset in LBA */\r
+                               fmt = check_fs(buf, bsect);     /* Check the partition */\r
+                       }\r
+               }\r
+       }\r
+       if (fmt == 3) return FR_DISK_ERR;\r
+       if (fmt) return FR_NO_FILESYSTEM;       /* No valid FAT patition is found */\r
+\r
+       /* Initialize the file system object */\r
+       if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;\r
+\r
+       fsize = LD_WORD(buf+BPB_FATSz16-13);                            /* Number of sectors per FAT */\r
+       if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);\r
+\r
+       fsize *= buf[BPB_NumFATs-13];                                           /* Number of sectors in FAT area */\r
+       fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */\r
+       fs->csize = buf[BPB_SecPerClus-13];                                     /* Number of sectors per cluster */\r
+       fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);         /* Nmuber of root directory entries */\r
+       tsect = LD_WORD(buf+BPB_TotSec16-13);                           /* Number of sectors on the file system */\r
+       if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);\r
+       mclst = (tsect                                          /* Last cluster# + 1 */\r
+               - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16\r
+               ) / fs->csize + 2;\r
+       fs->n_fatent = (CLUST)mclst;\r
+\r
+       fmt = FS_FAT16;                                                 /* Determine the FAT sub type */\r
+       if (mclst < 0xFF7)                                              /* Number of clusters < 0xFF5 */\r
+#if _FS_FAT12\r
+               fmt = FS_FAT12;\r
+#else\r
+               return FR_NO_FILESYSTEM;\r
+#endif\r
+       if (mclst >= 0xFFF7)                                    /* Number of clusters >= 0xFFF5 */\r
+#if _FS_FAT32\r
+               fmt = FS_FAT32;\r
+#else\r
+               return FR_NO_FILESYSTEM;\r
+#endif\r
+\r
+       fs->fs_type = fmt;              /* FAT sub-type */\r
+       if (_FS_FAT32 && fmt == FS_FAT32)\r
+               fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));  /* Root directory start cluster */\r
+       else\r
+               fs->dirbase = fs->fatbase + fsize;                              /* Root directory start sector (lba) */\r
+       fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;        /* Data start sector (lba) */\r
+\r
+       fs->flag = 0;\r
+       FatFs = fs;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Open or Create a File                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_open (\r
+       const char *path        /* Pointer to the file name */\r
+)\r
+{\r
+       FRESULT res;\r
+       DIR dj;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs)                                                /* Check file system */\r
+               return FR_NOT_ENABLED;\r
+\r
+       fs->flag = 0;\r
+       dj.fn = sp;\r
+       res = follow_path(&dj, dir, path);      /* Follow the file path */\r
+       if (res != FR_OK) return res;           /* Follow failed */\r
+       if (!dir[0] || (dir[DIR_Attr] & AM_DIR))        /* It is a directory */\r
+               return FR_NO_FILE;\r
+\r
+       fs->org_clust = LD_CLUST(dir);                  /* File start cluster */\r
+       fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */\r
+       fs->fptr = 0;                                           /* File pointer */\r
+       fs->flag = FA_OPENED;\r
+\r
+       return FR_OK;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read File                                                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_READ\r
+\r
+FRESULT pf_read (\r
+       void* buff,             /* Pointer to the read buffer (NULL:Forward data to the stream)*/\r
+       WORD btr,               /* Number of bytes to read */\r
+       WORD* br                /* Pointer to number of bytes read */\r
+)\r
+{\r
+       DRESULT dr;\r
+       CLUST clst;\r
+       DWORD sect, remain;\r
+       WORD rcnt;\r
+       BYTE cs, *rbuff = buff;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       *br = 0;\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+               return FR_NOT_OPENED;\r
+\r
+       remain = fs->fsize - fs->fptr;\r
+       if (btr > remain) btr = (WORD)remain;                   /* Truncate btr by remaining bytes */\r
+\r
+       while (btr)     {                                                                       /* Repeat until all data transferred */\r
+               if ((fs->fptr % 512) == 0) {                            /* On the sector boundary? */\r
+                       cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
+                       if (!cs) {                                                              /* On the cluster boundary? */\r
+                               clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
+                                       fs->org_clust : get_fat(fs->curr_clust);\r
+                               if (clst <= 1) goto fr_abort;\r
+                               fs->curr_clust = clst;                          /* Update current cluster */\r
+                       }\r
+                       sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
+                       if (!sect) goto fr_abort;\r
+                       fs->dsect = sect + cs;\r
+               }\r
+               rcnt = (WORD)(512 - (fs->fptr % 512));          /* Get partial sector data from sector buffer */\r
+               if (rcnt > btr) rcnt = btr;\r
+               dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);\r
+               if (dr) goto fr_abort;\r
+               fs->fptr += rcnt; rbuff += rcnt;                        /* Update pointers and counters */\r
+               btr -= rcnt; *br += rcnt;\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fr_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Write File                                                            */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_WRITE\r
+\r
+FRESULT pf_write (\r
+       const void* buff,       /* Pointer to the data to be written */\r
+       WORD btw,                       /* Number of bytes to write (0:Finalize the current write operation) */\r
+       WORD* bw                        /* Pointer to number of bytes written */\r
+)\r
+{\r
+       CLUST clst;\r
+       DWORD sect, remain;\r
+       const BYTE *p = buff;\r
+       BYTE cs;\r
+       WORD wcnt;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       *bw = 0;\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+               return FR_NOT_OPENED;\r
+\r
+       if (!btw) {             /* Finalize request */\r
+               if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;\r
+               fs->flag &= ~FA__WIP;\r
+               return FR_OK;\r
+       } else {                /* Write data request */\r
+               if (!(fs->flag & FA__WIP))              /* Round-down fptr to the sector boundary */\r
+                       fs->fptr &= 0xFFFFFE00;\r
+       }\r
+       remain = fs->fsize - fs->fptr;\r
+       if (btw > remain) btw = (WORD)remain;                   /* Truncate btw by remaining bytes */\r
+\r
+       while (btw)     {                                                                       /* Repeat until all data transferred */\r
+               if (((WORD)fs->fptr % 512) == 0) {                      /* On the sector boundary? */\r
+                       cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
+                       if (!cs) {                                                              /* On the cluster boundary? */\r
+                               clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
+                                       fs->org_clust : get_fat(fs->curr_clust);\r
+                               if (clst <= 1) goto fw_abort;\r
+                               fs->curr_clust = clst;                          /* Update current cluster */\r
+                       }\r
+                       sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
+                       if (!sect) goto fw_abort;\r
+                       fs->dsect = sect + cs;\r
+                       if (disk_writep(0, fs->dsect)) goto fw_abort;   /* Initiate a sector write operation */\r
+                       fs->flag |= FA__WIP;\r
+               }\r
+               wcnt = 512 - ((WORD)fs->fptr % 512);            /* Number of bytes to write to the sector */\r
+               if (wcnt > btw) wcnt = btw;\r
+               if (disk_writep(p, wcnt)) goto fw_abort;        /* Send data to the sector */\r
+               fs->fptr += wcnt; p += wcnt;                            /* Update pointers and counters */\r
+               btw -= wcnt; *bw += wcnt;\r
+               if (((WORD)fs->fptr % 512) == 0) {\r
+                       if (disk_writep(0, 0)) goto fw_abort;   /* Finalize the currtent secter write operation */\r
+                       fs->flag &= ~FA__WIP;\r
+               }\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fw_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Seek File R/W Pointer                                                 */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_LSEEK\r
+\r
+FRESULT pf_lseek (\r
+       DWORD ofs               /* File pointer from top of file */\r
+)\r
+{\r
+       CLUST clst;\r
+       DWORD bcs, sect, ifptr;\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
+       if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
+                       return FR_NOT_OPENED;\r
+\r
+       if (ofs > fs->fsize) ofs = fs->fsize;   /* Clip offset with the file size */\r
+       ifptr = fs->fptr;\r
+       fs->fptr = 0;\r
+       if (ofs > 0) {\r
+               bcs = (DWORD)fs->csize * 512;   /* Cluster size (byte) */\r
+               if (ifptr > 0 &&\r
+                       (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */\r
+                       fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */\r
+                       ofs -= fs->fptr;\r
+                       clst = fs->curr_clust;\r
+               } else {                                                        /* When seek to back cluster, */\r
+                       clst = fs->org_clust;                   /* start from the first cluster */\r
+                       fs->curr_clust = clst;\r
+               }\r
+               while (ofs > bcs) {                             /* Cluster following loop */\r
+                       clst = get_fat(clst);           /* Follow cluster chain */\r
+                       if (clst <= 1 || clst >= fs->n_fatent) goto fe_abort;\r
+                       fs->curr_clust = clst;\r
+                       fs->fptr += bcs;\r
+                       ofs -= bcs;\r
+               }\r
+               fs->fptr += ofs;\r
+               sect = clust2sect(clst);                /* Current sector */\r
+               if (!sect) goto fe_abort;\r
+               fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1));\r
+       }\r
+\r
+       return FR_OK;\r
+\r
+fe_abort:\r
+       fs->flag = 0;\r
+       return FR_DISK_ERR;\r
+}\r
+#endif\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Create a Directroy Object                                             */\r
+/*-----------------------------------------------------------------------*/\r
+#if _USE_DIR\r
+\r
+FRESULT pf_opendir (\r
+       DIR *dj,                        /* Pointer to directory object to create */\r
+       const char *path        /* Pointer to the directory path */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) {                              /* Check file system */\r
+               res = FR_NOT_ENABLED;\r
+       } else {\r
+               dj->fn = sp;\r
+               res = follow_path(dj, dir, path);               /* Follow the path to the directory */\r
+               if (res == FR_OK) {                                             /* Follow completed */\r
+                       if (dir[0]) {                                           /* It is not the root dir */\r
+                               if (dir[DIR_Attr] & AM_DIR)             /* The object is a directory */\r
+                                       dj->sclust = LD_CLUST(dir);\r
+                               else                                                    /* The object is not a directory */\r
+                                       res = FR_NO_PATH;\r
+                       }\r
+                       if (res == FR_OK)\r
+                               res = dir_rewind(dj);                   /* Rewind dir */\r
+               }\r
+               if (res == FR_NO_FILE) res = FR_NO_PATH;\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+\r
+\r
+\r
+/*-----------------------------------------------------------------------*/\r
+/* Read Directory Entry in Sequense                                      */\r
+/*-----------------------------------------------------------------------*/\r
+\r
+FRESULT pf_readdir (\r
+       DIR *dj,                        /* Pointer to the open directory object */\r
+       FILINFO *fno            /* Pointer to file information to return */\r
+)\r
+{\r
+       FRESULT res;\r
+       BYTE sp[12], dir[32];\r
+       FATFS *fs = FatFs;\r
+\r
+\r
+       if (!fs) {                              /* Check file system */\r
+               res = FR_NOT_ENABLED;\r
+       } else {\r
+               dj->fn = sp;\r
+               if (!fno) {\r
+                       res = dir_rewind(dj);\r
+               } else {\r
+                       res = dir_read(dj, dir);\r
+                       if (res == FR_NO_FILE) {\r
+                               dj->sect = 0;\r
+                               res = FR_OK;\r
+                       }\r
+                       if (res == FR_OK) {                             /* A valid entry is found */\r
+                               get_fileinfo(dj, dir, fno);     /* Get the object information */\r
+                               res = dir_next(dj);                     /* Increment index for next */\r
+                               if (res == FR_NO_FILE) {\r
+                                       dj->sect = 0;\r
+                                       res = FR_OK;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       return res;\r
+}\r
+\r
+#endif /* _USE_DIR */\r
+\r
diff --git a/firm/sample/sample1/os/pff.h b/firm/sample/sample1/os/pff.h
new file mode 100644 (file)
index 0000000..85be222
--- /dev/null
@@ -0,0 +1,188 @@
+/*---------------------------------------------------------------------------/\r
+/  Petit FatFs - FAT file system module include file  R0.02a   (C)ChaN, 2010\r
+/----------------------------------------------------------------------------/\r
+/ Petit FatFs module is an open source software to implement FAT file system to\r
+/ small embedded systems. This is a free software and is opened for education,\r
+/ research and commercial developments under license policy of following trems.\r
+/\r
+/  Copyright (C) 2010, ChaN, all right reserved.\r
+/\r
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.\r
+/ * No restriction on use. You can use, modify and redistribute it for\r
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.\r
+/ * Redistributions of source code must retain the above copyright notice.\r
+/\r
+/----------------------------------------------------------------------------*/\r
+\r
+#include "integer.h"\r
+\r
+/*---------------------------------------------------------------------------/\r
+/ Petit FatFs Configuration Options\r
+/\r
+/ CAUTION! Do not forget to make clean the project after any changes to\r
+/ the configuration options.\r
+/\r
+/----------------------------------------------------------------------------*/\r
+#ifndef _FATFS\r
+#define _FATFS\r
+\r
+#define        _USE_READ       1       /* 1:Enable pf_read() */\r
+\r
+#define        _USE_DIR        1       /* 1:Enable pf_opendir() and pf_readdir() */\r
+\r
+#define        _USE_LSEEK      1       /* 1:Enable pf_lseek() */\r
+\r
+#define        _USE_WRITE      1       /* 1:Enable pf_write() */\r
+\r
+#define _FS_FAT12      1       /* 1:Enable FAT12 support */\r
+#define _FS_FAT32      1       /* 1:Enable FAT32 support */\r
+\r
+\r
+#define        _CODE_PAGE      1\r
+/* Defines which code page is used for path name. Supported code pages are:\r
+/  932, 936, 949, 950, 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866,\r
+/  874, 1250, 1251, 1252, 1253, 1254, 1255, 1257, 1258 and 1 (ASCII only).\r
+/  SBCS code pages except for 1 requiers a case conversion table. This\r
+/  might occupy 128 bytes on the RAM on some platforms, e.g. avr-gcc. */\r
+\r
+\r
+#define _WORD_ACCESS   0\r
+/* The _WORD_ACCESS option defines which access method is used to the word\r
+/  data in the FAT structure.\r
+/\r
+/   0: Byte-by-byte access. Always compatible with all platforms.\r
+/   1: Word access. Do not choose this unless following condition is met.\r
+/\r
+/  When the byte order on the memory is big-endian or address miss-aligned\r
+/  word access results incorrect behavior, the _WORD_ACCESS must be set to 0.\r
+/  If it is not the case, the value can also be set to 1 to improve the\r
+/  performance and code efficiency. */\r
+\r
+\r
+/* End of configuration options. Do not change followings without care.     */\r
+/*--------------------------------------------------------------------------*/\r
+\r
+\r
+\r
+#if _FS_FAT32\r
+#define        CLUST   DWORD\r
+#else\r
+#define        CLUST   WORD\r
+#endif\r
+\r
+\r
+/* File system object structure */\r
+\r
+typedef struct {\r
+       BYTE    fs_type;        /* FAT sub type */\r
+       BYTE    flag;           /* File status flags */\r
+       BYTE    csize;          /* Number of sectors per cluster */\r
+       BYTE    pad1;\r
+       WORD    n_rootdir;      /* Number of root directory entries (0 on FAT32) */\r
+       CLUST   n_fatent;       /* Number of FAT entries (= number of clusters + 2) */\r
+       DWORD   fatbase;        /* FAT start sector */\r
+       DWORD   dirbase;        /* Root directory start sector (Cluster# on FAT32) */\r
+       DWORD   database;       /* Data start sector */\r
+       DWORD   fptr;           /* File R/W pointer */\r
+       DWORD   fsize;          /* File size */\r
+       CLUST   org_clust;      /* File start cluster */\r
+       CLUST   curr_clust;     /* File current cluster */\r
+       DWORD   dsect;          /* File current data sector */\r
+} FATFS;\r
+\r
+/* Directory object structure */\r
+\r
+typedef struct {\r
+       WORD    index;          /* Current read/write index number */\r
+       BYTE*   fn;                     /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */\r
+       CLUST   sclust;         /* Table start cluster (0:Static table) */\r
+       CLUST   clust;          /* Current cluster */\r
+       DWORD   sect;           /* Current sector */\r
+} DIR;\r
+\r
+/* File status structure */\r
+\r
+typedef struct {\r
+       DWORD   fsize;          /* File size */\r
+       WORD    fdate;          /* Last modified date */\r
+       WORD    ftime;          /* Last modified time */\r
+       BYTE    fattrib;        /* Attribute */\r
+       char    fname[13];      /* File name */\r
+} FILINFO;\r
+\r
+\r
+\r
+/* File function return code (FRESULT) */\r
+\r
+typedef enum {\r
+       FR_OK = 0,                      /* 0 */\r
+       FR_DISK_ERR,            /* 1 */\r
+       FR_NOT_READY,           /* 2 */\r
+       FR_NO_FILE,                     /* 3 */\r
+       FR_NO_PATH,                     /* 4 */\r
+       FR_NOT_OPENED,          /* 5 */\r
+       FR_NOT_ENABLED,         /* 6 */\r
+       FR_NO_FILESYSTEM        /* 7 */\r
+} FRESULT;\r
+\r
+\r
+\r
+/*--------------------------------------------------------------*/\r
+/* Petit FatFs module application interface                     */\r
+\r
+FRESULT pf_mount (FATFS*);                                             /* Mount/Unmount a logical drive */\r
+FRESULT pf_open (const char*);                                 /* Open a file */\r
+FRESULT pf_read (void*, WORD, WORD*);                  /* Read data from the open file */\r
+FRESULT pf_write (const void*, WORD, WORD*);   /* Write data to the open file */\r
+FRESULT pf_lseek (DWORD);                                              /* Move file pointer of the open file */\r
+FRESULT pf_opendir (DIR*, const char*);                        /* Open a directory */\r
+FRESULT pf_readdir (DIR*, FILINFO*);                   /* Read a directory item from the open directory */\r
+\r
+\r
+\r
+/*--------------------------------------------------------------*/\r
+/* Flags and offset address                                     */\r
+\r
+/* File status flag (FATFS.flag) */\r
+\r
+#define        FA_OPENED       0x01\r
+#define        FA_WPRT         0x02\r
+#define        FA__WIP         0x40\r
+\r
+\r
+/* FAT sub type (FATFS.fs_type) */\r
+\r
+#define FS_FAT12       1\r
+#define FS_FAT16       2\r
+#define FS_FAT32       3\r
+\r
+\r
+/* File attribute bits for directory entry */\r
+\r
+#define        AM_RDO  0x01    /* Read only */\r
+#define        AM_HID  0x02    /* Hidden */\r
+#define        AM_SYS  0x04    /* System */\r
+#define        AM_VOL  0x08    /* Volume label */\r
+#define AM_LFN 0x0F    /* LFN entry */\r
+#define AM_DIR 0x10    /* Directory */\r
+#define AM_ARC 0x20    /* Archive */\r
+#define AM_MASK        0x3F    /* Mask of defined bits */\r
+\r
+\r
+/*--------------------------------*/\r
+/* Multi-byte word access macros  */\r
+\r
+#if _WORD_ACCESS == 1  /* Enable word access to the FAT structure */\r
+#define        LD_WORD(ptr)            (WORD)(*(WORD*)(BYTE*)(ptr))\r
+#define        LD_DWORD(ptr)           (DWORD)(*(DWORD*)(BYTE*)(ptr))\r
+#define        ST_WORD(ptr,val)        *(WORD*)(BYTE*)(ptr)=(WORD)(val)\r
+#define        ST_DWORD(ptr,val)       *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)\r
+#else                                  /* Use byte-by-byte access to the FAT structure */\r
+#define        LD_WORD(ptr)            (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))\r
+#define        LD_DWORD(ptr)           (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))\r
+#define        ST_WORD(ptr,val)        *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)\r
+#define        ST_DWORD(ptr,val)       *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)\r
+#endif\r
+\r
+\r
+#endif /* _FATFS */\r
diff --git a/firm/sample/sample1/os/portconf.h b/firm/sample/sample1/os/portconf.h
new file mode 100644 (file)
index 0000000..c1b7d0e
--- /dev/null
@@ -0,0 +1,50 @@
+
+#ifndef PORTCONF_H
+#define PORTCONF_H
+
+/*
+ * Data Direction Register
+ */
+
+#define PORTCONF_P1DDR  ((volatile uint8 *)0xfee000)
+#define PORTCONF_P2DDR  ((volatile uint8 *)0xfee001)
+#define PORTCONF_P4DDR  ((volatile uint8 *)0xFEE003)
+#define PORTCONF_P8DDR  ((volatile uint8 *)0xfee007)
+#define PORTCONF_PADDR  ((volatile uint8 *)0xFEE009)
+#define PORTCONF_PBDDR  ((volatile uint8 *)0xfee00a)
+
+/*
+ * Port Data Register
+ */
+
+#define PORTCONF_P4DR   ((volatile uint8 *)0xFFFFD3)
+#define PORTCONF_P7DR   ((volatile uint8 *)0xFFFFD6)
+#define PORTCONF_PADR   ((volatile uint8 *)0xFFFFD9)
+#define PORTCONF_PBDR   ((volatile uint8 *)0xFFFFDA)
+
+/*
+ * Bit
+ */
+
+#define PORTCONF_PABIT_LEDG     (1 << 2)
+#define PORTCONF_PABIT_LEDR     (1 << 3)
+#define PORTCONF_PABIT_SWRE     (1 << 4)
+#define PORTCONF_PABIT_LED1     (1 << 6)
+#define PORTCONF_PABIT_LED2     (1 << 7)
+
+#define PORTCONF_PBBIT_SCLK     (1 << 5)
+#define PORTCONF_PBBIT_MOSI     (1 << 6)
+#define PORTCONF_PBBIT_MISO     (1 << 7)
+
+#define PORTCONF_P4BIT_SDCCS    (1 << 0)
+#define PORTCONF_P4BIT_VSCCS    (1 << 2)
+#define PORTCONF_P4BIT_VSDCS    (1 << 3)
+#define PORTCONF_P4BIT_VSDREQ   (1 << 4)
+#define PORTCONF_P4BIT_VSRST    (1 << 5)
+#define PORTCONF_P4BIT_LCD_RES  (1 << 7)
+
+#define PORTCONF_P7BIT_SW1      (1 << 0)
+#define PORTCONF_P7BIT_SW2      (1 << 1)
+
+#endif
+
diff --git a/firm/sample/sample1/os/re.c b/firm/sample/sample1/os/re.c
new file mode 100644 (file)
index 0000000..ea38be2
--- /dev/null
@@ -0,0 +1,16 @@
+#include "re.h"
+#include "spreg.h"
+
+int re_init(void)
+{
+  spreg_itu_init();
+  return 0;
+}
+
+uint16 re_read(void)
+{
+  uint16 value;
+  spreg_itu_counter(&value);
+  return value;
+}
+
diff --git a/firm/sample/sample1/os/re.h b/firm/sample/sample1/os/re.h
new file mode 100644 (file)
index 0000000..de5e3bf
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _RE_H_INCLUDED_
+#define _RE_H_INCLUDED_
+
+#include "defines.h"
+
+int re_init(void);
+uint16 re_read(void);
+
+#endif
+
diff --git a/firm/sample/sample1/os/serial.c b/firm/sample/sample1/os/serial.c
new file mode 100644 (file)
index 0000000..8ff4ea4
--- /dev/null
@@ -0,0 +1,154 @@
+#include "defines.h"
+#include "serial.h"
+
+#define SERIAL_SCI_NUM 3
+
+#define H8_3069F_SCI0 ((volatile struct h8_3069f_sci *)0xffffb0)
+#define H8_3069F_SCI1 ((volatile struct h8_3069f_sci *)0xffffb8)
+#define H8_3069F_SCI2 ((volatile struct h8_3069f_sci *)0xffffc0)
+
+struct h8_3069f_sci {
+  volatile uint8 smr;
+  volatile uint8 brr;
+  volatile uint8 scr;
+  volatile uint8 tdr;
+  volatile uint8 ssr;
+  volatile uint8 rdr;
+  volatile uint8 scmr;
+};
+
+#define H8_3069F_SCI_SMR_CKS_PER1  (0<<0)
+#define H8_3069F_SCI_SMR_CKS_PER4  (1<<0)
+#define H8_3069F_SCI_SMR_CKS_PER16 (2<<0)
+#define H8_3069F_SCI_SMR_CKS_PER64 (3<<0)
+#define H8_3069F_SCI_SMR_MP     (1<<2)
+#define H8_3069F_SCI_SMR_STOP   (1<<3)
+#define H8_3069F_SCI_SMR_OE     (1<<4)
+#define H8_3069F_SCI_SMR_PE     (1<<5)
+#define H8_3069F_SCI_SMR_CHR    (1<<6)
+#define H8_3069F_SCI_SMR_CA     (1<<7)
+
+#define H8_3069F_SCI_SCR_CKE0   (1<<0)
+#define H8_3069F_SCI_SCR_CKE1   (1<<1)
+#define H8_3069F_SCI_SCR_TEIE   (1<<2)
+#define H8_3069F_SCI_SCR_MPIE   (1<<3)
+#define H8_3069F_SCI_SCR_RE     (1<<4) /* ¼õ¿®Í­¸ú */
+#define H8_3069F_SCI_SCR_TE     (1<<5) /* Á÷¿®Í­¸ú */
+#define H8_3069F_SCI_SCR_RIE    (1<<6) /* ¼õ¿®³ä¹þ¤ßÍ­¸ú */
+#define H8_3069F_SCI_SCR_TIE    (1<<7) /* Á÷¿®³ä¹þ¤ßÍ­¸ú */
+
+#define H8_3069F_SCI_SSR_MPBT   (1<<0)
+#define H8_3069F_SCI_SSR_MPB    (1<<1)
+#define H8_3069F_SCI_SSR_TEND   (1<<2)
+#define H8_3069F_SCI_SSR_PER    (1<<3)
+#define H8_3069F_SCI_SSR_FERERS (1<<4)
+#define H8_3069F_SCI_SSR_ORER   (1<<5)
+#define H8_3069F_SCI_SSR_RDRF   (1<<6) /* ¼õ¿®´°Î» */
+#define H8_3069F_SCI_SSR_TDRE   (1<<7) /* Á÷¿®´°Î» */
+
+static struct {
+  volatile struct h8_3069f_sci *sci;
+} regs[SERIAL_SCI_NUM] = {
+  { H8_3069F_SCI0 }, 
+  { H8_3069F_SCI1 }, 
+  { H8_3069F_SCI2 }, 
+};
+
+/* ¥Ç¥Ð¥¤¥¹½é´ü²½ */
+int serial_init(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+
+  sci->scr = 0;
+  sci->smr = 0;
+  sci->brr = 64; /* 20MHz¤Î¥¯¥í¥Ã¥¯¤«¤é9600bps¤òÀ¸À®(25MHz¤Î¾ì¹ç¤Ï80¤Ë¤¹¤ë) */
+  sci->scr = H8_3069F_SCI_SCR_RE | H8_3069F_SCI_SCR_TE; /* Á÷¼õ¿®²Äǽ */
+  sci->ssr = 0;
+
+  return 0;
+}
+
+/* Á÷¿®²Äǽ¤«¡© */
+int serial_is_send_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  return (sci->ssr & H8_3069F_SCI_SSR_TDRE);
+}
+
+/* £±Ê¸»úÁ÷¿® */
+int serial_send_byte(int index, unsigned char c)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+
+  /* Á÷¿®²Äǽ¤Ë¤Ê¤ë¤Þ¤ÇÂԤĠ*/
+  while (!serial_is_send_enable(index))
+    ;
+  sci->tdr = c;
+  sci->ssr &= ~H8_3069F_SCI_SSR_TDRE; /* Á÷¿®³«»Ï */
+
+  return 0;
+}
+
+/* ¼õ¿®²Äǽ¤«¡© */
+int serial_is_recv_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  return (sci->ssr & H8_3069F_SCI_SSR_RDRF);
+}
+
+/* £±Ê¸»ú¼õ¿® */
+unsigned char serial_recv_byte(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  unsigned char c;
+
+  /* ¼õ¿®Ê¸»ú¤¬Íè¤ë¤Þ¤ÇÂԤĠ*/
+  while (!serial_is_recv_enable(index))
+    ;
+  c = sci->rdr;
+  sci->ssr &= ~H8_3069F_SCI_SSR_RDRF; /* ¼õ¿®´°Î» */
+
+  return c;
+}
+
+/* Á÷¿®³ä¹þ¤ßÍ­¸ú¤«¡© */
+int serial_intr_is_send_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  return (sci->scr & H8_3069F_SCI_SCR_TIE) ? 1 : 0;
+}
+
+/* Á÷¿®³ä¹þ¤ßÍ­¸ú²½ */
+void serial_intr_send_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  sci->scr |= H8_3069F_SCI_SCR_TIE;
+}
+
+/* Á÷¿®³ä¹þ¤ß̵¸ú²½ */
+void serial_intr_send_disable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  sci->scr &= ~H8_3069F_SCI_SCR_TIE;
+}
+
+/* ¼õ¿®³ä¹þ¤ßÍ­¸ú¤«¡© */
+int serial_intr_is_recv_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  return (sci->scr & H8_3069F_SCI_SCR_RIE) ? 1 : 0;
+}
+
+/* ¼õ¿®³ä¹þ¤ßÍ­¸ú²½ */
+void serial_intr_recv_enable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  sci->scr |= H8_3069F_SCI_SCR_RIE;
+}
+
+/* ¼õ¿®³ä¹þ¤ß̵¸ú²½ */
+void serial_intr_recv_disable(int index)
+{
+  volatile struct h8_3069f_sci *sci = regs[index].sci;
+  sci->scr &= ~H8_3069F_SCI_SCR_RIE;
+}
diff --git a/firm/sample/sample1/os/serial.h b/firm/sample/sample1/os/serial.h
new file mode 100644 (file)
index 0000000..bebf693
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _SERIAL_H_INCLUDED_
+#define _SERIAL_H_INCLUDED_
+
+int serial_init(int index);                       /* ¥Ç¥Ð¥¤¥¹½é´ü²½ */
+int serial_is_send_enable(int index);             /* Á÷¿®²Äǽ¤«¡© */
+int serial_send_byte(int index, unsigned char b); /* £±Ê¸»úÁ÷¿® */
+int serial_is_recv_enable(int index);             /* ¼õ¿®²Äǽ¤«¡© */
+unsigned char serial_recv_byte(int index);        /* £±Ê¸»ú¼õ¿® */
+int serial_intr_is_send_enable(int index);        /* Á÷¿®³ä¹þ¤ßÍ­¸ú¤«¡© */
+void serial_intr_send_enable(int index);          /* Á÷¿®³ä¹þ¤ßÍ­¸ú²½ */
+void serial_intr_send_disable(int index);         /* Á÷¿®³ä¹þ¤ß̵¸ú²½ */
+int serial_intr_is_recv_enable(int index);        /* ¼õ¿®³ä¹þ¤ßÍ­¸ú¤«¡© */
+void serial_intr_recv_enable(int index);          /* ¼õ¿®³ä¹þ¤ßÍ­¸ú²½ */
+void serial_intr_recv_disable(int index);         /* ¼õ¿®³ä¹þ¤ß̵¸ú²½ */
+
+#endif
diff --git a/firm/sample/sample1/os/sg12232c.c b/firm/sample/sample1/os/sg12232c.c
new file mode 100644 (file)
index 0000000..5b9aa83
--- /dev/null
@@ -0,0 +1,402 @@
+#include "sg12232c.h"
+#include "defines.h"
+
+static const uint8 FONT_X = 5;
+static const uint8 FONT_Y = 7;
+static const uint16 FONT_MIN_CODE = 0x20;
+static const uint16 FONT_MAX_CODE = 0x7F;
+
+#define swap(a,b) {int c=a;a=b;b=c;}
+#define abs(n) (((int)(n) < 0) ? ((int)(n) * (-1)) : (n))
+
+#define H8_3069F_P4DDR  ((volatile uint8 *)0xFEE003)
+#define H8_3069F_P4DR   ((volatile uint8 *)0xFFFFD3)
+#define H8_3069F_CSCR   ((volatile uint8 *)0xFEE01F)
+
+#define LCD_ADDR_LEFT   ((volatile uint8 *)0x800000)
+#define LCD_ADDR_RIGHT  ((volatile uint8 *)0xA00000)
+#define LCD_AOFS_CMD    (0)
+#define LCD_AOFS_DAT    (1 << 3)
+
+#define BIT_LCD_RES     (1 << 7)
+#define BIT_SDC_CS      (1 << 0)
+#define BIT_VSCCS       (1 << 2)
+#define BIT_VSDCS       (1 << 3)
+#define BIT_VSRST       (1 << 5)
+
+#define LCD1_CMD(VAL) \
+  do { \
+    *(LCD_ADDR_LEFT + LCD_AOFS_CMD) = (VAL); \
+  } while (0)
+
+#define LCD1_DAT_WRITE(VAL) \
+  do { \
+    *(LCD_ADDR_LEFT + LCD_AOFS_DAT) = (VAL); \
+  } while (0)
+
+#define LCD1_DAT_READ() (*(LCD_ADDR_LEFT + LCD_AOFS_DAT))
+
+#define LCD2_CMD(VAL) \
+  do { \
+    *(LCD_ADDR_RIGHT + LCD_AOFS_CMD) = (VAL); \
+  } while (0)
+
+#define LCD2_DAT_WRITE(VAL) \
+  do { \
+    *(LCD_ADDR_RIGHT + LCD_AOFS_DAT) = (VAL); \
+  } while (0)
+
+#define LCD2_DAT_READ() (*(LCD_ADDR_RIGHT + LCD_AOFS_DAT))
+
+static const uint8 font5x7_data[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, // (white space)
+  0x00, 0x00, 0x5F, 0x00, 0x00, // !
+  0x00, 0x07, 0x00, 0x07, 0x00, // "
+  0x14, 0x7F, 0x14, 0x7F, 0x14, // #
+  0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
+  0x23, 0x13, 0x08, 0x64, 0x62, // %
+  0x36, 0x49, 0x55, 0x22, 0x50, // &
+  0x00, 0x05, 0x03, 0x00, 0x00, // '
+  0x00, 0x1C, 0x22, 0x41, 0x00, // (
+  0x00, 0x41, 0x22, 0x1C, 0x00, // )
+  0x08, 0x2A, 0x1C, 0x2A, 0x08, // *
+  0x08, 0x08, 0x3E, 0x08, 0x08, // +
+  0x00, 0x50, 0x30, 0x00, 0x00, // ,
+  0x08, 0x08, 0x08, 0x08, 0x08, // -
+  0x00, 0x60, 0x60, 0x00, 0x00, // .
+  0x20, 0x10, 0x08, 0x04, 0x02, // /
+  0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
+  0x00, 0x42, 0x7F, 0x40, 0x00, // 1
+  0x42, 0x61, 0x51, 0x49, 0x46, // 2
+  0x21, 0x41, 0x45, 0x4B, 0x31, // 3
+  0x18, 0x14, 0x12, 0x7F, 0x10, // 4
+  0x27, 0x45, 0x45, 0x45, 0x39, // 5
+  0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
+  0x01, 0x71, 0x09, 0x05, 0x03, // 7
+  0x36, 0x49, 0x49, 0x49, 0x36, // 8
+  0x06, 0x49, 0x49, 0x29, 0x1E, // 9
+  0x00, 0x36, 0x36, 0x00, 0x00, // :
+  0x00, 0x56, 0x36, 0x00, 0x00, // ;
+  0x00, 0x08, 0x14, 0x22, 0x41, // <
+  0x14, 0x14, 0x14, 0x14, 0x14, // =
+  0x41, 0x22, 0x14, 0x08, 0x00, // >
+  0x02, 0x01, 0x51, 0x09, 0x06, // ?
+  0x32, 0x49, 0x79, 0x41, 0x3E, // @
+  0x7E, 0x11, 0x11, 0x11, 0x7E, // A
+  0x7F, 0x49, 0x49, 0x49, 0x36, // B
+  0x3E, 0x41, 0x41, 0x41, 0x22, // C
+  0x7F, 0x41, 0x41, 0x22, 0x1C, // D
+  0x7F, 0x49, 0x49, 0x49, 0x41, // E
+  0x7F, 0x09, 0x09, 0x01, 0x01, // F
+  0x3E, 0x41, 0x41, 0x51, 0x32, // G
+  0x7F, 0x08, 0x08, 0x08, 0x7F, // H
+  0x00, 0x41, 0x7F, 0x41, 0x00, // I
+  0x20, 0x40, 0x41, 0x3F, 0x01, // J
+  0x7F, 0x08, 0x14, 0x22, 0x41, // K
+  0x7F, 0x40, 0x40, 0x40, 0x40, // L
+  0x7F, 0x02, 0x04, 0x02, 0x7F, // M
+  0x7F, 0x04, 0x08, 0x10, 0x7F, // N
+  0x3E, 0x41, 0x41, 0x41, 0x3E, // O
+  0x7F, 0x09, 0x09, 0x09, 0x06, // P
+  0x3E, 0x41, 0x51, 0x21, 0x5E, // Q
+  0x7F, 0x09, 0x19, 0x29, 0x46, // R
+  0x46, 0x49, 0x49, 0x49, 0x31, // S
+  0x01, 0x01, 0x7F, 0x01, 0x01, // T
+  0x3F, 0x40, 0x40, 0x40, 0x3F, // U
+  0x1F, 0x20, 0x40, 0x20, 0x1F, // V
+  0x7F, 0x20, 0x18, 0x20, 0x7F, // W
+  0x63, 0x14, 0x08, 0x14, 0x63, // X
+  0x03, 0x04, 0x78, 0x04, 0x03, // Y
+  0x61, 0x51, 0x49, 0x45, 0x43, // Z
+  0x00, 0x00, 0x7F, 0x41, 0x41, // [
+  0x02, 0x04, 0x08, 0x10, 0x20, // /
+  0x41, 0x41, 0x7F, 0x00, 0x00, // ]
+  0x04, 0x02, 0x01, 0x02, 0x04, // ^
+  0x40, 0x40, 0x40, 0x40, 0x40, // _
+  0x00, 0x01, 0x02, 0x04, 0x00, // `
+  0x20, 0x54, 0x54, 0x54, 0x78, // a
+  0x7F, 0x48, 0x44, 0x44, 0x38, // b
+  0x38, 0x44, 0x44, 0x44, 0x20, // c
+  0x38, 0x44, 0x44, 0x48, 0x7F, // d
+  0x38, 0x54, 0x54, 0x54, 0x18, // e
+  0x08, 0x7E, 0x09, 0x01, 0x02, // f
+  0x08, 0x14, 0x54, 0x54, 0x3C, // g
+  0x7F, 0x08, 0x04, 0x04, 0x78, // h
+  0x00, 0x44, 0x7D, 0x40, 0x00, // i
+  0x20, 0x40, 0x44, 0x3D, 0x00, // j
+  0x00, 0x7F, 0x10, 0x28, 0x44, // k
+  0x00, 0x41, 0x7F, 0x40, 0x00, // l
+  0x7C, 0x04, 0x18, 0x04, 0x78, // m
+  0x7C, 0x08, 0x04, 0x04, 0x78, // n
+  0x38, 0x44, 0x44, 0x44, 0x38, // o
+  0x7C, 0x14, 0x14, 0x14, 0x08, // p
+  0x08, 0x14, 0x14, 0x18, 0x7C, // q
+  0x7C, 0x08, 0x04, 0x04, 0x08, // r
+  0x48, 0x54, 0x54, 0x54, 0x20, // s
+  0x04, 0x3F, 0x44, 0x40, 0x20, // t
+  0x3C, 0x40, 0x40, 0x20, 0x7C, // u
+  0x1C, 0x20, 0x40, 0x20, 0x1C, // v
+  0x3C, 0x40, 0x30, 0x40, 0x3C, // w
+  0x44, 0x28, 0x10, 0x28, 0x44, // x
+  0x0C, 0x50, 0x50, 0x50, 0x3C, // y
+  0x44, 0x64, 0x54, 0x4C, 0x44, // z
+  0x00, 0x08, 0x36, 0x41, 0x00, // {
+  0x00, 0x00, 0x7F, 0x00, 0x00, // |
+  0x00, 0x41, 0x36, 0x08, 0x00, // }
+  0x08, 0x08, 0x2A, 0x1C, 0x08, // ->
+  0x08, 0x1C, 0x2A, 0x08, 0x08  // <-
+};
+
+void sg12232c_init(void)
+{
+  *H8_3069F_P4DDR = BIT_LCD_RES | BIT_SDC_CS | BIT_VSCCS | BIT_VSDCS | BIT_VSRST;
+
+  /*
+   * L->H : 68K mode.
+   */
+  *H8_3069F_P4DR &= ~BIT_LCD_RES;
+  asm volatile ("nop");
+  asm volatile ("nop");
+  asm volatile ("nop");
+  asm volatile ("nop");
+  *H8_3069F_P4DR |= BIT_LCD_RES;
+
+  *H8_3069F_CSCR = 0x3F;
+
+  LCD1_CMD(0xE2);   // Reset
+  LCD1_CMD(0xA4);   // Static Drive Off
+  LCD1_CMD(0xC0);   // Display Start Line
+  LCD1_CMD(0xAF);   // Display On
+  LCD1_CMD(0xB8);   // Page Address Setup
+  LCD1_CMD(0x00);   // Column Address
+
+  LCD2_CMD(0xE2);   // Reset
+  LCD2_CMD(0xA4);   // Static Drive Off
+  LCD2_CMD(0xC0);   // Display Start Line
+  LCD2_CMD(0xAF);   // Display On
+  LCD2_CMD(0xB8);   // Page Address Setup
+  LCD2_CMD(0x00);   // Column Address
+}
+
+void sg12232c_clear(void)
+{
+  int p, c;
+
+  for (p = 0; p <= 3; p++) {
+    LCD1_CMD(0xB8 | (p & 0x03));  // Page Address Setup
+    LCD1_CMD(0x00 | (0 & 0x7F));  // Column Address
+    for (c = 0; c < 62; c++) {
+      LCD1_DAT_WRITE(0);
+    }
+
+    LCD2_CMD(0xB8 | (p & 0x03));  // Page Address Setup
+    LCD2_CMD(0x00 | (0 & 0x7F));  // Column Address
+    for (c = 0; c < 62; c++) {
+      LCD2_DAT_WRITE(0);
+    }
+  }
+}
+
+void sg12232c_set_pixel(int x, int y, int reverse)
+{
+  volatile uint8 dat;
+  int p, c;
+
+  if (x <= 60) {
+    p = y / 8;
+    c = x;
+    LCD1_CMD(0xB8 | (p & 0x03));  // Page Address Setup
+    LCD1_CMD(0x00 | (c & 0x7F));  // Column Address
+    LCD1_CMD(0xE0);
+    dat = LCD1_DAT_READ();    // Dummy Read
+    dat = LCD1_DAT_READ();    // Real Read
+    if (reverse) {
+      dat |= (1 << (y % 8));
+    } else {
+      dat &= ~(1 << (y % 8));
+    }
+    LCD1_DAT_WRITE(dat);
+    LCD1_CMD(0xEE);
+  } else {
+    p = y / 8;
+    c = x - 61;
+    LCD2_CMD(0xB8 | (p & 0x03));  // Page Address Setup
+    LCD2_CMD(0x00 | (c & 0x7F));  // Column Address
+    LCD2_CMD(0xE0);
+    dat = LCD2_DAT_READ();    // Dummy Read
+    dat = LCD2_DAT_READ();    // Real Read
+    if (reverse) {
+      dat |= (1 << (y % 8));
+    } else {
+      dat &= ~(1 << (y % 8));
+    }
+    LCD2_DAT_WRITE(dat);
+    LCD2_CMD(0xEE);
+  }
+}
+
+void sg12232c_draw_line(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
+{
+  int x;
+  /*
+   * Bresenham's line algorithm
+   */
+  uint8 steep = abs(y2 - y1) > abs(x2 - x1);
+  if (steep) {
+    swap(x1, y1);
+    swap(x2, y2);
+  }
+  if (x1 > x2) {
+    swap(x1, x2);
+    swap(y1, y2);
+  }
+  int deltax = x2 - x1;
+  int deltay = abs(y2 - y1);
+  int error = deltax / 2;
+  int ystep;
+  int y = y1;
+  if (y1 < y2) {
+    ystep = 1;
+  } else {
+    ystep = -1;
+  }
+  for (x = x1; x <= x2; x++) {
+    if (steep) {
+      if (reverse) {
+        sg12232c_set_pixel(y, x, 0);
+      } else {
+        sg12232c_set_pixel(y, x, 1);
+      }
+    } else {
+      if (reverse) {
+        sg12232c_set_pixel(x, y, 0);
+      } else {
+        sg12232c_set_pixel(x, y, 1);
+      }
+    }
+    error = error - deltay;
+    if (error < 0) {
+      y = y + ystep;
+      error = error + deltax;
+    }
+  }
+}
+
+void sg12232c_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
+{
+  int x, y;
+  for (x = x1; x <= x2; x++) {
+    if (reverse) {
+      sg12232c_set_pixel(x, y1, 0);
+      sg12232c_set_pixel(x, y2, 0);
+    } else {
+      sg12232c_set_pixel(x, y1, 1);
+      sg12232c_set_pixel(x, y2, 1);
+    }
+  }
+  for (y = y1; y <= y2; y++) {
+    if (reverse) {
+      sg12232c_set_pixel(x1, y, 0);
+      sg12232c_set_pixel(x2, y, 0);
+    } else {
+      sg12232c_set_pixel(x1, y, 1);
+      sg12232c_set_pixel(x2, y, 1);
+    }
+  }
+}
+
+void sg12232c_fill_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
+{
+  int x, y;
+  for (x = x1; x <= x2; x++) {
+    for (y = y1; y <= y2; y++) {
+      if (reverse) {
+        sg12232c_set_pixel(x, y, 0);
+      } else {
+        sg12232c_set_pixel(x, y, 1);
+      }
+    }
+  }
+}
+
+void sg12232c_draw_string(uint8 x, uint8 y, char *str, uint8 reverse)
+{
+  char *p = str;
+  int cnt = 0;
+  while (*p) {
+    sg12232c_draw_char(x + (FONT_X * cnt), y, *p, reverse);
+    p++;
+    cnt++;
+  }
+}
+
+void sg12232c_draw_char(uint8 x, uint8 y, char c, uint8 reverse)
+{
+  int i, j;
+  if ((FONT_MIN_CODE <= c) &&(c <= FONT_MAX_CODE)) {
+    int aofs = (c - FONT_MIN_CODE) * FONT_X;
+    for (i = 0; i < FONT_X; i++) {
+      uint8 pat = font5x7_data[aofs + i];
+      for (j = 0; j < FONT_Y; j++) {
+        if (pat & (1 << j)) {
+          if (reverse) {
+            sg12232c_set_pixel(x + i, y + j, 0);
+          } else {
+            sg12232c_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            sg12232c_set_pixel(x + i, y + j, 1);
+          } else {
+            sg12232c_set_pixel(x + i, y + j, 0);
+          }
+        }
+      }
+    }
+  } else {
+    for (i = 0; i < FONT_X; i++) {
+      uint8 pat = (i % 2) ? 0x55 : 0xAA;
+      for (j = 0; j < FONT_Y; j++) {
+        if (pat & (1 << j)) {
+          if (reverse) {
+            sg12232c_set_pixel(x + i, y + j, 0);
+          } else {
+            sg12232c_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            sg12232c_set_pixel(x + i, y + j, 1);
+          } else {
+            sg12232c_set_pixel(x + i, y + j, 0);
+          }
+        }
+      }
+    }
+  }
+}
+
+void sg12232c_draw_checkbox(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 state, uint8 reverse)
+{
+  sg12232c_draw_box(x1, y1, x2, y2, reverse);
+  if (state) {
+    sg12232c_draw_line(x1, y1, x2, y2, reverse);
+    sg12232c_draw_line(x1, y2, x2, y1, reverse);
+  }
+}
+
+void sg12232c_draw_progressbar(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse)
+{
+  sg12232c_draw_box(x1, y1, x2, y2, reverse);
+  if ((value < min) || (max < value)) {
+    return;
+  }
+  int tmp_max = max - min;
+  int tmp_val = value - min;
+  int pix = ((x2 - x1) * tmp_val) / tmp_max;
+  sg12232c_fill_box(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
+  sg12232c_fill_box(x1 + pix, y1 + 1, x2 - 1, y2 - 1, !reverse);
+}
+
diff --git a/firm/sample/sample1/os/sg12232c.h b/firm/sample/sample1/os/sg12232c.h
new file mode 100644 (file)
index 0000000..e419c69
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _LCD_H_INCLUDED_
+#define _LCD_H_INCLUDED_
+
+#include "defines.h"
+
+void sg12232c_init(void);
+void sg12232c_clear(void);
+void sg12232c_set_pixel(int x, int y, int reverse);
+void sg12232c_draw_line(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void sg12232c_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void sg12232c_fill_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void sg12232c_draw_string(uint8 x, uint8 y, char *str, uint8 reverse);
+void sg12232c_draw_char(uint8 x, uint8 y, char c, uint8 reverse);
+void sg12232c_draw_checkbox(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 state, uint8 reverse);
+void sg12232c_draw_progressbar(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse);
+
+#endif
+
diff --git a/firm/sample/sample1/os/spi.c b/firm/sample/sample1/os/spi.c
new file mode 100644 (file)
index 0000000..480299e
--- /dev/null
@@ -0,0 +1,90 @@
+
+#include "spi.h"
+#include "portconf.h"
+
+#define CK_H()  do { *PORTCONF_PBDR |=  PORTCONF_PBBIT_SCLK; } while (0)    /* Set MMC SCLK "high" */
+#define CK_L()  do { *PORTCONF_PBDR &= ~PORTCONF_PBBIT_SCLK; } while (0)    /* Set MMC SCLK "low" */
+#define DI_H()  do { *PORTCONF_PBDR |=  PORTCONF_PBBIT_MOSI; } while (0)    /* Set MMC DI "high" */
+#define DI_L()  do { *PORTCONF_PBDR &= ~PORTCONF_PBBIT_MOSI; } while (0)    /* Set MMC DI "low" */
+#define DO      ((*PORTCONF_PBDR & PORTCONF_PBBIT_MISO) ? 1 : 0)            /* Get MMC DO value (high:true, low:false) */
+
+#define VS1011E_CTRL_H()    do { *PORTCONF_P4DR |=  PORTCONF_P4BIT_VSCCS; } while (0)
+#define VS1011E_CTRL_L()    do { *PORTCONF_P4DR &= ~PORTCONF_P4BIT_VSCCS; } while (0)
+#define VS1011E_DATA_H()    do { *PORTCONF_P4DR |=  PORTCONF_P4BIT_VSDCS; } while (0)
+#define VS1011E_DATA_L()    do { *PORTCONF_P4DR &= ~PORTCONF_P4BIT_VSDCS; } while (0)
+#define SDCARD_H()          do { *PORTCONF_P4DR |=  PORTCONF_P4BIT_SDCCS; } while (0)   /* Set MMC CS "high" */
+#define SDCARD_L()          do { *PORTCONF_P4DR &= ~PORTCONF_P4BIT_SDCCS; } while (0)   /* Set MMC CS "low" */
+
+void spi_init(void)
+{
+}
+
+void spi_tx(uint8 d)
+{
+    if (d & 0x80) DI_H(); else DI_L(); /* bit7 */
+    CK_H(); CK_L();
+    if (d & 0x40) DI_H(); else DI_L(); /* bit6 */
+    CK_H(); CK_L();
+    if (d & 0x20) DI_H(); else DI_L(); /* bit5 */
+    CK_H(); CK_L();
+    if (d & 0x10) DI_H(); else DI_L(); /* bit4 */
+    CK_H(); CK_L();
+    if (d & 0x08) DI_H(); else DI_L(); /* bit3 */
+    CK_H(); CK_L();
+    if (d & 0x04) DI_H(); else DI_L(); /* bit2 */
+    CK_H(); CK_L();
+    if (d & 0x02) DI_H(); else DI_L(); /* bit1 */
+    CK_H(); CK_L();
+    if (d & 0x01) DI_H(); else DI_L(); /* bit0 */
+    CK_H(); CK_L();
+}
+
+uint8 spi_rx(void)
+{
+    uint8 r;
+
+    DI_H();    /* Send 0xFF */
+
+    r = 0;   if (DO) r++;      /* bit7 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit6 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit5 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit4 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit3 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit2 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit1 */
+    CK_H(); CK_L();
+    r <<= 1; if (DO) r++;      /* bit0 */
+    CK_H(); CK_L();
+
+    return r;
+}
+
+void spi_select(SpiTarget st)
+{
+    spi_deselect();
+    switch (st) {
+        case SpiTarget_VS1011E_CTRL:
+            VS1011E_CTRL_L();
+            break;
+        case SpiTarget_VS1011E_DATA:
+            VS1011E_DATA_L();
+            break;
+        case SpiTarget_SDCARD:
+            SDCARD_L();
+            break;
+    }
+}
+
+void spi_deselect(void)
+{
+    VS1011E_CTRL_H();
+    VS1011E_DATA_H();
+    SDCARD_H();
+}
+
diff --git a/firm/sample/sample1/os/spi.h b/firm/sample/sample1/os/spi.h
new file mode 100644 (file)
index 0000000..d5cd7bf
--- /dev/null
@@ -0,0 +1,20 @@
+
+#ifndef SPI_H
+#define SPI_H
+
+#include "defines.h"
+
+typedef enum {
+    SpiTarget_VS1011E_CTRL,
+    SpiTarget_VS1011E_DATA,
+    SpiTarget_SDCARD
+} SpiTarget;
+
+void spi_init(void);
+void spi_tx(uint8 d);
+uint8 spi_rx(void);
+void spi_select(SpiTarget st);
+void spi_deselect(void);
+
+#endif
+
diff --git a/firm/sample/sample1/os/spreg.c b/firm/sample/sample1/os/spreg.c
new file mode 100644 (file)
index 0000000..ca2fd5c
--- /dev/null
@@ -0,0 +1,82 @@
+
+#include "spreg.h"
+#include "defines.h"
+#include "portconf.h"
+
+/*
+ * DRAM
+ */
+#define SPREG_DRAM_ABWCR  ((volatile uint8 *)0xfee020)
+#define SPREG_DRAM_ASTCR  ((volatile uint8 *)0xfee021)
+#define SPREG_DRAM_RTCOR  ((volatile uint8 *)0xfee02a)
+#define SPREG_DRAM_RTMCSR ((volatile uint8 *)0xfee028)
+#define SPREG_DRAM_DRCRB  ((volatile uint8 *)0xfee027)
+#define SPREG_DRAM_DRCRA  ((volatile uint8 *)0xfee026)
+#define SPREG_DRAM_WCRH   ((volatile uint8 *)0xfee022)
+#define SPREG_DRAM_WCRL   ((volatile uint8 *)0xfee023)
+
+/*
+ * ITU
+ */
+#define SPREG_ITU_TMDR       ((volatile uint8 *)0xFFFF62)
+#define SPREG_ITU_TSTR       ((volatile uint8 *)0xFFFF60)
+#define SPREG_ITU_16TCNT2H   ((volatile uint8 *)0xFFFF7A)
+#define SPREG_ITU_16TCNT2L   ((volatile uint8 *)0xFFFF7B)
+
+#define SPREG_ITU_TSTR_BIT_STR2   (1 << 2)
+#define SPREG_ITU_TMDR_BIT_MDF    (1 << 6)
+
+/*
+ * Chip Select Control Register
+ */
+#define SPREG_CSCR       ((volatile uint8 *)0xFEE01F)
+
+void spreg_itu_init(void)
+{
+  *SPREG_ITU_TMDR = SPREG_ITU_TMDR_BIT_MDF;
+  *SPREG_ITU_TSTR = SPREG_ITU_TSTR_BIT_STR2;
+}
+
+void spreg_itu_counter(uint16 *value)
+{
+  *value = ((*SPREG_ITU_16TCNT2H) << 8) | (*SPREG_ITU_16TCNT2L << 0);
+}
+
+void spreg_dram_init(void)
+{
+  int i, j;
+
+  *SPREG_DRAM_ABWCR  = 0xff;
+  *SPREG_DRAM_RTCOR  = 0x03; /* リフレッシュ周期を短めに設定 */
+  *SPREG_DRAM_RTMCSR = 0x37;
+  *SPREG_DRAM_DRCRB  = 0x8f; /* ウエイト挿入 */
+  *SPREG_DRAM_DRCRA  = 0x20;
+
+  *PORTCONF_P1DDR  = 0xff;
+  *PORTCONF_P2DDR  = 0x07;
+  *PORTCONF_P8DDR  = 0xee;
+  *PORTCONF_PBDDR  = 0x6c;
+
+  for (i = 0; i < 200; i++) {
+    for (j = 0; j < 200; j++) {
+      asm volatile ("nop");
+    }
+  }
+
+  /*
+   * 3ステートアクセス
+   */
+  *SPREG_DRAM_WCRH = 0xff;
+  *SPREG_DRAM_WCRL = 0xff;
+
+  /*
+   * 3ステートアクセス
+   */
+  *SPREG_DRAM_ASTCR = 0xff;
+
+  /*
+   * チップセレクトコントロールレジスタもここで設定する。
+   */
+  *SPREG_CSCR = 0x3F;
+}
+
diff --git a/firm/sample/sample1/os/spreg.h b/firm/sample/sample1/os/spreg.h
new file mode 100644 (file)
index 0000000..eb127c5
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef SPREG_H
+#define SPREG_H
+
+#include "defines.h"
+
+void spreg_itu_init(void);
+void spreg_itu_counter(uint16 *value);
+void spreg_dram_init(void);
+
+#endif
+
diff --git a/firm/sample/sample1/os/startup.s b/firm/sample/sample1/os/startup.s
new file mode 100644 (file)
index 0000000..e6b0d36
--- /dev/null
@@ -0,0 +1,23 @@
+       .h8300h\r
+       .section .text\r
+       .global _start\r
+#      .type   _start,@function\r
+_start:\r
+       mov.l   #_bootstack,sp\r
+       jsr     @_main\r
+\r
+1:\r
+       bra     1b\r
+\r
+       .global _dispatch\r
+#      .type   _dispatch,@function\r
+_dispatch:\r
+       mov.l   @er0,er7\r
+       mov.l   @er7+,er0\r
+       mov.l   @er7+,er1\r
+       mov.l   @er7+,er2\r
+       mov.l   @er7+,er3\r
+       mov.l   @er7+,er4\r
+       mov.l   @er7+,er5\r
+       mov.l   @er7+,er6\r
+       rte\r
diff --git a/firm/sample/sample1/os/sw.c b/firm/sample/sample1/os/sw.c
new file mode 100644 (file)
index 0000000..ce69937
--- /dev/null
@@ -0,0 +1,26 @@
+
+#include "sw.h"
+#include "portconf.h"
+
+int sw_init(void)
+{
+  return 0;
+}
+
+uint8 sw_read(sw_target_t target)
+{
+  uint8 c = 0;
+  switch (target) {
+    case Sw1:
+      c = (*PORTCONF_P7DR & PORTCONF_P7BIT_SW1) ? 0 : 1;
+      break;
+    case Sw2:
+      c = (*PORTCONF_P7DR & PORTCONF_P7BIT_SW2) ? 0 : 1;
+      break;
+    case SwRe:
+      c = (*PORTCONF_PADR & PORTCONF_PABIT_SWRE) ? 0 : 1;
+      break;
+  }
+  return c;
+}
+
diff --git a/firm/sample/sample1/os/sw.h b/firm/sample/sample1/os/sw.h
new file mode 100644 (file)
index 0000000..65e1133
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _SW_H_INCLUDED_
+#define _SW_H_INCLUDED_
+
+#include "defines.h"
+
+typedef enum {
+    Sw1,
+    Sw2,
+    SwRe,
+} sw_target_t;
+
+int sw_init(void);
+uint8 sw_read(sw_target_t target);
+
+#endif
+
diff --git a/firm/sample/sample1/os/syscall.c b/firm/sample/sample1/os/syscall.c
new file mode 100644 (file)
index 0000000..744d715
--- /dev/null
@@ -0,0 +1,143 @@
+#include "defines.h"
+#include "kozos.h"
+#include "interrupt.h"
+#include "syscall.h"
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë */
+
+kz_thread_id_t kz_run(kz_func_t func, char *name, int priority, int stacksize,
+                     int argc, char *argv[])
+{
+  kz_syscall_param_t param;
+  param.un.run.func = func;
+  param.un.run.name = name;
+  param.un.run.priority = priority;
+  param.un.run.stacksize = stacksize;
+  param.un.run.argc = argc;
+  param.un.run.argv = argv;
+  kz_syscall(KZ_SYSCALL_TYPE_RUN, &param);
+  return param.un.run.ret;
+}
+
+void kz_exit(void)
+{
+  kz_syscall(KZ_SYSCALL_TYPE_EXIT, NULL);
+}
+
+int kz_wait(void)
+{
+  kz_syscall_param_t param;
+  kz_syscall(KZ_SYSCALL_TYPE_WAIT, &param);
+  return param.un.wait.ret;
+}
+
+int kz_sleep(void)
+{
+  kz_syscall_param_t param;
+  kz_syscall(KZ_SYSCALL_TYPE_SLEEP, &param);
+  return param.un.sleep.ret;
+}
+
+int kz_wakeup(kz_thread_id_t id)
+{
+  kz_syscall_param_t param;
+  param.un.wakeup.id = id;
+  kz_syscall(KZ_SYSCALL_TYPE_WAKEUP, &param);
+  return param.un.wakeup.ret;
+}
+
+kz_thread_id_t kz_getid(void)
+{
+  kz_syscall_param_t param;
+  kz_syscall(KZ_SYSCALL_TYPE_GETID, &param);
+  return param.un.getid.ret;
+}
+
+int kz_chpri(int priority)
+{
+  kz_syscall_param_t param;
+  param.un.chpri.priority = priority;
+  kz_syscall(KZ_SYSCALL_TYPE_CHPRI, &param);
+  return param.un.chpri.ret;
+}
+
+void *kz_kmalloc(int size)
+{
+  kz_syscall_param_t param;
+  param.un.kmalloc.size = size;
+  kz_syscall(KZ_SYSCALL_TYPE_KMALLOC, &param);
+  return param.un.kmalloc.ret;
+}
+
+int kz_kmfree(void *p)
+{
+  kz_syscall_param_t param;
+  param.un.kmfree.p = p;
+  kz_syscall(KZ_SYSCALL_TYPE_KMFREE, &param);
+  return param.un.kmfree.ret;
+}
+
+int kz_send(kz_msgbox_id_t id, int size, char *p)
+{
+  kz_syscall_param_t param;
+  param.un.send.id = id;
+  param.un.send.size = size;
+  param.un.send.p = p;
+  kz_syscall(KZ_SYSCALL_TYPE_SEND, &param);
+  return param.un.send.ret;
+}
+
+kz_thread_id_t kz_recv(kz_msgbox_id_t id, int *sizep, char **pp)
+{
+  kz_syscall_param_t param;
+  param.un.recv.id = id;
+  param.un.recv.sizep = sizep;
+  param.un.recv.pp = pp;
+  kz_syscall(KZ_SYSCALL_TYPE_RECV, &param);
+  return param.un.recv.ret;
+}
+
+int kz_setintr(softvec_type_t type, kz_handler_t handler)
+{
+  kz_syscall_param_t param;
+  param.un.setintr.type = type;
+  param.un.setintr.handler = handler;
+  kz_syscall(KZ_SYSCALL_TYPE_SETINTR, &param);
+  return param.un.setintr.ret;
+}
+
+/* ¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë */
+
+int kx_wakeup(kz_thread_id_t id)
+{
+  kz_syscall_param_t param;
+  param.un.wakeup.id = id;
+  kz_srvcall(KZ_SYSCALL_TYPE_WAKEUP, &param);
+  return param.un.wakeup.ret;
+}
+
+void *kx_kmalloc(int size)
+{
+  kz_syscall_param_t param;
+  param.un.kmalloc.size = size;
+  kz_srvcall(KZ_SYSCALL_TYPE_KMALLOC, &param);
+  return param.un.kmalloc.ret;
+}
+
+int kx_kmfree(void *p)
+{
+  kz_syscall_param_t param;
+  param.un.kmfree.p = p;
+  kz_srvcall(KZ_SYSCALL_TYPE_KMFREE, &param);
+  return param.un.kmfree.ret;
+}
+
+int kx_send(kz_msgbox_id_t id, int size, char *p)
+{
+  kz_syscall_param_t param;
+  param.un.send.id = id;
+  param.un.send.size = size;
+  param.un.send.p = p;
+  kz_srvcall(KZ_SYSCALL_TYPE_SEND, &param);
+  return param.un.send.ret;
+}
diff --git a/firm/sample/sample1/os/syscall.h b/firm/sample/sample1/os/syscall.h
new file mode 100644 (file)
index 0000000..65e0061
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef _KOZOS_SYSCALL_H_INCLUDED_
+#define _KOZOS_SYSCALL_H_INCLUDED_
+
+#include "defines.h"
+#include "interrupt.h"
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ëÈÖ¹æ¤ÎÄêµÁ */
+typedef enum {
+  KZ_SYSCALL_TYPE_RUN = 0,
+  KZ_SYSCALL_TYPE_EXIT,
+  KZ_SYSCALL_TYPE_WAIT,
+  KZ_SYSCALL_TYPE_SLEEP,
+  KZ_SYSCALL_TYPE_WAKEUP,
+  KZ_SYSCALL_TYPE_GETID,
+  KZ_SYSCALL_TYPE_CHPRI,
+  KZ_SYSCALL_TYPE_KMALLOC,
+  KZ_SYSCALL_TYPE_KMFREE,
+  KZ_SYSCALL_TYPE_SEND,
+  KZ_SYSCALL_TYPE_RECV,
+  KZ_SYSCALL_TYPE_SETINTR,
+} kz_syscall_type_t;
+
+/* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¸Æ¤Ó½Ð¤·»þ¤Î¥Ñ¥é¥á¡¼¥¿³ÊǼ°è¤ÎÄêµÁ */
+typedef struct {
+  union {
+    struct {
+      kz_func_t func;
+      char *name;
+      int priority;
+      int stacksize;
+      int argc;
+      char **argv;
+      kz_thread_id_t ret;
+    } run;
+    struct {
+      int dummy;
+    } exit;
+    struct {
+      int ret;
+    } wait;
+    struct {
+      int ret;
+    } sleep;
+    struct {
+      kz_thread_id_t id;
+      int ret;
+    } wakeup;
+    struct {
+      kz_thread_id_t ret;
+    } getid;
+    struct {
+      int priority;
+      int ret;
+    } chpri;
+    struct {
+      int size;
+      void *ret;
+    } kmalloc;
+    struct {
+      char *p;
+      int ret;
+    } kmfree;
+    struct {
+      kz_msgbox_id_t id;
+      int size;
+      char *p;
+      int ret;
+    } send;
+    struct {
+      kz_msgbox_id_t id;
+      int *sizep;
+      char **pp;
+      kz_thread_id_t ret;
+    } recv;
+    struct {
+      softvec_type_t type;
+      kz_handler_t handler;
+      int ret;
+    } setintr;
+  } un;
+} kz_syscall_param_t;
+
+#endif
diff --git a/firm/sample/sample1/os/task.h b/firm/sample/sample1/os/task.h
new file mode 100644 (file)
index 0000000..b2568b6
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef TASK_H
+#define TASK_H
+
+#include "task_userinput.h"
+#include "task_ir.h"
+#include "task_command.h"
+
+#endif
diff --git a/firm/sample/sample1/os/task_command.c b/firm/sample/sample1/os/task_command.c
new file mode 100644 (file)
index 0000000..b07d4be
--- /dev/null
@@ -0,0 +1,44 @@
+#include "defines.h"
+#include "kozos.h"
+#include "driver_console.h"
+#include "driver_led.h"
+#include "lib.h"
+
+int task_command(int argc, char *argv[])
+{
+  char *p;
+  int size;
+
+  console_use(SERIAL_DEFAULT_DEVICE);
+
+  while (1) {
+    console_write("command> "); /* ¥×¥í¥ó¥×¥Èɽ¼¨ */
+
+    /* ¥³¥ó¥½¡¼¥ë¤«¤é¤Î¼õ¿®Ê¸»úÎó¤ò¼õ¤±¼è¤ë */
+    kz_recv(MSGBOX_ID_CONSINPUT, &size, &p);
+    if (p == NULL) {
+      console_write("expired.\n");
+      continue;
+    }
+    p[size] = '\0';
+
+    if (!strncmp(p, "echo", 4)) { /* echo¥³¥Þ¥ó¥É */
+      console_write(p + 4); /* echo¤Ë³¤¯Ê¸»úÎó¤ò½ÐÎϤ¹¤ë */
+      console_write("\n");
+    } else if (!strncmp(p, "led1", 4)) {
+      leddrv_toggle(0);
+    } else if (!strncmp(p, "led2", 4)) {
+      leddrv_toggle(1);
+    } else if (!strncmp(p, "ledg", 4)) {
+      leddrv_toggle(2);
+    } else if (!strncmp(p, "ledr", 4)) {
+      leddrv_toggle(3);
+    } else {
+      console_write("unknown.\n");
+    }
+
+    kz_kmfree(p);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/task_command.h b/firm/sample/sample1/os/task_command.h
new file mode 100644 (file)
index 0000000..4c580bd
--- /dev/null
@@ -0,0 +1,5 @@
+
+#ifndef _TASK_COMMAND_H_
+#define _TASK_COMMAND_H_
+int task_command(int argc, char *argv[]);
+#endif
diff --git a/firm/sample/sample1/os/task_ir.c b/firm/sample/sample1/os/task_ir.c
new file mode 100644 (file)
index 0000000..6d5f993
--- /dev/null
@@ -0,0 +1,117 @@
+#include "task_ir.h"
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "led.h"
+#include "lib.h"
+#include "driver_console.h"
+#include "driver_audio.h"
+#include "driver_led.h"
+
+#define H8_3069F_ISCR       ((volatile uint8 *)0xFEE014)
+#define H8_3069F_IER        ((volatile uint8 *)0xFEE015)
+#define H8_3069F_ISR        ((volatile uint8 *)0xFEE016)
+
+#define H8_3069F_TSTR       ((volatile uint8 *)0xFFFF60)
+#define H8_3069F_TISRC      ((volatile uint8 *)0xFFFF66)
+#define H8_3069F_16TCR0     ((volatile uint8 *)0xFFFF68)
+#define H8_3069F_TIOR0      ((volatile uint8 *)0xFFFF69)
+#define H8_3069F_16TCNT0H   ((volatile uint8 *)0xFFFF6A)
+#define H8_3069F_16TCNT0L   ((volatile uint8 *)0xFFFF6B)
+
+#define MAX_BIT_COUNT (64)
+
+typedef enum {
+  WaitLeader,
+  FoundLeader,
+  Receiving,
+  Received
+} ir_state_t;
+
+static uint16 bitcnt = 0;
+static uint16 tmrovf = 0;
+static uint8 data[MAX_BIT_COUNT / 8];
+static ir_state_t irs = WaitLeader;
+
+static void remocon_intr_edge(void)
+{
+  switch (irs) {
+    case WaitLeader:
+      *H8_3069F_TSTR |= (1 << 0);
+      bitcnt = 0;
+      tmrovf = 0;
+      irs = FoundLeader;
+      break;
+    case FoundLeader:
+      irs = Receiving;
+      break;
+    case Receiving:
+      if (bitcnt < MAX_BIT_COUNT) {
+        if ((bitcnt % 8) == 0) {
+          data[bitcnt / 8] = 0;
+        }
+        uint16 tmrval =
+          ((*H8_3069F_16TCNT0H) << 8) |
+          ((*H8_3069F_16TCNT0L) << 0);
+        if (tmrval > 0x1077) {
+          data[bitcnt / 8] |= (1 << (bitcnt % 8));
+        }
+        bitcnt++;
+      }
+      if (32 <= bitcnt) {
+        irs = Received;
+      }
+      break;
+    case Received:
+      *H8_3069F_TSTR &= ~(1 << 0);
+      break;
+    default:
+      break;
+  }
+  *H8_3069F_16TCNT0H = 0;
+  *H8_3069F_16TCNT0L = 0;
+}
+
+static void remocon_intr_tovf(void)
+{
+  *H8_3069F_TISRC &= ~(1 << 0);
+  tmrovf = 1;
+  *H8_3069F_TSTR &= ~(1 << 0);
+}
+
+int task_ir(int argc, char *argv[])
+{
+  kz_setintr(SOFTVEC_TYPE_IR_EDGE, remocon_intr_edge);
+  kz_setintr(SOFTVEC_TYPE_IR_TOVF, remocon_intr_tovf);
+  *H8_3069F_ISCR |= (1 << 4);
+  *H8_3069F_IER |= (1 << 4);
+
+  *H8_3069F_TISRC |= (1 << 4);
+  *H8_3069F_16TCR0 = 0x03;
+
+  while (1) {
+    if (tmrovf) {
+      if (bitcnt == 32) {
+#if 0
+        int i;
+        for (i = 0; i < bitcnt; i++) {
+          if (data[i / 8] & (1 << (i % 8))) {
+            console_write("1");
+          } else {
+            console_write("0");
+          }
+        }
+        console_write("\n");
+#endif
+        audio_pulse();
+        leddrv_toggle(2);
+      }
+      bitcnt = 0;
+      tmrovf = 0;
+      irs = WaitLeader;
+    }
+  }
+
+  return 0;
+}
+
diff --git a/firm/sample/sample1/os/task_ir.h b/firm/sample/sample1/os/task_ir.h
new file mode 100644 (file)
index 0000000..f6d53b9
--- /dev/null
@@ -0,0 +1,5 @@
+
+#ifndef _TASK_IR_H_
+#define _TASK_IR_H_
+int task_ir(int argc, char *argv[]);
+#endif
diff --git a/firm/sample/sample1/os/task_userinput.c b/firm/sample/sample1/os/task_userinput.c
new file mode 100644 (file)
index 0000000..703a1e5
--- /dev/null
@@ -0,0 +1,57 @@
+#include "defines.h"
+#include "kozos.h"
+#include "driver_timer.h"
+#include "driver_led.h"
+#include "driver_lcd.h"
+#include "lib.h"
+#include "sw.h"
+#include "re.h"
+
+int task_userinput(int argc, char *argv[])
+{
+  int nx = 40, ny = 12;
+  re_init();
+  sw_init();
+
+  lcddrv_clear();
+  lcddrv_draw_logo(  0, 0, 2);
+  lcddrv_draw_box(0, 0, 121, 31, 1);
+  lcddrv_draw_text(40, 4, "KOZOS EXPBRD #00");
+
+  lcddrv_draw_logo(nx, ny, 0);
+
+  uint16 prev = 0, curr = 0;
+  while (1) {
+    curr = re_read();
+    if (curr != prev) {
+      int dir = (int)(curr & 0xff) - (int)(prev & 0xff);
+      if (dir < 0) {
+        if (-32 < dir) {
+          leddrv_write(1, 0);
+          leddrv_toggle(0);
+        }
+        if (40 < nx) {
+          nx--;
+        }
+      } else {
+        if (dir < 32) {
+          leddrv_write(0, 0);
+          leddrv_toggle(1);
+        }
+        if (nx < 100) {
+          nx++;
+        }
+      }
+      prev = curr;
+
+      lcddrv_draw_box(nx + 20, ny, nx + 20, ny + 16, 0);
+      lcddrv_draw_logo(nx, ny, 0);
+    }
+
+    timerdrv_start(5);
+    timerdrv_wait();
+    leddrv_toggle(3);
+  }
+
+  return 0;
+}
diff --git a/firm/sample/sample1/os/task_userinput.h b/firm/sample/sample1/os/task_userinput.h
new file mode 100644 (file)
index 0000000..db06351
--- /dev/null
@@ -0,0 +1,5 @@
+
+#ifndef _TASK_USERINPUT_H_
+#define _TASK_USERINPUT_H_
+int task_userinput(int argc, char *argv[]);
+#endif
diff --git a/firm/sample/sample1/os/timer.c b/firm/sample/sample1/os/timer.c
new file mode 100644 (file)
index 0000000..9af5ba0
--- /dev/null
@@ -0,0 +1,136 @@
+#include "defines.h"
+#include "timer.h"
+
+#define TIMER_TMR_NUM 2
+
+#define H8_3069F_TMR01 ((volatile struct h8_3069f_tmr *)0xffff80)
+#define H8_3069F_TMR23 ((volatile struct h8_3069f_tmr *)0xffff90)
+
+struct h8_3069f_tmr {
+  volatile uint8 tcr0;
+  volatile uint8 tcr1;
+  volatile uint8 tcsr0;
+  volatile uint8 tcsr1;
+  volatile uint8 tcora0;
+  volatile uint8 tcora1;
+  volatile uint8 tcorb0;
+  volatile uint8 tcorb1;
+  volatile uint16 tcnt;
+};
+
+#define H8_3069F_TMR_TCR_DISCLK       (0<<0)
+#define H8_3069F_TMR_TCR_CLK8         (1<<0)
+#define H8_3069F_TMR_TCR_CLK64        (2<<0)
+#define H8_3069F_TMR_TCR_CLK8192      (3<<0)
+#define H8_3069F_TMR_TCR_OVF          (4<<0)
+#define H8_3069F_TMR_TCR_CMFA         (4<<0)
+#define H8_3069F_TMR_TCR_CLKUP        (5<<0)
+#define H8_3069F_TMR_TCR_CLKDOWN      (6<<0)
+#define H8_3069F_TMR_TCR_CLKBOTH      (7<<0)
+
+#define H8_3069F_TMR_TCR_CCLR_DISCLR  (0<<3)
+#define H8_3069F_TMR_TCR_CCLR_CLRCMFA (1<<3)
+#define H8_3069F_TMR_TCR_CCLR_CLRCMFB (2<<3)
+#define H8_3069F_TMR_TCR_CCLR_DISINPB (3<<3)
+
+#define H8_3069F_TMR_TCR_OVIE         (1<<5)
+#define H8_3069F_TMR_TCR_CMIEA        (1<<6)
+#define H8_3069F_TMR_TCR_CMIEB        (1<<7)
+
+#define H8_3069F_TMR_TCSR_OS_NOACT    (0<<0)
+#define H8_3069F_TMR_TCSR_OIS_NOACT   (0<<2)
+#define H8_3069F_TMR_TCSR_ADTE        (1<<4)
+#define H8_3069F_TMR_TCSR_ICE         (1<<4)
+#define H8_3069F_TMR_TCSR_OVF         (1<<5)
+#define H8_3069F_TMR_TCSR_CMFA        (1<<6)
+#define H8_3069F_TMR_TCSR_CMFB        (1<<7)
+
+static struct {
+  volatile struct h8_3069f_tmr *tmr;
+} regs[TIMER_TMR_NUM] = {
+  { H8_3069F_TMR01 }, 
+  { H8_3069F_TMR23 }, 
+};
+
+/* ¥¿¥¤¥Þ³«»Ï */
+int timer_start(int index, int msec, int flags)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+  int count;
+  uint8 tcr;
+
+  tcr = H8_3069F_TMR_TCR_OVF;
+  if (flags & TIMER_START_FLAG_CYCLE)
+    tcr |= H8_3069F_TMR_TCR_CCLR_CLRCMFA;
+  else
+    tcr |= H8_3069F_TMR_TCR_CCLR_DISCLR;
+  tmr->tcr0 = tcr;
+  tmr->tcr1 = H8_3069F_TMR_TCR_CLK8192 | H8_3069F_TMR_TCR_CCLR_DISCLR;
+
+  tmr->tcsr0 = 0;
+  tmr->tcsr1 = 0;
+
+  count = msec / 105; /* 20MHz: (msec * 20000000 / 8192 / 256 / 1000) */
+
+  tmr->tcnt = 0;
+  tmr->tcora0 = count;
+  tmr->tcr0 |= H8_3069F_TMR_TCR_CMIEA; /* ³ä¹þ¤ßÍ­¸ú²½ */
+
+  return 0;
+}
+
+/* ¥¿¥¤¥ÞËþλ¤·¤¿¤«¡© */
+int timer_is_expired(int index)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+  return (tmr->tcsr0 & H8_3069F_TMR_TCSR_CMFA) ? 1 : 0;
+}
+
+/* ¥¿¥¤¥ÞËþλ½èÍý */
+int timer_expire(int index)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+
+  tmr->tcsr0 &= ~H8_3069F_TMR_TCSR_CMFA;
+
+  return 0;
+}
+
+/* ¥¿¥¤¥Þ¥­¥ã¥ó¥»¥ë */
+int timer_cancel(int index)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+
+  timer_expire(index);
+
+  tmr->tcr0 = 0;
+  tmr->tcr1 = 0;
+
+  tmr->tcr0 &= ~H8_3069F_TMR_TCR_CMIEA; /* ³ä¹þ¤ß̵¸ú²½ */
+
+  return 0;
+}
+
+/* ¥¿¥¤¥ÞÆ°ºîÃ椫¡© */
+int timer_is_running(int index)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+  return (tmr->tcr0 & H8_3069F_TMR_TCR_CMIEA) ? 1 : 0;
+}
+
+/* ¥¿¥¤¥Þ¤Î¸½ºßÃÍ */
+int timer_gettime(int index)
+{
+  volatile struct h8_3069f_tmr *tmr = regs[index].tmr;
+  volatile int count;
+  int msec;
+
+  /*
+   * ¼þ´ü¥¿¥¤¥Þ¤Î¾ì¹ç¤ÏÆ°ºîÃ椫¤É¤¦¤«¤Î¥Á¥§¥Ã¥¯¤Îľ¸å¤Ë¥¿¥¤¥ÞËþλ¤¹¤ë¤È
+   * ¥«¥¦¥ó¥¿¤¬¥¼¥í¤Ë½é´ü²½¤µ¤ì¤Æ¤·¤Þ¤¦¤Î¤Ç¡¤Á°¤â¤Ã¤ÆÃͤò¼èÆÀ¤·¤Æ¤ª¤¯¡¥
+   */
+  count = tmr->tcnt;
+  msec = count * 2 / 5; /* 20MHz: (count * 8192 * 1000 / 20000000) */
+
+  return timer_is_running(index) ? msec : -1;
+}
diff --git a/firm/sample/sample1/os/timer.h b/firm/sample/sample1/os/timer.h
new file mode 100644 (file)
index 0000000..3ce7039
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _TIMER_H_INCLUDED_
+#define _TIMER_H_INCLUDED_
+
+#define TIMER_START_FLAG_CYCLE (1<<0)
+
+int timer_start(int index, int msec, int flags); /* ¥¿¥¤¥Þ³«»Ï */
+int timer_is_expired(int index);                 /* ¥¿¥¤¥ÞËþλ¤·¤¿¤«¡© */
+int timer_expire(int index);                     /* ¥¿¥¤¥ÞËþλ½èÍý */
+int timer_cancel(int index);                     /* ¥¿¥¤¥Þ¥­¥ã¥ó¥»¥ë */
+int timer_is_running(int index);                 /* ¥¿¥¤¥ÞÆ°ºîÃ椫¡© */
+int timer_gettime(int index);                    /* ¥¿¥¤¥Þ¤Î¸½ºßÃÍ */
+
+#endif
diff --git a/firm/sample/sample1/os/vs1011e.c b/firm/sample/sample1/os/vs1011e.c
new file mode 100644 (file)
index 0000000..3468d9b
--- /dev/null
@@ -0,0 +1,302 @@
+
+#include "vs1011e.h"
+#include "portconf.h"
+#include "spi.h"
+
+#define VS1011E_OPCODE_READ    0x03
+#define VS1011E_OPCODE_WRITE   0x02
+
+#define REGADDR_MODE           0x00
+#define REGADDR_STATUS         0x01
+#define REGADDR_BASS           0x02
+#define REGADDR_CLOCKF         0x03
+#define REGADDR_DECODE_TIME    0x04
+#define REGADDR_AUDATA         0x05
+#define REGADDR_WRAM           0x06
+#define REGADDR_WRAMADDR       0x07
+#define REGADDR_HDAT0          0x08
+#define REGADDR_HDAT1          0x09
+#define REGADDR_AIADDR         0x0A
+#define REGADDR_VOL            0x0B
+#define REGADDR_AICTRL0                0x0C
+#define REGADDR_AICTRL1                0x0D
+#define REGADDR_AICTRL2                0x0E
+#define REGADDR_AICTRL3                0x0F
+
+#define SM_DIFF                (1 <<  0)
+#define SM_LAYER12     (1 <<  1)
+#define SM_RESET       (1 <<  2)
+#define SM_OUTOFWAV    (1 <<  3)
+#define SM_SETTOZERO1  (1 <<  4)
+#define SM_TESTS       (1 <<  5)
+#define SM_STREAM      (1 <<  6)
+#define SM_SETTOZERO2  (1 <<  7)
+#define SM_DACT                (1 <<  8)
+#define SM_SDIORD      (1 <<  9)
+#define SM_SDISHARE    (1 << 10)
+#define SM_SDINEW      (1 << 11)
+#define SM_SETTOZERO3  (1 << 12)
+#define SM_SETTOZERO4  (1 << 13)
+
+#define SCI_BASS_BITBASS_ST_AMP                12
+#define SCI_BASS_BITBASS_ST_FREQ       8
+#define SCI_BASS_BITBASS_SB_AMP                4
+#define SCI_BASS_BITBASS_SB_FREQ       0
+
+#define VS1011E_RESET1()    do { *PORTCONF_P4DR |=  PORTCONF_P4BIT_VSRST; } while (0)
+#define VS1011E_RESET0()    do { *PORTCONF_P4DR &= ~PORTCONF_P4BIT_VSRST; } while (0)
+
+#define VS1011E_CHK_DREQ()  (((*PORTCONF_P4DR) & PORTCONF_P4BIT_VSDREQ) ? 0 : 1)
+
+static void _delay_ms(int ms)
+{
+    int i;
+    for (i = 0; i < ms * 10000; i++) {
+    }
+}
+
+static void _delay_us(int us)
+{
+    int i;
+    for (i = 0; i < us * 10; i++) {
+    }
+}
+
+static void vs1011e_read(uint8 addr, uint16 * stat);
+static void vs1011e_write(uint8 addr, uint16 stat);
+
+void vs1011e_init()
+{
+    vs1011e_reset_by_hardware();
+    vs1011e_reset_by_software();
+}
+
+void vs1011e_reset_by_hardware()
+{
+    // Assert vs1011 reset
+    VS1011E_RESET0();
+    // Delay 30ms
+    _delay_ms(30);
+    // Deassert CS
+    spi_deselect();
+    // Release vs1011 reset
+    VS1011E_RESET1();
+    // Delay 10ms (2.5ms accordig to datasheet)
+    _delay_ms(10);
+    // Set volume to minimum
+    vs1011e_write(REGADDR_VOL, 0xFFFF);
+    // Set CLOCKF
+    vs1011e_write(REGADDR_CLOCKF, 0x9800);
+    // Delay 1ms
+    _delay_ms(1);
+    // Set slow sample rate for slow analog part startup
+    vs1011e_write(REGADDR_AUDATA, 10);
+    // Delay 100ms
+    _delay_ms(100);
+    // Switch on the analog parts
+    vs1011e_write(REGADDR_VOL, 0xFEFE);
+    vs1011e_write(REGADDR_AUDATA, 44101);
+    vs1011e_write(REGADDR_VOL, 0x0202);
+}
+
+void vs1011e_reset_by_software()
+{
+    uint16 i;
+
+    // Delay 200ms
+    _delay_ms(200);
+    // Set SW reset bit, set VS1011 native mode on SPI
+    vs1011e_write(REGADDR_MODE,
+            SM_LAYER12 | SM_RESET | SM_SDINEW | SM_TESTS);
+    // Delay 2us
+    _delay_us(2);
+    // Rewrite SCI_CLOCKF after soft reset
+    vs1011e_write(REGADDR_CLOCKF, 0x9800);
+    // Assert DCS
+    spi_select(SpiTarget_VS1011E_DATA);
+    // Check the DREQ.
+    while (VS1011E_CHK_DREQ()) {
+    }
+    // Send 0x53 to SPI
+    spi_tx(0x53);
+    // Send 1024 nulls
+    for (i = 0; i < 1024; i++) {
+        // Check the DREQ.
+        while (VS1011E_CHK_DREQ()) {
+        }
+        spi_tx(0x00);
+    }
+    // Deassert DCS
+    spi_deselect();
+}
+
+void vs1011e_cancel_data()
+{
+    uint16 i;
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    spi_select(SpiTarget_VS1011E_DATA);
+    for (i = 0; i < 2048; i++) {
+        while (VS1011E_CHK_DREQ()) {
+        }
+        spi_tx(0x00);
+    }
+    spi_deselect();
+}
+
+void vs1011e_set_enhancer(uint8 st_amp, uint8 st_freq, uint8 sb_amp,
+        uint8 sb_freq)
+{
+    uint16 val =
+        (st_amp << SCI_BASS_BITBASS_ST_AMP) |
+        (st_freq << SCI_BASS_BITBASS_ST_FREQ) |
+        (sb_amp << SCI_BASS_BITBASS_SB_AMP) |
+        (sb_freq << SCI_BASS_BITBASS_SB_FREQ);
+    vs1011e_write(REGADDR_BASS, val);
+}
+
+void vs1011e_get_enhancer(uint8 * st_amp, uint8 * st_freq,
+        uint8 * sb_amp, uint8 * sb_freq)
+{
+    uint16 val;
+    vs1011e_read(REGADDR_BASS, &val);
+    *st_amp = (val >> SCI_BASS_BITBASS_ST_AMP) & 0x0F;
+    *st_freq = (val >> SCI_BASS_BITBASS_ST_FREQ) & 0x0F;
+    *sb_amp = (val >> SCI_BASS_BITBASS_SB_AMP) & 0x0F;
+    *sb_freq = (val >> SCI_BASS_BITBASS_SB_FREQ) & 0x0F;
+}
+
+void vs1011e_volume_read(uint8 * left, uint8 * right)
+{
+    uint16 val;
+    vs1011e_read(REGADDR_VOL, &val);
+    *left = val >> 8;
+    *right = val >> 0;
+}
+
+void vs1011e_volume_write(const uint8 left, const uint8 right)
+{
+    uint16 val =
+        (((uint16) left << 8) & 0xFF00) | (((uint16) right << 0) &
+            0x00FF);
+    vs1011e_write(REGADDR_VOL, val);
+}
+
+void vs1011e_play(int8(*func) (uint8 * buf, const uint16 len))
+{
+#define UNITBYTE    (128)
+    uint8 i;
+    uint8 buf[UNITBYTE];
+    while (1) {
+        /*
+         * Read the song data.
+         */
+        int8 len = func(buf, UNITBYTE);
+        if (len <= 0) {
+            return;
+        }
+        /*
+         * Send the data.
+         */
+        for (i = 0; i < UNITBYTE; i++) {
+            while (VS1011E_CHK_DREQ()) { }
+            spi_select(SpiTarget_VS1011E_DATA);
+            spi_tx(*(buf + i));
+            spi_deselect();
+        }
+    }
+}
+
+void vs1011e_decodetime_read(uint16 * sec)
+{
+    vs1011e_read(REGADDR_DECODE_TIME, sec);
+}
+
+void vs1011e_decodetime_write(const uint16 sec)
+{
+    vs1011e_write(REGADDR_DECODE_TIME, sec);
+}
+
+void vs1011e_sinetest_init()
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    spi_select(SpiTarget_VS1011E_DATA);
+    spi_tx(0x53);
+    spi_tx(0xEF);
+    spi_tx(0x6E);
+    spi_tx(0xF0);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_deselect();
+}
+
+void vs1011e_sinetest_fini()
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    spi_select(SpiTarget_VS1011E_DATA);
+    spi_tx(0x45);
+    spi_tx(0x78);
+    spi_tx(0x69);
+    spi_tx(0x74);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_tx(0x00);
+    spi_deselect();
+
+    vs1011e_cancel_data();
+}
+
+void vs1011e_register_print()
+{
+#if 0
+    uint8 i;
+    uint16 val;
+    xprintf(PSTR("===================\r\n"));
+    for (i = 0; i <= 0x0F; i++) {
+        vs1011e_read(i, &val);
+        xprintf(PSTR("0x%02X: 0x%04X\r\n"), i, val);
+    }
+    xprintf(PSTR("===================\r\n"));
+#endif
+}
+
+static void vs1011e_read(uint8 addr, uint16 * stat)
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    spi_select(SpiTarget_VS1011E_CTRL);
+
+    spi_tx(VS1011E_OPCODE_READ);
+    spi_tx(addr);
+
+    *stat = 0;
+    *stat |= spi_rx() << 8;
+    *stat |= spi_rx();
+
+    spi_deselect();
+}
+
+static void vs1011e_write(uint8 addr, uint16 stat)
+{
+    while (VS1011E_CHK_DREQ()) {
+    }
+
+    spi_select(SpiTarget_VS1011E_CTRL);
+
+    spi_tx(VS1011E_OPCODE_WRITE);
+    spi_tx(addr);
+
+    spi_tx(stat >> 8);
+    spi_tx(stat >> 0);
+
+    spi_deselect();
+}
diff --git a/firm/sample/sample1/os/vs1011e.h b/firm/sample/sample1/os/vs1011e.h
new file mode 100644 (file)
index 0000000..17138d9
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef VS1011_H
+#define VS1011_H
+
+#include "defines.h"
+
+void vs1011e_init(void);
+void vs1011e_reset_by_hardware(void);
+void vs1011e_reset_by_software(void);
+void vs1011e_cancel_data(void);
+void vs1011e_set_enhancer(uint8 st_amp, uint8 st_freq, uint8 sb_amp, uint8 sb_freq);
+void vs1011e_get_enhancer(uint8 * st_amp, uint8 * st_freq, uint8 * sb_amp, uint8 * sb_freq);
+void vs1011e_volume_read(uint8 * left, uint8 * right);
+void vs1011e_volume_write(const uint8 left, const uint8 right);
+void vs1011e_play(int8(*func) (uint8 * buf, const uint16 len));
+void vs1011e_decodetime_read(uint16 * sec);
+void vs1011e_decodetime_write(const uint16 sec);
+void vs1011e_register_print(void);
+
+void vs1011e_sinetest_init(void);
+void vs1011e_sinetest_fini(void);
+
+#endif
+