OSDN Git Service

Copied from 05.
authorShinichiro Nakamura <shinta.main.jp@gmail.com>
Tue, 29 May 2012 10:06:45 +0000 (19:06 +0900)
committerShinichiro Nakamura <shinta.main.jp@gmail.com>
Tue, 29 May 2012 10:06:45 +0000 (19:06 +0900)
70 files changed:
firm/06/bootload/KL-01 [new file with mode: 0644]
firm/06/bootload/LICENSE [new file with mode: 0644]
firm/06/bootload/Makefile [new file with mode: 0644]
firm/06/bootload/defines.h [new file with mode: 0644]
firm/06/bootload/dram.c [new file with mode: 0644]
firm/06/bootload/dram.h [new file with mode: 0644]
firm/06/bootload/elf.c [new file with mode: 0644]
firm/06/bootload/elf.h [new file with mode: 0644]
firm/06/bootload/interrupt.c [new file with mode: 0644]
firm/06/bootload/interrupt.h [new file with mode: 0644]
firm/06/bootload/intr.S [new file with mode: 0644]
firm/06/bootload/intr.h [new file with mode: 0644]
firm/06/bootload/lcd.c [new file with mode: 0644]
firm/06/bootload/lcd.h [new file with mode: 0644]
firm/06/bootload/ld.scr [new file with mode: 0644]
firm/06/bootload/led.c [new file with mode: 0644]
firm/06/bootload/led.h [new file with mode: 0644]
firm/06/bootload/lib.c [new file with mode: 0644]
firm/06/bootload/lib.h [new file with mode: 0644]
firm/06/bootload/main.c [new file with mode: 0644]
firm/06/bootload/re.c [new file with mode: 0644]
firm/06/bootload/re.h [new file with mode: 0644]
firm/06/bootload/serial.c [new file with mode: 0644]
firm/06/bootload/serial.h [new file with mode: 0644]
firm/06/bootload/startup.s [new file with mode: 0644]
firm/06/bootload/sw.c [new file with mode: 0644]
firm/06/bootload/sw.h [new file with mode: 0644]
firm/06/bootload/vector.c [new file with mode: 0644]
firm/06/bootload/xmodem.c [new file with mode: 0644]
firm/06/bootload/xmodem.h [new file with mode: 0644]
firm/06/os/KL-01 [new file with mode: 0644]
firm/06/os/LICENSE [new file with mode: 0644]
firm/06/os/Makefile [new file with mode: 0644]
firm/06/os/clock.c [new file with mode: 0644]
firm/06/os/command.c [new file with mode: 0644]
firm/06/os/consdrv.c [new file with mode: 0644]
firm/06/os/consdrv.h [new file with mode: 0644]
firm/06/os/defines.h [new file with mode: 0644]
firm/06/os/interrupt.c [new file with mode: 0644]
firm/06/os/interrupt.h [new file with mode: 0644]
firm/06/os/intr.h [new file with mode: 0644]
firm/06/os/kozos.c [new file with mode: 0644]
firm/06/os/kozos.h [new file with mode: 0644]
firm/06/os/lcd.c [new file with mode: 0644]
firm/06/os/lcd.h [new file with mode: 0644]
firm/06/os/ld.scr [new file with mode: 0644]
firm/06/os/led.c [new file with mode: 0644]
firm/06/os/led.h [new file with mode: 0644]
firm/06/os/leddrv.c [new file with mode: 0644]
firm/06/os/leddrv.h [new file with mode: 0644]
firm/06/os/lib.c [new file with mode: 0644]
firm/06/os/lib.h [new file with mode: 0644]
firm/06/os/main.c [new file with mode: 0644]
firm/06/os/memory.c [new file with mode: 0644]
firm/06/os/memory.h [new file with mode: 0644]
firm/06/os/re.c [new file with mode: 0644]
firm/06/os/re.h [new file with mode: 0644]
firm/06/os/rotenc.c [new file with mode: 0644]
firm/06/os/rotenc.h [new file with mode: 0644]
firm/06/os/serial.c [new file with mode: 0644]
firm/06/os/serial.h [new file with mode: 0644]
firm/06/os/startup.s [new file with mode: 0644]
firm/06/os/sw.c [new file with mode: 0644]
firm/06/os/sw.h [new file with mode: 0644]
firm/06/os/syscall.c [new file with mode: 0644]
firm/06/os/syscall.h [new file with mode: 0644]
firm/06/os/timer.c [new file with mode: 0644]
firm/06/os/timer.h [new file with mode: 0644]
firm/06/os/timerdrv.c [new file with mode: 0644]
firm/06/os/timerdrv.h [new file with mode: 0644]

diff --git a/firm/06/bootload/KL-01 b/firm/06/bootload/KL-01
new file mode 100644 (file)
index 0000000..335ecb7
--- /dev/null
@@ -0,0 +1,117 @@
+Àî¹çƲ¥é¥¤¥»¥ó¥¹-01  ver.1.0
+                                                  2000.12.30  H.Kawai (Àî¹ç½¨¼Â)
+                                                  2007.10.07 ¥ê¥ó¥¯½¤Àµ:¤¢¤Ã¤­¤£
+
+£°¡¥³µÍ×
+
+  Ê¿¤¿¤¯¸À¤¦¤È¡¢¡Ö¥Õ¥ê¡¼¥½¥Õ¥È¤Ç¤¹¡£»ÈÍÑÁ°»ÈÍѸå¤ËÂвÁ¤ò»Ùʧ¤¦¤³¤È¤Ê¤¯¡¢¼«Í³¤Ë»È
+¤¨¤Þ¤¹¡£¥³¥Ô¡¼¤·¤Æ¤â¤¤¤¤¤Ç¤¹¡£²þÊѤ·¤Æ¤â¤¤¤¤¤Ç¤¹¡£¾¦¶ÈÍøÍѤ·¤Æ¤â¤¤¤¤¤Ç¤¹¡£¤Ç¤â¥Ð
+¥°¤Ê¤É¤Ç»³²¤¬½Ð¤Æ¤âÀÕǤ¤Ï¤È¤ì¤Þ¤»¤ó¡£¡×¤Ã¤Æ¤³¤È¤Ç¤¹¡£
+
+  ÍøÍѼԤä²þÊѤ·¤¿¤ê»²¹Í¤Ë¤·¤¿¤ê¤¹¤ë¿Í¤ÎÍø±×¤Î¤¿¤á¤Ë¡¢¥×¥í¥°¥é¥àÃæ¤Ç»È¤Ã¤Æ¤¤¤ë¥¢
+¥ë¥´¥ê¥º¥à¤ÇÃøºî¼Ô¤¬¾­ÍèÆõö¤ò¤È¤ë¤³¤È¤¬¤¢¤Ã¤Æ¤â¡¢ÆõöÎÁ¤òÍ׵ᤷ¤¿¤ê¤Ï¤·¤Ê¤¤¤È¤¤
+¤¦Êݾڤ⤢¤ê¤Þ¤¹¡£
+
+£±¡¥ÌÜŪ
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤ÇÄ󶡤µ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Ï¡¢¾¯¤·¤Ç¤â¿¤¯¤Î¿Í¤ËÍø±×¤ò¤â¤¿¤é¤·¡¢¥½
+¥Õ¥È¥¦¥§¥¢µ»½Ñ¤Î¿ÊÊâ¤Ë¾¯¤·¤Ç¤â¹×¸¥¤Ç¤­¤ì¤Ð¤È¤¤¤¦ÌÜŪ¤Ç¸ø³«¤¹¤ë¡£
+
+£²¡¥¼ñ»Ý
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤Ï¡¢Ãøºî¸¢¤òÊü´þ¤¹¤ë¤â¤Î¤Ç¤Ï¤Ê¤¤¡ÊÆÈÀêŪ¤Ë¥³¥Ô¡¼¤¹¤ë¸¢Íø¤ÏÊü´þ¤·
+¤Æ¤¤¤ë¡Ë¡£ÍøÍѼԤϤ³¤Î¥½¥Õ¥È¥¦¥§¥¢¤Î°ìÉô¤Þ¤¿¤ÏÁ´Éô¤ò¼«Í³¤Ë¥³¥Ô¡¼¤·¡¢ºÆÇÛÉÛ¤¹¤ë¤³
+¤È¤¬¤Ç¤­¤ë¡£ÍøÍѤ˺ݤ·¤ÆÂвÁ¤òÍ׵ᤷ¤Ê¤¤¡£²òÀÏ¡¢²þÊѤâÂвÁ¤Ê¤·¤Ëǧ¤á¤ë¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤ÎÍøÍѤˤĤ¤¤Æ¡¢¾¦¶ÈŪ¤ÊÍøÍѤâ̵¾ò·ï¤Çǧ
+¤á¤ë¡£¤½¤Î¤Þ¤ÞÍ­½þ¤ÇÈÎÇ䤷¤Æ¤â¹½¤ï¤Ê¤¤¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Î°ìÉô¤Þ¤¿¤ÏÁ´Éô¤ò¸µ¤Ë¤·¤ÆºîÀ®¤µ¤ì¤¿¥½¥Õ
+¥È¥¦¥§¥¢¡Ê°Ê¹ß¡¢ÇÉÀ¸Êª¤È¾Î¤¹¤ë¡Ë¤ËÂФ·¡¢¤É¤ó¤Ê¥é¥¤¥»¥ó¥¹¤òÉÕÍ¿¤·¤Æ¤â¤è¤¤¡£¤¹¤Ê¤ï
+¤Á¡¢ÇÉÀ¸Êª¤¬¥³¥Ô¡¼¶Ø»ß¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¤·¡¢ÇÉÀ¸Êª¤¬Í­½þ¤Ç¤·¤«ÇÛÉÛ¤µ¤ì¤Ê¤¯¤Æ¤â¹½¤ï¤Ê
+¤¤¡£¤â¤Á¤í¤ó̵½þ¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¡£ÇÉÀ¸Êª¤ËÂФ¹¤ëÃøºî¸¢¤Ï¡¢ÇÉÀ¸Êª¤òÀ¸À®¤·¤¿¼Ô¤Ëµ¢¤·
+¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤¬ÇÉÀ¸Êª¤ËÂФ·¤ÆÃøºî¸¢¤ò¼çÄ¥¤¹¤ë
+¤³¤È¤Ï¤Ê¤¤¡£
+
+  ÇÉÀ¸Êª¤Î¥É¥­¥å¥á¥ó¥ÈÃæ¤Ë¡¢¸µ¤Ë¤·¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤ò¾Ò²ð¤¹¤ëµÁ̳¤Ï¤Ê¤¤¡£¤³
+¤Îʸ¤Ï¡¢¤â¤Á¤í¤ó¡¢¾Ò²ð¤¹¤ë¤³¤È¤ò¶Ø»ß¤¹¤ë¤â¤Î¤Ç¤â¤Ê¤¤¡£
+
+  ÇÉÀ¸Êª¤Î¸ø³«¤ËºÝ¤·¤Æ¡¢¸µ¤Ë¤·¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤Ë³Îǧ¤ò¼è¤ëµÁ̳¤Ï¤Ê¤¤¡£¤³¤Î
+ʸ¤Ï¡¢¤â¤Á¤í¤ó¡¢³Îǧ¤ò¶Ø»ß¤¹¤ë¤â¤Î¤Ç¤Ï¤Ê¤¤¡£
+
+  Ãøºî¼Ô¤Ï¡¢¥½¥Õ¥È¥¦¥§¥¢¤Î¼Á¤òÊݾڤ·¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÇÈï³²¤òÈï
+¤Ã¤¿¤ê¡¢´üÂÔ¤·¤¿·ë²Ì¤¬ÆÀ¤é¤ì¤Ê¤¯¤Æ¤â¡¢Ãøºî¼Ô¤ÏÀÕǤ¤òÉé¤ï¤Ê¤¤¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Ç»È¤ï¤ì¤Æ¤¤¤ëµ»½Ñ¤Ë¤Ä¤¤¤Æ¤Ï¡¢»öÁ°¤ËÃøºî
+¼Ô¤Ëµö¤µ¤ì¤¿¼Ô°Ê³°¤¬Æõö¤ò¼èÆÀ¤¹¤ë¤³¤È¤Ï¶Ø»ß¤¹¤ë¡£¿·¤¿¤Êµ»½Ñ¤ò²Ã¤¨¤¿ÇÉÀ¸Êª¤òÀ¸À®
+¤·¡¢¤½¤ÎÄɲ䵤줿Éôʬ¤ÎÆõö¤ò¤È¤ë¤³¤È¤Ïǧ¤á¤ë¡£Ãøºî¼Ô¤¬¥½¥Õ¥È¥¦¥§¥¢Ãæ¤Îµ»½Ñ¤ËÂÐ
+¤·¤Æ¸å¤«¤éÆõö¤ò¤È¤ë¤³¤È¤Ï¤¢¤ê¤¦¤ë¤¬¡¢ÇÉÀ¸Êª¤ä¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÎÍøÍѤËÂФ·¤ÆÆõö
+ÎÁ¤ä¤½¤Î¾¤ÎÂвÁ¤òµá¤á¤ë¤³¤È¤Ï¤Ê¤¤¤³¤È¤òÊݾڤ¹¤ë¡£¤³¤ÎÊݾڤϡ¢Æõö¼èÆÀÁ°¤ËÀ¸À®¤µ
+¤ì¤¿ÇÉÀ¸Êª¤À¤±¤Ç¤Ê¤¯¡¢Æõö¼èÆÀ¸å¤ËÀ¸À®¤µ¤ì¤¿ÇÉÀ¸Êª¤Ë¤âŬÍѤµ¤ì¤ë¡£
+
+  ²òÀÏ·ë²Ì¤ò¤Þ¤È¤á¤ÆÆõö¤ò¤È¤ë¤³¤È¤Ë¤Ï»öÁ°¤ÎÃøºî¼Ô¤Îµö²Ä¤¬É¬ÍפÀ¤«¡¢Æõö¤ò¤È¤ë¤³
+¤È°Ê³°¤Ë¤Ä¤¤¤Æ¤Ï²¿¤éÀ©¸Â¤Ï¤Ê¤¤¡£
+
+£³¡¥Êä­
+
+  ´ðËÜŪ¤Ë¡¢¥³¥Ô¡¼¤ÏÂç´¿·Þ¤Ç¤¹¡£¤â¤·¡¢Ãøºî¼Ô¤Ë²¿¤«²¸¤ò´¶¤¸¤¿¤é¡¢°ì¿Í¤Ç¤â¿¤¯¤Î¿Í
+¤Ë¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ò¤¹¤¹¤á¤Æ¡¢¥³¥Ô¡¼¤·¤Æ¤¢¤²¤Æ²¼¤µ¤¤¡£Ãøºî¼Ô¤Ï¿¤¯¤Î¿Í¤Ë»È¤Ã¤Æ¤â
+¤é¤¤¤¿¤¤¤È»×¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢¥³¥Ô¡¼¤¹¤ì¤ÐÃøºî¼Ô¤Ï´î¤Ó¤Þ¤¹¡£¤½¤ì¤Ç¤â­¤ê¤Ê¤¤¤È´¶¤¸¤¿
+¤é¡¢À§Èó¡¢´¶ÁÛ¤òÃøºî¼Ô¤ËÁ÷¤Ã¤Æ¤¢¤²¤Æ²¼¤µ¤¤¡£¤½¤¦¤¹¤ì¤Ð¡¢¤â¤Ã¤È´î¤Ö¤Ç¤·¤ç¤¦¡£
+
+  ¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¸¢¾ðÊó¤À¤±¤ò²þÊѤ·¡¢¤½¤ì¤òºÆÇÛÉÛ¤¹¤ë¤³
+¤È¤Ï¤³¤Î¥é¥¤¥»¥ó¥¹¤Ë¤è¤Ã¤Æ¶Ø»ß¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£ÇÉÀ¸Êª°·¤¤¤Ç¤¹¡£¤³¤ì¤ÏÈ´¤±·ê¤Ç¤Ï¤Ê
+¤¤¤Ç¤¹¡£¤·¤¿¤¬¤Ã¤Æ¡¢Ãøºî¸¢¾ðÊó¤À¤±¤ò½ñ¤­´¹¤¨¤ÆºÆÇÛÉÛ¤¹¤ë¤³¤È¤¬É¬Íפʤ顢¤·¤Æ¤¤¤¿
+¤À¤¤¤Æ¤«¤Þ¤¤¤Þ¤»¤ó¡£
+
+  ¥Ð¥°¤ò¼è¤Ã¤¿¤ê¡¢µ¡Ç½¤òÄɲ䷤Ƥ¤¤¿¤À¤¯¤Î¤Ï¤â¤Á¤í¤ó¤Ç¤¹¤¬¡¢¥×¥í¥°¥é¥à¤ËÃð¼á¤òÉÕ
+¤±¤ÆÆɤߤ䤹¤¯¤·¤¿¤ê¡¢¥É¥­¥å¥á¥ó¥È¤òÊä­¤¹¤ë¤Ê¤É¡¢¤½¤¦¤¤¤¦¥Ð¥¤¥Ê¥ê¡¼¤ä¼Â¹Ô·ë²Ì¤Ë
+È¿±Ç¤µ¤ì¤Ê¤¤¤è¤¦¤Ê²þÊѤâÂç´¿·Þ¤Ç¤¹¡£¤½¤¦¤¤¤¦ÇÉÀ¸Êª¤¬¤Ç¤­¤¿¤é¡¢Ï¢Íí¤·¤Æ¤â¤é¤¨¤ë¤È
+¤¦¤ì¤·¤¤¤Ç¤¹¡ÊµÁ̳¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡Ë¡£
+
+  ²¿¤«µ¿ÌäÅÀ¤¬¤¢¤Ã¤¿¤ê¡¢ÇÉÀ¸Êª¤òºîÀ®¤¹¤ë¾å¤Ç¾ðÊó¤¬ÉÔ­¤·¤Æ¤¤¤ë¤È´¶¤¸¤¿¤é¡¢Ãøºî¼Ô
+¤ËÏ¢Íí¤ò¤È¤Ã¤Æ¼ÁÌ䤹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤¿¤À¡¢Ãøºî¼Ô¤ÎÅÔ¹ç¤Ç¤¹¤°¤Ë¤ÏÊÖ»ö¤¬¤Ç¤­¤Ê¤¤
+¤«¤â¤·¤ì¤Þ¤»¤ó¡£¤½¤ì¤Ï¤´ÍƼϤ¯¤À¤µ¤¤¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤½¤Î¤â¤Î¤ÎÉÔÈ÷¤Ê¤É¤ò»ØŦ¤¹¤ë
+¾ì¹ç¤Ï¡¢Ãøºî¼Ô¤«Àî¹çƲ¤Ë¤´Ï¢Íí¤¯¤À¤µ¤¤¡£
+
+  ¤â¤·¤«¤¹¤ë¤È¡¢¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ëµ»½Ñ¤Ë¤Ä¤¤¤Æ¡¢
+Ãøºî¼Ô¤Îµö²Ä¤Î̵¤¤¼Ô¤¬Æõö¤ò¼èÆÀ¤¹¤ë¤³¤È¤ò¶Ø¤¸¤Æ¤¤¤ë¤³¤È¤¬¡¢ÆüËܤÎÆõöË¡¤ËÄñ¿¨¤·
+¤Æ¤¤¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡Ê¤´°Õ¸«¤òÂԤäƤ¤¤Þ¤¹¡Ë¡£¤³¤ì¤Ë¤Ä¤¤¤Æ¡¢¥é¥¤¥»¥ó¥¹¤òºÇ½é¤ËÄó
+¾§¤·¤¿Àî¹ç½¨¼Â¤Î¸«²ò¤ò°Ê²¼¤Ë½ñ¤¤¤Æ¤ª¤­¤Þ¤¹¡£
+
+  ÆõöË¡¤¬À©Äꤵ¤ì¤¿Çطʤˤϡ¢È¯ÌÀ¼Ô¤¬¼«Ê¬¤ÎȯÌÀ¤Ë¤è¤ëÍø±×¤ò¼é¤ë¤¿¤á¤ËȯÌÀ¤Î¾ÜºÙ
+¤ò¸øɽ¤·¤Ê¤¤¤³¤È¤¬²Ê³Øµ»½Ñ¤Î¿ÊÊâ¤òÃ٤餻¤ë¤«¤é¡¢¸øɽ¤·¤Æ¤â¤é¤¦Âå¤ï¤ê¤Ë°ìÄê´ü´Ö¤Î
+ÆÈÀêÍøÍѤòˡŪ¤ËÊݸ¤ë¡¢¤È¤¤¤¦Àº¿À¤¬¤¢¤ê¤Þ¤¹¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤Ç¤Ï¡¢È¯ÌÀ¤Î¾ÜºÙ¤ò
+°Õ¿ÞŪ¤Ë±£¤¹¤Ä¤â¤ê¤Ï¤Ê¤¯¡¢¤·¤¿¤¬¤Ã¤ÆÆõö¤ò¼è¤ë¤³¤È¤ò¶Ø»ß¤·¤Æ¤âÆõöË¡¤ÎÀº¿À¤Ë¤ÏÈ¿
+¤·¤Æ¤¤¤Ê¤¤¤È¹Í¤¨¤Æ¤¤¤Þ¤¹¡£¤à¤·¤í¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤ÎÀº¿À¤òµâ¤Þ¤Ê¤¤¼Ô¤¬Æõö¤ò¼èÆÀ¤·
+¥ª¥ê¥¸¥Ê¥ë¤Î¥½¥Õ¥È¥¦¥§¥¢¤äÇÉÀ¸Êª¤ËÂФ·¤ÆÆõöÎÁ¤òÀÁµá¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤É԰¤ÎÊý¤¬¡¢
+²Ê³Øµ»½Ñ¤Î¿ÊÊâ¤òÃ٤餻¤ë¤È¹Í¤¨¤Þ¤¹¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ÎÉ԰¤ò»öÁ°¤Ëʧ¿¡¤·¤¿¤³¤Î¥é¥¤
+¥»¥ó¥¹¤ÏÆõöË¡¤ËŬ¤Ã¤¿¤â¤Î¤À¤È¹Í¤¨¤Æ¤¤¤Þ¤¹¡£
+
+  ¤â¤Á¤í¤ó¡¢°ìÈְ¿´¤Ê¤Î¤Ï¡¢¥ª¥ê¥¸¥Ê¥ë¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÇȯÌÀ¤Èǧ¤á¤é¤ì¤ë¤¹¤Ù¤Æ¤Î¤â
+¤Î¤Ë¤Ä¤¤¤ÆÃøºî¼Ô¤¬Æõö¤ò¼èÆÀ¤·¤Æ¡¢Â¾¼Ô¤ÎÆõö¼èÆÀ¤ò»öÁ°¤Ë˸¤²¤ì¤Ð¤¤¤¤¤Î¤Ç¤¹¤¬¡¢¤½
+¤ì¤ÏÃøºî¼Ô¤Ë¤ÏÉéô¤Ë¤Ê¤ë¾ì¹ç¤¬¤¢¤ê¤Þ¤¹¡£¤½¤ÎÉéô¤È¥½¥Õ¥È¥¦¥§¥¢¤ò¸ø³«¤¹¤ë¤«¤É¤¦¤«
+¤òÅ·Çé¤Ë¤«¤±¤Ê¤±¤ì¤Ð¤¤¤±¤Ê¤¤¤È¤·¤¿¤é¡¢¸ø³«¤ò¤¢¤­¤é¤á¤Æ¤·¤Þ¤¦¾ì¹ç¤â¤¢¤ë¤«¤â¤·¤ì¤Þ
+¤»¤ó¡£¤½¤ì¤ÏÆõöË¡¤ÎÀº¿À¤Î´üÂÔ¤¹¤ë¤â¤Î¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¤·¡¢²æ¡¹¤ÎÌÜŪ¡Ê¡Ö£±¡¥ÌÜŪ¡×
+¤ò»²¾È¡Ë¤Ë¤â±è¤¤¤Þ¤»¤ó¡£
+
+  ¤Þ¤¿¡¢È¯ÌÀ¤Î¾ÜºÙ¤¬ÆõöË¡¤Î·Á¼°¤Ë¤è¤Ã¤Æµ­½Ò¤µ¤ì¤Æ¤¤¤Ê¤¤¤¿¤á¤ËÌÀ¤é¤«¤Ç¤Ê¤¤¾ì¹ç¡¢
+Ãøºî¼Ô°Ê³°¤Î¤â¤Î¤¬µö²Ä¤Ê¤¯¤½¤ì¤ò²òÀϤ·¤ÆÌÀ¤é¤«¤Ë¤¹¤ë¤³¤È¤Ï¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤Çǧ¤á
+¤é¤ì¤Æ¤¤¤Æ¤¤¤Þ¤¹¡£¤½¤ì¤ò̵½þ¤Ç¸ø³«¤·¤Æ¤â¤¤¤¤¤Ç¤¹¤·¡¢Í­½þ¤ÇÈÎÇ䤹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹
+¡£
+
+  ¤Ê¤ª¡¢¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢Ãæ¤Î¤¹¤Ù¤Æ¤Îµ»½Ñ¤ËÂФ·¤Æ¡¢ÍøÍѤ˺ݤ·¤Æ
+ÆõöÎÁ¤ò»Ùʧ¤¦¿´ÇÛ¤¬Á´¤¯Ìµ¤¤¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£¸ø³«¤Î»þÅÀ¤ÇÍ­¸ú¤ÊÆõö¤Ë¤è¤ëµ»½Ñ
+¤¬¥½¥Õ¥È¥¦¥§¥¢Æâ¤Ç»È¤ï¤ì¤Æ¤¤¤ì¤Ð¡¢¤½¤ì¤Ë¤Ä¤¤¤Æ¤ÏÆõöÊÝ»ý¼Ô¤«¤é¤ÎÆõöÎÁÍ׵᤬¤¢¤ê
+¤¨¤Þ¤¹¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤¬ÆõöÎÁ¤Î¿´ÇÛ̵¤·¤ÈÊݾڤ·¤Æ¤¤¤ë¤Î¤Ï¡¢¤³¤Î¥½¥Õ¥È¥¦¥§¥¢Æâ¤Ç
+¿·¤¿¤ËȯÌÀ¤Èǧ¤á¤é¤ì¤ëµ»½Ñ¤ËÂФ·¤Æ¤Î¤ß¤Ç¤¹¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤ò¼«Ê¬¤Î¥½¥Õ¥È¥¦¥§¥¢¤ËŬÍѤ·¤¿¤¤¤È»×¤¦Êý¤¬¤ª¤é¤ì¤Þ¤·¤¿¤é¡¢»öÁ°¡¦
+»ö¸å¤Ëµö²Ä¤òµá¤á¤ë¤³¤È¤Ê¤¯»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤«¤Þ¤¤¤Þ¤»¤ó¡£¤â¤·ÉÔÅԹ礬¤¢¤ì¤Ð¡¢¥é¥¤
+¥»¥ó¥¹Ê¸¤ò²þÊѤ·¤Æ»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤â¤¤¤¤¤Ç¤¹¡£²þÊѤκݤˤϡ¢º®Íð¤òËɤ°¤¿¤á¤Ë¥é¥¤
+¥»¥ó¥¹Ì¾¤òÊѹ¹¤¹¤ë¤Î¤ò˺¤ì¤Ê¤¤¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
+
+£´¡¥¥ê¥ó¥¯
+
+  Àî¹ç½¨¼ÂURL     http://k.osask.jp/
+       e-mail     kawai@osask.jp
diff --git a/firm/06/bootload/LICENSE b/firm/06/bootload/LICENSE
new file mode 100644 (file)
index 0000000..6128b3b
--- /dev/null
@@ -0,0 +1,6 @@
+¤³¤Î¥½¥Õ¥È¥¦¥¨¥¢¤Ïºä°æ¹°Î¼¤Ë¤è¤Ã¤ÆºîÀ®¤µ¤ì¤¿¤â¤Î¤Ç¤¢¤ê¡¤KL-01¤ÇÇÛÉÛ¤·¤Þ¤¹¡¥
+KL-01¤Ë¤Ä¤¤¤Æ¤ÏźÉդΠKL-01 ¤«¡¤¤â¤·¤¯¤Ï°Ê²¼¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+http://wiki.osask.jp/?KL-01
+
+°Ê¾å
diff --git a/firm/06/bootload/Makefile b/firm/06/bootload/Makefile
new file mode 100644 (file)
index 0000000..a9a50eb
--- /dev/null
@@ -0,0 +1,72 @@
+PREFIX  = /usr/local
+ARCH    = h8300-elf
+BINDIR  = $(PREFIX)/bin
+ADDNAME = $(ARCH)-
+
+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
+
+H8WRITE = ../../tools/kz_h8write/kz_h8write
+
+# FreeBSD-4.x:/dev/cuaaX, FreeBSD-6.x:/dev/cuadX, FreeBSD(USB):/dev/cuaUx
+# Linux:/dev/ttySx, Linux(USB):/dev/ttyUSBx, Windows:comX
+H8WRITE_SERDEV = /dev/ttyUSB0
+
+OBJS  = vector.o startup.o intr.o main.o interrupt.o
+OBJS += lib.o serial.o xmodem.o elf.o dram.o
+OBJS += led.o
+OBJS += re.o
+OBJS += sw.o
+OBJS += lcd.o
+
+TARGET = kzload
+
+CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
+#CFLAGS += -mint32 # int¤ò32¥Ó¥Ã¥È¤Ë¤¹¤ë¤È³Ý»»¡¿³ä»»¤¬¤Ç¤­¤Ê¤¯¤Ê¤ë
+CFLAGS += -I.
+#CFLAGS += -g
+CFLAGS += -Os
+CFLAGS += -DKZLOAD
+
+LFLAGS = -static -T ld.scr -L.
+
+.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) $<
+
+$(TARGET).mot :        $(TARGET)
+               $(OBJCOPY) -O srec $(TARGET) $(TARGET).mot
+
+image :                $(TARGET).mot
+
+write :                $(TARGET).mot
+               $(H8WRITE) -3069 -f20 $(TARGET).mot $(H8WRITE_SERDEV)
+
+clean :
+               rm -f $(OBJS) $(TARGET) $(TARGET).elf $(TARGET).mot
+
+console :
+       minicom -o console -b 9600 -D $(H8WRITE_SERDEV)
diff --git a/firm/06/bootload/defines.h b/firm/06/bootload/defines.h
new file mode 100644 (file)
index 0000000..e7dcac8
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _DEFINES_H_INCLUDED_
+#define _DEFINES_H_INCLUDED_
+
+#define NULL ((void *)0)
+#define SERIAL_DEFAULT_DEVICE 1
+
+typedef unsigned char  uint8;
+typedef unsigned short uint16;
+typedef unsigned long  uint32;
+
+#endif
diff --git a/firm/06/bootload/dram.c b/firm/06/bootload/dram.c
new file mode 100644 (file)
index 0000000..d3e5662
--- /dev/null
@@ -0,0 +1,202 @@
+#include "defines.h"
+#include "lib.h"
+#include "dram.h"
+
+#define H8_3069F_ABWCR  ((volatile uint8 *)0xfee020)
+#define H8_3069F_ASTCR  ((volatile uint8 *)0xfee021)
+#define H8_3069F_RTCOR  ((volatile uint8 *)0xfee02a)
+#define H8_3069F_RTMCSR ((volatile uint8 *)0xfee028)
+#define H8_3069F_DRCRB  ((volatile uint8 *)0xfee027)
+#define H8_3069F_DRCRA  ((volatile uint8 *)0xfee026)
+
+#define H8_3069F_P1DDR  ((volatile uint8 *)0xfee000)
+#define H8_3069F_P2DDR  ((volatile uint8 *)0xfee001)
+#define H8_3069F_P8DDR  ((volatile uint8 *)0xfee007)
+#define H8_3069F_PBDDR  ((volatile uint8 *)0xfee00a)
+
+#define H8_3069F_WCRH   ((volatile uint8 *)0xfee022)
+#define H8_3069F_WCRL   ((volatile uint8 *)0xfee023)
+
+typedef struct {
+  union {
+    volatile uint8  val8[4];
+    volatile uint16 val16[2];
+    volatile uint32 val32[1];
+  } u;
+} val_t;
+
+int dram_init()
+{
+  int i, j;
+
+  *H8_3069F_ABWCR  = 0xff;
+  *H8_3069F_RTCOR  = 0x03; /* ¥ê¥Õ¥ì¥Ã¥·¥å¼þ´ü¤òû¤á¤ËÀßÄê */
+  *H8_3069F_RTMCSR = 0x37;
+  *H8_3069F_DRCRB  = 0x9f; /* ¥¦¥¨¥¤¥ÈÁÞÆþ */
+  *H8_3069F_DRCRA  = 0x20;
+
+  *H8_3069F_P1DDR  = 0xff;
+  *H8_3069F_P2DDR  = 0x07;
+  *H8_3069F_P8DDR  = 0xee;
+  *H8_3069F_PBDDR  = 0x0c;
+
+  for (i = 0; i < 200; i++) {
+    for (j = 0; j < 200; j++) {
+      asm volatile ("nop");
+    }
+  }
+
+  /*
+   * 3¥¹¥Æ¡¼¥È¥¢¥¯¥»¥¹
+   */
+  *H8_3069F_WCRH = 0xff;
+  *H8_3069F_WCRL = 0xff;
+
+  /*
+   * 3¥¹¥Æ¡¼¥È¥¢¥¯¥»¥¹
+   */
+  *H8_3069F_ASTCR = 0xff;
+
+  return 0;
+}
+
+static int check_val(volatile val_t *p, volatile val_t *wval)
+{
+  volatile val_t rval;
+
+  p->u.val8[0] = wval->u.val8[0]; p->u.val8[1] = wval->u.val8[1];
+  p->u.val8[2] = wval->u.val8[2]; p->u.val8[3] = wval->u.val8[3];
+  rval.u.val8[0] = p->u.val8[0]; rval.u.val8[1] = p->u.val8[1];
+  rval.u.val8[2] = p->u.val8[2]; rval.u.val8[3] = p->u.val8[3];
+
+  if (rval.u.val32[0] != wval->u.val32[0])
+    return -1;
+
+  p->u.val16[0] = wval->u.val16[0]; p->u.val16[1] = wval->u.val16[1];
+  rval.u.val16[0] = p->u.val16[0]; rval.u.val16[1] = p->u.val16[1];
+
+  if (rval.u.val32[0] != wval->u.val32[0])
+    return -1;
+
+  p->u.val32[0] = wval->u.val32[0];
+  rval.u.val32[0] = p->u.val32[0];
+
+  if (rval.u.val32[0] != wval->u.val32[0])
+    return -1;
+
+  return 0;
+}
+
+int dram_check()
+{
+  uint32 *p;
+  int err;
+  val_t val;
+
+  puts("DRAM checking...\n");
+
+  for (p = (uint32 *)DRAM_START; p < (uint32 *)DRAM_END; p++) {
+    putxval((unsigned long)p, 8);
+    err = 1;
+
+    val.u.val32[0] = (uint32)p;
+    if (check_val((val_t *)p, &val) < 0)
+      goto err;
+
+    val.u.val32[0] = 0;
+    if (check_val((val_t *)p, &val) < 0)
+      goto err;
+
+    val.u.val32[0] = 0xffffffffUL;
+    if (check_val((val_t *)p, &val) < 0)
+      goto err;
+
+    puts("\x08\x08\x08\x08\x08\x08\x08\x08");
+  }
+  puts("\nall check OK.\n");
+  return 0;
+
+err:
+  puts("\nERROR: ");
+  putxval((unsigned long)*p, 8);
+  puts("\n");
+  return -1;
+}
+
+static uint32 dram_check2_val0(uint32 *addr) {  return  0x55555555UL; }
+static uint32 dram_check2_val1(uint32 *addr) {  return  0xaaaaaaaaUL; }
+static uint32 dram_check2_val2(uint32 *addr) {  return  0x00000000UL; }
+static uint32 dram_check2_val3(uint32 *addr) {  return  0xffffffffUL; }
+static uint32 dram_check2_val4(uint32 *addr) {  return  (uint32)addr; }
+static uint32 dram_check2_val5(uint32 *addr) {  return ~(uint32)addr; }
+
+int dram_check2()
+{
+  uint32 *p;
+  int ret = 0, i;
+  uint32 (*getval[])(uint32 *) = {
+    dram_check2_val0,
+    dram_check2_val1,
+    dram_check2_val2,
+    dram_check2_val3,
+    dram_check2_val4,
+    dram_check2_val5,
+    NULL
+  };
+
+  for (i = 0; getval[i]; i++) {
+
+    puts("DRAM check pattern: ");
+    putxval(i, 0);
+
+    puts("\nDRAM setting...\n");
+
+    for (p = (uint32 *)DRAM_START; p < (uint32 *)DRAM_END; p++) {
+      *p = getval[i](p);
+      if (!((uint32)p & 0xfff)) {
+       putxval((unsigned long)p, 8);
+       puts("\x08\x08\x08\x08\x08\x08\x08\x08");
+      }
+    }
+
+    puts("\nDRAM checking...\n");
+
+    for (p = (uint32 *)DRAM_START; p < (uint32 *)DRAM_END; p++) {
+      if (*p != getval[i](p)) {
+       puts("\nERROR! :");
+       putxval((unsigned long)p, 8);
+       puts(" ");
+       putxval((unsigned long)*p, 8);
+       puts("\n");
+       ret = -1;
+      }
+      if (!((uint32)p & 0xfff)) {
+       putxval((unsigned long)p, 8);
+       puts("\x08\x08\x08\x08\x08\x08\x08\x08");
+      }
+    }
+
+    puts("\n");
+
+  }
+
+  if (ret == 0) {
+    puts("\nall check OK.\n");
+  }
+
+  return ret;
+}
+
+int dram_clear()
+{
+  uint32 *p;
+
+  puts("DRAM clearing...\n");
+
+  for (p = (uint32 *)DRAM_START; p < (uint32 *)DRAM_END; p++)
+    *p = 0;
+
+  puts("DRAM cleared.\n");
+
+  return 0;
+}
diff --git a/firm/06/bootload/dram.h b/firm/06/bootload/dram.h
new file mode 100644 (file)
index 0000000..b5d2d90
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _DRAM_H_INCLUDED_
+#define _DRAM_H_INCLUDED_
+
+#define DRAM_START 0x400000
+#define DRAM_END   0x600000
+
+int dram_init();
+int dram_check();
+int dram_check2();
+int dram_clear();
+
+#endif
diff --git a/firm/06/bootload/elf.c b/firm/06/bootload/elf.c
new file mode 100644 (file)
index 0000000..965d0a5
--- /dev/null
@@ -0,0 +1,94 @@
+#include "defines.h"
+#include "elf.h"
+#include "lib.h"
+
+struct elf_header {
+  struct {
+    unsigned char magic[4];
+    unsigned char class;
+    unsigned char format;
+    unsigned char version;
+    unsigned char abi;
+    unsigned char abi_version;
+    unsigned char reserve[7];
+  } id;
+  short type;
+  short arch;
+  long version;
+  long entry_point;
+  long program_header_offset;
+  long section_header_offset;
+  long flags;
+  short header_size;
+  short program_header_size;
+  short program_header_num;
+  short section_header_size;
+  short section_header_num;
+  short section_name_index;
+};
+
+struct elf_program_header {
+  long type;
+  long offset;
+  long virtual_addr;
+  long physical_addr;
+  long file_size;
+  long memory_size;
+  long flags;
+  long align;
+};
+
+/* ELF¥Ø¥Ã¥À¤Î¥Á¥§¥Ã¥¯ */
+static int elf_check(struct elf_header *header)
+{
+  if (memcmp(header->id.magic, "\x7f" "ELF", 4))
+    return -1;
+
+  if (header->id.class   != 1) return -1; /* ELF32 */
+  if (header->id.format  != 2) return -1; /* Big endian */
+  if (header->id.version != 1) return -1; /* version 1 */
+  if (header->type       != 2) return -1; /* Executable file */
+  if (header->version    != 1) return -1; /* version 1 */
+
+  /* Hitachi H8/300 or H8/300H */
+  if ((header->arch != 46) && (header->arch != 47)) return -1;
+
+  return 0;
+}
+
+/* ¥»¥°¥á¥ó¥Èñ°Ì¤Ç¤Î¥í¡¼¥É */
+static int elf_load_program(struct elf_header *header)
+{
+  int i;
+  struct elf_program_header *phdr;
+
+  for (i = 0; i < header->program_header_num; i++) {
+    /* ¥×¥í¥°¥é¥à¡¦¥Ø¥Ã¥À¤ò¼èÆÀ */
+    phdr = (struct elf_program_header *)
+      ((char *)header + header->program_header_offset +
+       header->program_header_size * i);
+
+    if (phdr->type != 1) /* ¥í¡¼¥É²Äǽ¤Ê¥»¥°¥á¥ó¥È¤«¡© */
+      continue;
+
+    memcpy((char *)phdr->physical_addr, (char *)header + phdr->offset,
+          phdr->file_size);
+    memset((char *)phdr->physical_addr + phdr->file_size, 0,
+          phdr->memory_size - phdr->file_size);
+  }
+
+  return 0;
+}
+
+char *elf_load(char *buf)
+{
+  struct elf_header *header = (struct elf_header *)buf;
+
+  if (elf_check(header) < 0) /* ELF¥Ø¥Ã¥À¤Î¥Á¥§¥Ã¥¯ */
+    return NULL;
+
+  if (elf_load_program(header) < 0) /* ¥»¥°¥á¥ó¥Èñ°Ì¤Ç¤Î¥í¡¼¥É */
+    return NULL;
+
+  return (char *)header->entry_point;
+}
diff --git a/firm/06/bootload/elf.h b/firm/06/bootload/elf.h
new file mode 100644 (file)
index 0000000..c6ed725
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _ELF_H_INCLUDED_
+#define _ELF_H_INCLUDED_
+
+char *elf_load(char *buf);
+
+#endif
diff --git a/firm/06/bootload/interrupt.c b/firm/06/bootload/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/06/bootload/interrupt.h b/firm/06/bootload/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/06/bootload/intr.S b/firm/06/bootload/intr.S
new file mode 100644 (file)
index 0000000..c8324eb
--- /dev/null
@@ -0,0 +1,107 @@
+#include "intr.h"\r
+       .h8300h\r
+       .section .text\r
+\r
+       .global _intr_softerr\r
+#      .type   _intr_softerr,@function\r
+_intr_softerr:\r
+       mov.l   er6,@-er7\r
+       mov.l   er5,@-er7\r
+       mov.l   er4,@-er7\r
+       mov.l   er3,@-er7\r
+       mov.l   er2,@-er7\r
+       mov.l   er1,@-er7\r
+       mov.l   er0,@-er7\r
+       mov.l   er7,er1\r
+       mov.l   #_intrstack,sp\r
+       mov.l   er1,@-er7\r
+       mov.w   #SOFTVEC_TYPE_SOFTERR,r0\r
+       jsr     @_interrupt\r
+       mov.l   @er7+,er1\r
+       mov.l   er1,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
+\r
+       .global _intr_syscall\r
+#      .type   _intr_syscall,@function\r
+_intr_syscall:\r
+       mov.l   er6,@-er7\r
+       mov.l   er5,@-er7\r
+       mov.l   er4,@-er7\r
+       mov.l   er3,@-er7\r
+       mov.l   er2,@-er7\r
+       mov.l   er1,@-er7\r
+       mov.l   er0,@-er7\r
+       mov.l   er7,er1\r
+       mov.l   #_intrstack,sp\r
+       mov.l   er1,@-er7\r
+       mov.w   #SOFTVEC_TYPE_SYSCALL,r0\r
+       jsr     @_interrupt\r
+       mov.l   @er7+,er1\r
+       mov.l   er1,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
+\r
+       .global _intr_serintr\r
+#      .type   _intr_serintr,@function\r
+_intr_serintr:\r
+       mov.l   er6,@-er7\r
+       mov.l   er5,@-er7\r
+       mov.l   er4,@-er7\r
+       mov.l   er3,@-er7\r
+       mov.l   er2,@-er7\r
+       mov.l   er1,@-er7\r
+       mov.l   er0,@-er7\r
+       mov.l   er7,er1\r
+       mov.l   #_intrstack,sp\r
+       mov.l   er1,@-er7\r
+       mov.w   #SOFTVEC_TYPE_SERINTR,r0\r
+       jsr     @_interrupt\r
+       mov.l   @er7+,er1\r
+       mov.l   er1,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
+\r
+       .global _intr_timintr\r
+#      .type   _intr_timintr,@function\r
+_intr_timintr:\r
+       mov.l   er6,@-er7\r
+       mov.l   er5,@-er7\r
+       mov.l   er4,@-er7\r
+       mov.l   er3,@-er7\r
+       mov.l   er2,@-er7\r
+       mov.l   er1,@-er7\r
+       mov.l   er0,@-er7\r
+       mov.l   er7,er1\r
+       mov.l   #_intrstack,sp\r
+       mov.l   er1,@-er7\r
+       mov.w   #SOFTVEC_TYPE_TIMINTR,r0\r
+       jsr     @_interrupt\r
+       mov.l   @er7+,er1\r
+       mov.l   er1,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/06/bootload/intr.h b/firm/06/bootload/intr.h
new file mode 100644 (file)
index 0000000..d31c9a0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _INTR_H_INCLUDED_
+#define _INTR_H_INCLUDED_
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÄêµÁ */
+
+#define SOFTVEC_TYPE_NUM     4
+
+#define SOFTVEC_TYPE_SOFTERR 0
+#define SOFTVEC_TYPE_SYSCALL 1
+#define SOFTVEC_TYPE_SERINTR 2
+#define SOFTVEC_TYPE_TIMINTR 3
+
+#endif
diff --git a/firm/06/bootload/lcd.c b/firm/06/bootload/lcd.c
new file mode 100644 (file)
index 0000000..0392bc5
--- /dev/null
@@ -0,0 +1,398 @@
+#include "lcd.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 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 lcd_init(void)
+{
+  *H8_3069F_P4DDR = BIT_LCD_RES;
+
+  /*
+   * 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 lcd_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 lcd_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 lcd_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) {
+        lcd_set_pixel(y, x, 0);
+      } else {
+        lcd_set_pixel(y, x, 1);
+      }
+    } else {
+      if (reverse) {
+        lcd_set_pixel(x, y, 0);
+      } else {
+        lcd_set_pixel(x, y, 1);
+      }
+    }
+    error = error - deltay;
+    if (error < 0) {
+      y = y + ystep;
+      error = error + deltax;
+    }
+  }
+}
+
+void lcd_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
+{
+  int x, y;
+  for (x = x1; x <= x2; x++) {
+    if (reverse) {
+      lcd_set_pixel(x, y1, 0);
+      lcd_set_pixel(x, y2, 0);
+    } else {
+      lcd_set_pixel(x, y1, 1);
+      lcd_set_pixel(x, y2, 1);
+    }
+  }
+  for (y = y1; y <= y2; y++) {
+    if (reverse) {
+      lcd_set_pixel(x1, y, 0);
+      lcd_set_pixel(x2, y, 0);
+    } else {
+      lcd_set_pixel(x1, y, 1);
+      lcd_set_pixel(x2, y, 1);
+    }
+  }
+}
+
+void lcd_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) {
+        lcd_set_pixel(x, y, 0);
+      } else {
+        lcd_set_pixel(x, y, 1);
+      }
+    }
+  }
+}
+
+void lcd_draw_string(uint8 x, uint8 y, char *str, uint8 reverse)
+{
+  char *p = str;
+  int cnt = 0;
+  while (*p) {
+    lcd_draw_char(x + (FONT_X * cnt), y, *p, reverse);
+    p++;
+    cnt++;
+  }
+}
+
+void lcd_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) {
+            lcd_set_pixel(x + i, y + j, 0);
+          } else {
+            lcd_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            lcd_set_pixel(x + i, y + j, 1);
+          } else {
+            lcd_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) {
+            lcd_set_pixel(x + i, y + j, 0);
+          } else {
+            lcd_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            lcd_set_pixel(x + i, y + j, 1);
+          } else {
+            lcd_set_pixel(x + i, y + j, 0);
+          }
+        }
+      }
+    }
+  }
+}
+
+void lcd_draw_checkbox(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 state, uint8 reverse)
+{
+  lcd_draw_box(x1, y1, x2, y2, reverse);
+  if (state) {
+    lcd_draw_line(x1, y1, x2, y2, reverse);
+    lcd_draw_line(x1, y2, x2, y1, reverse);
+  }
+}
+
+void lcd_draw_progressbar(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse)
+{
+  lcd_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;
+  lcd_fill_box(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
+  lcd_fill_box(x1 + pix, y1 + 1, x2 - 1, y2 - 1, !reverse);
+}
+
diff --git a/firm/06/bootload/lcd.h b/firm/06/bootload/lcd.h
new file mode 100644 (file)
index 0000000..4092c20
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _LCD_H_INCLUDED_
+#define _LCD_H_INCLUDED_
+
+#include "defines.h"
+
+void lcd_init(void);
+void lcd_clear(void);
+void lcd_set_pixel(int x, int y, int reverse);
+void lcd_draw_line(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_fill_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_draw_string(uint8 x, uint8 y, char *str, uint8 reverse);
+void lcd_draw_char(uint8 x, uint8 y, char c, uint8 reverse);
+void lcd_draw_checkbox(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 state, uint8 reverse);
+void lcd_draw_progressbar(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse);
+
+#endif
+
diff --git a/firm/06/bootload/ld.scr b/firm/06/bootload/ld.scr
new file mode 100644 (file)
index 0000000..4ce149c
--- /dev/null
@@ -0,0 +1,75 @@
+/* OUTPUT_FORMAT("elf32-h8300") */
+OUTPUT_ARCH(h8300h)
+ENTRY("_start")
+
+MEMORY
+{
+       /* internal ROM (512KB) */
+       romall(rx)      : o = 0x000000, l = 0x080000 /* 512KB */
+       vectors(r)      : o = 0x000000, l = 0x000100 /* top of ROM */
+       rom(rx)         : o = 0x000100, l = 0x07ff00
+
+       /* DRAM (2MB) */
+       dramall(rwx)    : o = 0x400000, l = 0x200000 /* 2MB */
+       buffer(rwx)     : o = 0x500000, l = 0x100000 /* 1MB */
+
+       /* internal RAM (16KB) */
+       ramall(rwx)     : o = 0xffbf20, l = 0x004000 /* 16KB */
+       softvec(rw)     : o = 0xffbf20, l = 0x000040 /* top of RAM */
+       data(rwx)       : o = 0xffc000, l = 0x003f00
+       bootstack(rw)   : o = 0xffff00, l = 0x000000
+       intrstack(rw)   : o = 0xffff00, l = 0x000000 /* end of RAM */
+}
+
+SECTIONS
+{
+       .vectors : {
+               vector.o(.data)
+       } > vectors
+
+       .text : {
+               _text_start = . ;
+               *(.text)
+               _etext = . ;
+       } > rom
+
+       .rodata : {
+               _rodata_start = . ;
+               *(.strings)
+               *(.rodata)
+               *(.rodata.*)
+               _erodata = . ;
+       } > rom
+
+       .softvec : {
+               _softvec = .;
+       } > softvec
+
+       .buffer : {
+               _buffer_start = . ;
+       } > buffer
+
+       .data : {
+               _data_start = . ;
+               *(.data)
+               _edata = . ;
+       } > data AT> rom
+
+       .bss : {
+               _bss_start = . ;
+               *(.bss)
+               *(COMMON)
+               _ebss = . ;
+       } > data AT> rom
+
+       . = ALIGN(4);
+       _end = . ;
+
+       .bootstack : {
+               _bootstack = .;
+       } > bootstack
+
+       .intrstack : {
+               _intrstack = .;
+       } > intrstack
+}
diff --git a/firm/06/bootload/led.c b/firm/06/bootload/led.c
new file mode 100644 (file)
index 0000000..f918d3a
--- /dev/null
@@ -0,0 +1,99 @@
+#include "led.h"
+#include "defines.h"
+
+#define H8_3069F_PADDR  ((volatile uint8 *)0xFEE009)
+#define H8_3069F_PADR   ((volatile uint8 *)0xFFFFD9)
+
+#define MASK_LEDG   (1 << 2)
+#define MASK_LEDR   (1 << 3)
+#define MASK_LED1   (1 << 6)
+#define MASK_LED2   (1 << 7)
+
+int led_init(void)
+{
+  volatile uint8 mask = MASK_LED1 | MASK_LED2 | MASK_LEDG | MASK_LEDR;
+
+  /*
+   * ¥Ý¡¼¥È¥Ç¥£¥ì¥¯¥·¥ç¥ó¤òÀßÄꤹ¤ëÁ°¤Ë¥Ç¡¼¥¿¥ì¥¸¥¹¥¿¤ò½é´ü²½¤¹¤ë¡£
+   * ÉéÏÀÍý¤Ê¤Î¤Ç¡¢½é´üÃͤΥ¼¥í¤À¤È½ÐÎϤˤ·¤¿»þÅÀ¤ÇÅÀÅô¾õÂ֤Ȥʤ롣
+   */
+  *H8_3069F_PADR |= mask;
+
+  /*
+   * ¥Ý¡¼¥ÈA¤Î¥Ó¥Ã¥È2,3,6,7¤Ï½ÐÎϥݡ¼¥È¤È¤·¤ÆÀßÄꤹ¤ë¡£
+   *
+   * ¥Ç¡¼¥¿¥Ç¥£¥ì¥¯¥·¥ç¥ó¥ì¥¸¥¹¥¿¤ÏWrite Only¤Ê¤Î¤Ç¡¢
+   * Â¾¤Î¥Ó¥Ã¥È¤ÎÀßÄ꤬ɬÍפˤʤä¿»þÅÀ¤Ç¡¢
+   * ¥Ý¡¼¥ÈÆþ½ÐÎÏÀßÄê¤ò¤Þ¤È¤á¤Æ´ÉÍý¤¹¤ë¤è¤¦¤Ê
+   * ²¿¤é¤«¤ÎÂкö¤¬É¬ÍפȤʤë¤À¤í¤¦¡£
+   */
+  *H8_3069F_PADDR = 0xCC;
+
+  return 0;
+}
+
+int led_write(led_target_t target, led_state_t state)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = MASK_LED1;
+      break;
+    case Led2:
+      mask = MASK_LED2;
+      break;
+    case LedG:
+      mask = MASK_LEDG;
+      break;
+    case LedR:
+      mask = MASK_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  switch (state) {
+    case LedOn:
+      *H8_3069F_PADR &= ~mask;
+      break;
+    case LedOff:
+      *H8_3069F_PADR |= mask;
+      break;
+    default:
+      return -1;
+  }
+
+  return 0;
+}
+
+int led_toggle(led_target_t target)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = MASK_LED1;
+      break;
+    case Led2:
+      mask = MASK_LED2;
+      break;
+    case LedG:
+      mask = MASK_LEDG;
+      break;
+    case LedR:
+      mask = MASK_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  if (*H8_3069F_PADR & mask) {
+    *H8_3069F_PADR &= ~mask;
+  } else {
+    *H8_3069F_PADR |= mask;
+  }
+
+  return 0;
+}
+
diff --git a/firm/06/bootload/led.h b/firm/06/bootload/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/06/bootload/lib.c b/firm/06/bootload/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/06/bootload/lib.h b/firm/06/bootload/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/06/bootload/main.c b/firm/06/bootload/main.c
new file mode 100644 (file)
index 0000000..3fbbbe1
--- /dev/null
@@ -0,0 +1,157 @@
+#include "defines.h"
+#include "interrupt.h"
+#include "serial.h"
+#include "xmodem.h"
+#include "elf.h"
+#include "dram.h"
+#include "lib.h"
+#include "led.h"
+#include "re.h"
+#include "sw.h"
+#include "lcd.h"
+
+static int init(void)
+{
+  /* °Ê²¼¤Ï¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÇÄêµÁ¤·¤Æ¤¢¤ë¥·¥ó¥Ü¥ë */
+  extern int erodata, data_start, edata, bss_start, ebss;
+
+  /*
+   * ¥Ç¡¼¥¿Îΰè¤ÈBSSÎΰè¤ò½é´ü²½¤¹¤ë¡¥¤³¤Î½èÍý°Ê¹ß¤Ç¤Ê¤¤¤È¡¤
+   * ¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤¬½é´ü²½¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤ÇÃí°Õ¡¥
+   */
+  memcpy(&data_start, &erodata, (long)&edata - (long)&data_start);
+  memset(&bss_start, 0, (long)&ebss - (long)&bss_start);
+
+  /* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¤ê¹þ¤ß¥Ù¥¯¥¿¤ò½é´ü²½¤¹¤ë */
+  softvec_init();
+
+  /* ¥·¥ê¥¢¥ë¤Î½é´ü²½ */
+  serial_init(SERIAL_DEFAULT_DEVICE);
+
+  /* DRAM¤Î½é´ü²½ */
+  dram_init();
+
+  /* LED¤Î½é´ü²½ */
+  led_init();
+
+  /* ¥í¡¼¥¿¥ê¡¼¥¨¥ó¥³¡¼¥À¡¼¤Î½é´ü²½ */
+  re_init();
+
+  /* ¥¹¥¤¥Ã¥Á¤Î½é´ü²½ */
+  sw_init();
+
+  /* LCD¤Î½é´ü²½ */
+  lcd_init();
+
+  return 0;
+}
+
+/* ¥á¥â¥ê¤Î16¿Ê¥À¥ó¥×½ÐÎÏ */
+static int dump(char *buf, long size)
+{
+  long i;
+
+  if (size < 0) {
+    puts("no data.\n");
+    return -1;
+  }
+  for (i = 0; i < size; i++) {
+    putxval(buf[i], 2);
+    if ((i & 0xf) == 15) {
+      puts("\n");
+    } else {
+      if ((i & 0xf) == 7) puts(" ");
+      puts(" ");
+    }
+  }
+  puts("\n");
+
+  return 0;
+}
+
+static void wait()
+{
+  volatile long i;
+  for (i = 0; i < 300000; i++)
+    ;
+}
+
+int main(void)
+{
+  static char buf[16];
+  static long size = -1;
+  static unsigned char *loadbuf = NULL;
+  char *entry_point;
+  void (*f)(void);
+  extern int buffer_start; /* ¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥Ð¥Ã¥Õ¥¡ */
+
+  INTR_DISABLE; /* ³ä¹þ¤ß̵¸ú¤Ë¤¹¤ë */
+
+  init();
+
+  puts("kzload (kozos boot loader) started.\n");
+
+  while (1) {
+    puts("kzload> "); /* ¥×¥í¥ó¥×¥Èɽ¼¨ */
+    gets(buf); /* ¥·¥ê¥¢¥ë¤«¤é¤Î¥³¥Þ¥ó¥É¼õ¿® */
+
+    if (!strcmp(buf, "load")) { /* XMODEM¤Ç¤Î¥Õ¥¡¥¤¥ë¤Î¥À¥¦¥ó¥í¡¼¥É */
+      loadbuf = (char *)(&buffer_start);
+      size = xmodem_recv(loadbuf);
+      wait(); /* Å¾Á÷¥¢¥×¥ê¤¬½ªÎ»¤·Ã¼Ëö¥¢¥×¥ê¤ËÀ©¸æ¤¬Ìá¤ë¤Þ¤ÇÂÔ¤Á¹ç¤ï¤»¤ë */
+      if (size < 0) {
+       puts("\nXMODEM receive error!\n");
+      } else {
+       puts("\nXMODEM receive succeeded.\n");
+      }
+    } else if (!strcmp(buf, "dump")) { /* ¥á¥â¥ê¤Î16¿Ê¥À¥ó¥×½ÐÎÏ */
+      puts("size: ");
+      putxval(size, 0);
+      puts("\n");
+      dump(loadbuf, size);
+    } else if (!strcmp(buf, "run")) { /* ELF·Á¼°¥Õ¥¡¥¤¥ë¤Î¼Â¹Ô */
+      entry_point = elf_load(loadbuf); /* ¥á¥â¥ê¾å¤ËŸ³«(¥í¡¼¥É) */
+      if (!entry_point) {
+       puts("run error!\n");
+      } else {
+       puts("starting from entry point: ");
+       putxval((unsigned long)entry_point, 0);
+       puts("\n");
+       f = (void (*)(void))entry_point;
+       f(); /* ¤³¤³¤Ç¡¤¥í¡¼¥É¤·¤¿¥×¥í¥°¥é¥à¤Ë½èÍý¤òÅϤ¹ */
+       /* ¤³¤³¤Ë¤ÏÊ֤äƤ³¤Ê¤¤ */
+      }
+    } else if (!strcmp(buf, "ramchk")) {
+      dram_check();
+    } else if (!strcmp(buf, "ramchk2")) {
+      dram_check2();
+    } else if (!strcmp(buf, "ramclr")) {
+      dram_clear();
+    } else if (!strcmp(buf, "led1")) {
+      led_toggle(Led1);
+    } else if (!strcmp(buf, "led2")) {
+      led_toggle(Led2);
+    } else if (!strcmp(buf, "ledg")) {
+      led_toggle(LedG);
+    } else if (!strcmp(buf, "ledr")) {
+      led_toggle(LedR);
+    } else if (!strcmp(buf, "re")) {
+      puts("value: ");
+      putxval(re_read(), 0);
+      puts("\n");
+    } else if (!strcmp(buf, "sw")) {
+      if (sw_read(Sw1)) {   puts("Sw1\n"); }
+      if (sw_read(Sw2)) {   puts("Sw2\n"); }
+      if (sw_read(SwRe)) {  puts("SwRe\n"); }
+    } else if (!strcmp(buf, "lcd")) {
+      uint8 reverse = 0;
+      lcd_clear();
+      lcd_draw_box(0, 0, 121, 31, reverse);
+      lcd_draw_string(2, 2, "KOZOS", reverse);
+    } else {
+      puts("unknown.\n");
+    }
+  }
+
+  return 0;
+}
diff --git a/firm/06/bootload/re.c b/firm/06/bootload/re.c
new file mode 100644 (file)
index 0000000..af73317
--- /dev/null
@@ -0,0 +1,23 @@
+#include "re.h"
+
+#define H8_3069F_TMDR       ((volatile uint8 *)0xFFFF62)
+#define H8_3069F_TSTR       ((volatile uint8 *)0xFFFF60)
+#define H8_3069F_16TCNT2H   ((volatile uint8 *)0xFFFF7A)
+#define H8_3069F_16TCNT2L   ((volatile uint8 *)0xFFFF7B)
+
+#define TMDR_BIT_MDF    (1 << 6)
+#define TSTR_BIT_STR2   (1 << 2)
+
+int re_init(void)
+{
+  *H8_3069F_TMDR = TMDR_BIT_MDF;
+  *H8_3069F_TSTR = TSTR_BIT_STR2;
+
+  return 0;
+}
+
+uint16 re_read(void)
+{
+  return ((*H8_3069F_16TCNT2H) << 8) | (*H8_3069F_16TCNT2L << 0);
+}
+
diff --git a/firm/06/bootload/re.h b/firm/06/bootload/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/06/bootload/serial.c b/firm/06/bootload/serial.c
new file mode 100644 (file)
index 0000000..1f30bbf
--- /dev/null
@@ -0,0 +1,112 @@
+#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;
+}
diff --git a/firm/06/bootload/serial.h b/firm/06/bootload/serial.h
new file mode 100644 (file)
index 0000000..27a5c20
--- /dev/null
@@ -0,0 +1,10 @@
+#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);        /* £±Ê¸»ú¼õ¿® */
+
+#endif
diff --git a/firm/06/bootload/startup.s b/firm/06/bootload/startup.s
new file mode 100644 (file)
index 0000000..8ba4038
--- /dev/null
@@ -0,0 +1,10 @@
+       .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
diff --git a/firm/06/bootload/sw.c b/firm/06/bootload/sw.c
new file mode 100644 (file)
index 0000000..391b26d
--- /dev/null
@@ -0,0 +1,31 @@
+#include "sw.h"
+
+#define H8_3069F_P7DR   ((volatile uint8 *)0xFFFFD6)
+#define H8_3069F_PADR   ((volatile uint8 *)0xFFFFD9)
+
+#define SW_BIT_P7_SW1   (1 << 0)
+#define SW_BIT_P7_SW2   (1 << 1)
+#define SW_BIT_PA_SWRE  (1 << 4)
+
+int sw_init(void)
+{
+  return 0;
+}
+
+uint8 sw_read(sw_target_t target)
+{
+  uint8 c = 0;
+  switch (target) {
+    case Sw1:
+      c = (*H8_3069F_P7DR & SW_BIT_P7_SW1) ? 0 : 1;
+      break;
+    case Sw2:
+      c = (*H8_3069F_P7DR & SW_BIT_P7_SW2) ? 0 : 1;
+      break;
+    case SwRe:
+      c = (*H8_3069F_PADR & SW_BIT_PA_SWRE) ? 0 : 1;
+      break;
+  }
+  return c;
+}
+
diff --git a/firm/06/bootload/sw.h b/firm/06/bootload/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/06/bootload/vector.c b/firm/06/bootload/vector.c
new file mode 100644 (file)
index 0000000..3ddd93b
--- /dev/null
@@ -0,0 +1,25 @@
+#include "defines.h"
+
+extern void start(void);        /* ¥¹¥¿¡¼¥È¡¦¥¢¥Ã¥× */
+extern void intr_softerr(void); /* ¥½¥Õ¥È¥¦¥¨¥¢¡¦¥¨¥é¡¼ */
+extern void intr_syscall(void); /* ¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë */
+extern void intr_serintr(void); /* ¥·¥ê¥¢¥ë³ä¹þ¤ß */
+extern void intr_timintr(void); /* ¥¿¥¤¥Þ³ä¹þ¤ß */
+
+/*
+ * ³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÀßÄê¡¥
+ * ¥ê¥ó¥«¡¦¥¹¥¯¥ê¥×¥È¤ÎÄêµÁ¤Ë¤è¤ê¡¤ÀèƬÈÖÃϤËÇÛÃÖ¤µ¤ì¤ë¡¥
+ */
+void (*vectors[])(void) = {
+  start, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 
+  intr_syscall, intr_softerr, intr_softerr, intr_softerr,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  intr_timintr, intr_timintr, intr_timintr, intr_timintr,
+  intr_timintr, intr_timintr, intr_timintr, intr_timintr,
+  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+  intr_serintr, intr_serintr, intr_serintr, intr_serintr,
+};
diff --git a/firm/06/bootload/xmodem.c b/firm/06/bootload/xmodem.c
new file mode 100644 (file)
index 0000000..dfde193
--- /dev/null
@@ -0,0 +1,94 @@
+#include "defines.h"
+#include "serial.h"
+#include "lib.h"
+#include "xmodem.h"
+
+#define XMODEM_SOH 0x01
+#define XMODEM_STX 0x02
+#define XMODEM_EOT 0x04
+#define XMODEM_ACK 0x06
+#define XMODEM_NAK 0x15
+#define XMODEM_CAN 0x18
+#define XMODEM_EOF 0x1a /* Ctrl-Z */
+
+#define XMODEM_BLOCK_SIZE 128
+
+/* ¼õ¿®³«»Ï¤µ¤ì¤ë¤Þ¤ÇÁ÷¿®Í×µá¤ò½Ð¤¹ */
+static int xmodem_wait(void)
+{
+  long cnt = 0;
+
+  while (!serial_is_recv_enable(SERIAL_DEFAULT_DEVICE)) {
+    if (++cnt >= 2000000) {
+      cnt = 0;
+      serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_NAK);
+    }
+  }
+
+  return 0;
+}
+
+/* ¥Ö¥í¥Ã¥¯Ã±°Ì¤Ç¤Î¼õ¿® */
+static int xmodem_read_block(unsigned char block_number, char *buf)
+{
+  unsigned char c, block_num, check_sum;
+  int i;
+
+  block_num = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+  if (block_num != block_number)
+    return -1;
+
+  block_num ^= serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+  if (block_num != 0xff)
+    return -1;
+
+  check_sum = 0;
+  for (i = 0; i < XMODEM_BLOCK_SIZE; i++) {
+    c = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+    *(buf++) = c;
+    check_sum += c;
+  }
+
+  check_sum ^= serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+  if (check_sum)
+    return -1;
+
+  return i;
+}
+
+long xmodem_recv(char *buf)
+{
+  int r, receiving = 0;
+  long size = 0;
+  unsigned char c, block_number = 1;
+
+  while (1) {
+    if (!receiving)
+      xmodem_wait(); /* ¼õ¿®³«»Ï¤µ¤ì¤ë¤Þ¤ÇÁ÷¿®Í×µá¤ò½Ð¤¹ */
+
+    c = serial_recv_byte(SERIAL_DEFAULT_DEVICE);
+
+    if (c == XMODEM_EOT) { /* ¼õ¿®½ªÎ» */
+      serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_ACK);
+      break;
+    } else if (c == XMODEM_CAN) { /* ¼õ¿®ÃæÃÇ */
+      return -1;
+    } else if (c == XMODEM_SOH) { /* ¼õ¿®³«»Ï */
+      receiving++;
+      r = xmodem_read_block(block_number, buf); /* ¥Ö¥í¥Ã¥¯Ã±°Ì¤Ç¤Î¼õ¿® */
+      if (r < 0) { /* ¼õ¿®¥¨¥é¡¼ */
+       serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_NAK);
+      } else { /* Àµ¾ï¼õ¿® */
+       block_number++;
+       size += r;
+       buf  += r;
+       serial_send_byte(SERIAL_DEFAULT_DEVICE, XMODEM_ACK);
+      }
+    } else {
+      if (receiving)
+       return -1;
+    }
+  }
+
+  return size;
+}
diff --git a/firm/06/bootload/xmodem.h b/firm/06/bootload/xmodem.h
new file mode 100644 (file)
index 0000000..c090f17
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _XMODEM_H_INCLUDED_
+#define _XMODEM_H_INCLUDED_
+
+long xmodem_recv(char *buf);
+
+#endif
diff --git a/firm/06/os/KL-01 b/firm/06/os/KL-01
new file mode 100644 (file)
index 0000000..335ecb7
--- /dev/null
@@ -0,0 +1,117 @@
+Àî¹çƲ¥é¥¤¥»¥ó¥¹-01  ver.1.0
+                                                  2000.12.30  H.Kawai (Àî¹ç½¨¼Â)
+                                                  2007.10.07 ¥ê¥ó¥¯½¤Àµ:¤¢¤Ã¤­¤£
+
+£°¡¥³µÍ×
+
+  Ê¿¤¿¤¯¸À¤¦¤È¡¢¡Ö¥Õ¥ê¡¼¥½¥Õ¥È¤Ç¤¹¡£»ÈÍÑÁ°»ÈÍѸå¤ËÂвÁ¤ò»Ùʧ¤¦¤³¤È¤Ê¤¯¡¢¼«Í³¤Ë»È
+¤¨¤Þ¤¹¡£¥³¥Ô¡¼¤·¤Æ¤â¤¤¤¤¤Ç¤¹¡£²þÊѤ·¤Æ¤â¤¤¤¤¤Ç¤¹¡£¾¦¶ÈÍøÍѤ·¤Æ¤â¤¤¤¤¤Ç¤¹¡£¤Ç¤â¥Ð
+¥°¤Ê¤É¤Ç»³²¤¬½Ð¤Æ¤âÀÕǤ¤Ï¤È¤ì¤Þ¤»¤ó¡£¡×¤Ã¤Æ¤³¤È¤Ç¤¹¡£
+
+  ÍøÍѼԤä²þÊѤ·¤¿¤ê»²¹Í¤Ë¤·¤¿¤ê¤¹¤ë¿Í¤ÎÍø±×¤Î¤¿¤á¤Ë¡¢¥×¥í¥°¥é¥àÃæ¤Ç»È¤Ã¤Æ¤¤¤ë¥¢
+¥ë¥´¥ê¥º¥à¤ÇÃøºî¼Ô¤¬¾­ÍèÆõö¤ò¤È¤ë¤³¤È¤¬¤¢¤Ã¤Æ¤â¡¢ÆõöÎÁ¤òÍ׵ᤷ¤¿¤ê¤Ï¤·¤Ê¤¤¤È¤¤
+¤¦Êݾڤ⤢¤ê¤Þ¤¹¡£
+
+£±¡¥ÌÜŪ
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤ÇÄ󶡤µ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Ï¡¢¾¯¤·¤Ç¤â¿¤¯¤Î¿Í¤ËÍø±×¤ò¤â¤¿¤é¤·¡¢¥½
+¥Õ¥È¥¦¥§¥¢µ»½Ñ¤Î¿ÊÊâ¤Ë¾¯¤·¤Ç¤â¹×¸¥¤Ç¤­¤ì¤Ð¤È¤¤¤¦ÌÜŪ¤Ç¸ø³«¤¹¤ë¡£
+
+£²¡¥¼ñ»Ý
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤Ï¡¢Ãøºî¸¢¤òÊü´þ¤¹¤ë¤â¤Î¤Ç¤Ï¤Ê¤¤¡ÊÆÈÀêŪ¤Ë¥³¥Ô¡¼¤¹¤ë¸¢Íø¤ÏÊü´þ¤·
+¤Æ¤¤¤ë¡Ë¡£ÍøÍѼԤϤ³¤Î¥½¥Õ¥È¥¦¥§¥¢¤Î°ìÉô¤Þ¤¿¤ÏÁ´Éô¤ò¼«Í³¤Ë¥³¥Ô¡¼¤·¡¢ºÆÇÛÉÛ¤¹¤ë¤³
+¤È¤¬¤Ç¤­¤ë¡£ÍøÍѤ˺ݤ·¤ÆÂвÁ¤òÍ׵ᤷ¤Ê¤¤¡£²òÀÏ¡¢²þÊѤâÂвÁ¤Ê¤·¤Ëǧ¤á¤ë¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤ÎÍøÍѤˤĤ¤¤Æ¡¢¾¦¶ÈŪ¤ÊÍøÍѤâ̵¾ò·ï¤Çǧ
+¤á¤ë¡£¤½¤Î¤Þ¤ÞÍ­½þ¤ÇÈÎÇ䤷¤Æ¤â¹½¤ï¤Ê¤¤¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Î°ìÉô¤Þ¤¿¤ÏÁ´Éô¤ò¸µ¤Ë¤·¤ÆºîÀ®¤µ¤ì¤¿¥½¥Õ
+¥È¥¦¥§¥¢¡Ê°Ê¹ß¡¢ÇÉÀ¸Êª¤È¾Î¤¹¤ë¡Ë¤ËÂФ·¡¢¤É¤ó¤Ê¥é¥¤¥»¥ó¥¹¤òÉÕÍ¿¤·¤Æ¤â¤è¤¤¡£¤¹¤Ê¤ï
+¤Á¡¢ÇÉÀ¸Êª¤¬¥³¥Ô¡¼¶Ø»ß¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¤·¡¢ÇÉÀ¸Êª¤¬Í­½þ¤Ç¤·¤«ÇÛÉÛ¤µ¤ì¤Ê¤¯¤Æ¤â¹½¤ï¤Ê
+¤¤¡£¤â¤Á¤í¤ó̵½þ¤Ç¤¢¤Ã¤Æ¤â¤è¤¤¡£ÇÉÀ¸Êª¤ËÂФ¹¤ëÃøºî¸¢¤Ï¡¢ÇÉÀ¸Êª¤òÀ¸À®¤·¤¿¼Ô¤Ëµ¢¤·
+¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤¬ÇÉÀ¸Êª¤ËÂФ·¤ÆÃøºî¸¢¤ò¼çÄ¥¤¹¤ë
+¤³¤È¤Ï¤Ê¤¤¡£
+
+  ÇÉÀ¸Êª¤Î¥É¥­¥å¥á¥ó¥ÈÃæ¤Ë¡¢¸µ¤Ë¤·¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤ò¾Ò²ð¤¹¤ëµÁ̳¤Ï¤Ê¤¤¡£¤³
+¤Îʸ¤Ï¡¢¤â¤Á¤í¤ó¡¢¾Ò²ð¤¹¤ë¤³¤È¤ò¶Ø»ß¤¹¤ë¤â¤Î¤Ç¤â¤Ê¤¤¡£
+
+  ÇÉÀ¸Êª¤Î¸ø³«¤ËºÝ¤·¤Æ¡¢¸µ¤Ë¤·¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¼Ô¤Ë³Îǧ¤ò¼è¤ëµÁ̳¤Ï¤Ê¤¤¡£¤³¤Î
+ʸ¤Ï¡¢¤â¤Á¤í¤ó¡¢³Îǧ¤ò¶Ø»ß¤¹¤ë¤â¤Î¤Ç¤Ï¤Ê¤¤¡£
+
+  Ãøºî¼Ô¤Ï¡¢¥½¥Õ¥È¥¦¥§¥¢¤Î¼Á¤òÊݾڤ·¤Ê¤¤¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÇÈï³²¤òÈï
+¤Ã¤¿¤ê¡¢´üÂÔ¤·¤¿·ë²Ì¤¬ÆÀ¤é¤ì¤Ê¤¯¤Æ¤â¡¢Ãøºî¼Ô¤ÏÀÕǤ¤òÉé¤ï¤Ê¤¤¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤¬Å¬ÍѤµ¤ì¤ë¥½¥Õ¥È¥¦¥§¥¢¤Ç»È¤ï¤ì¤Æ¤¤¤ëµ»½Ñ¤Ë¤Ä¤¤¤Æ¤Ï¡¢»öÁ°¤ËÃøºî
+¼Ô¤Ëµö¤µ¤ì¤¿¼Ô°Ê³°¤¬Æõö¤ò¼èÆÀ¤¹¤ë¤³¤È¤Ï¶Ø»ß¤¹¤ë¡£¿·¤¿¤Êµ»½Ñ¤ò²Ã¤¨¤¿ÇÉÀ¸Êª¤òÀ¸À®
+¤·¡¢¤½¤ÎÄɲ䵤줿Éôʬ¤ÎÆõö¤ò¤È¤ë¤³¤È¤Ïǧ¤á¤ë¡£Ãøºî¼Ô¤¬¥½¥Õ¥È¥¦¥§¥¢Ãæ¤Îµ»½Ñ¤ËÂÐ
+¤·¤Æ¸å¤«¤éÆõö¤ò¤È¤ë¤³¤È¤Ï¤¢¤ê¤¦¤ë¤¬¡¢ÇÉÀ¸Êª¤ä¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÎÍøÍѤËÂФ·¤ÆÆõö
+ÎÁ¤ä¤½¤Î¾¤ÎÂвÁ¤òµá¤á¤ë¤³¤È¤Ï¤Ê¤¤¤³¤È¤òÊݾڤ¹¤ë¡£¤³¤ÎÊݾڤϡ¢Æõö¼èÆÀÁ°¤ËÀ¸À®¤µ
+¤ì¤¿ÇÉÀ¸Êª¤À¤±¤Ç¤Ê¤¯¡¢Æõö¼èÆÀ¸å¤ËÀ¸À®¤µ¤ì¤¿ÇÉÀ¸Êª¤Ë¤âŬÍѤµ¤ì¤ë¡£
+
+  ²òÀÏ·ë²Ì¤ò¤Þ¤È¤á¤ÆÆõö¤ò¤È¤ë¤³¤È¤Ë¤Ï»öÁ°¤ÎÃøºî¼Ô¤Îµö²Ä¤¬É¬ÍפÀ¤«¡¢Æõö¤ò¤È¤ë¤³
+¤È°Ê³°¤Ë¤Ä¤¤¤Æ¤Ï²¿¤éÀ©¸Â¤Ï¤Ê¤¤¡£
+
+£³¡¥Êä­
+
+  ´ðËÜŪ¤Ë¡¢¥³¥Ô¡¼¤ÏÂç´¿·Þ¤Ç¤¹¡£¤â¤·¡¢Ãøºî¼Ô¤Ë²¿¤«²¸¤ò´¶¤¸¤¿¤é¡¢°ì¿Í¤Ç¤â¿¤¯¤Î¿Í
+¤Ë¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ò¤¹¤¹¤á¤Æ¡¢¥³¥Ô¡¼¤·¤Æ¤¢¤²¤Æ²¼¤µ¤¤¡£Ãøºî¼Ô¤Ï¿¤¯¤Î¿Í¤Ë»È¤Ã¤Æ¤â
+¤é¤¤¤¿¤¤¤È»×¤Ã¤Æ¤¤¤ë¤Î¤Ç¡¢¥³¥Ô¡¼¤¹¤ì¤ÐÃøºî¼Ô¤Ï´î¤Ó¤Þ¤¹¡£¤½¤ì¤Ç¤â­¤ê¤Ê¤¤¤È´¶¤¸¤¿
+¤é¡¢À§Èó¡¢´¶ÁÛ¤òÃøºî¼Ô¤ËÁ÷¤Ã¤Æ¤¢¤²¤Æ²¼¤µ¤¤¡£¤½¤¦¤¹¤ì¤Ð¡¢¤â¤Ã¤È´î¤Ö¤Ç¤·¤ç¤¦¡£
+
+  ¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÎÃøºî¸¢¾ðÊó¤À¤±¤ò²þÊѤ·¡¢¤½¤ì¤òºÆÇÛÉÛ¤¹¤ë¤³
+¤È¤Ï¤³¤Î¥é¥¤¥»¥ó¥¹¤Ë¤è¤Ã¤Æ¶Ø»ß¤µ¤ì¤Æ¤¤¤Þ¤»¤ó¡£ÇÉÀ¸Êª°·¤¤¤Ç¤¹¡£¤³¤ì¤ÏÈ´¤±·ê¤Ç¤Ï¤Ê
+¤¤¤Ç¤¹¡£¤·¤¿¤¬¤Ã¤Æ¡¢Ãøºî¸¢¾ðÊó¤À¤±¤ò½ñ¤­´¹¤¨¤ÆºÆÇÛÉÛ¤¹¤ë¤³¤È¤¬É¬Íפʤ顢¤·¤Æ¤¤¤¿
+¤À¤¤¤Æ¤«¤Þ¤¤¤Þ¤»¤ó¡£
+
+  ¥Ð¥°¤ò¼è¤Ã¤¿¤ê¡¢µ¡Ç½¤òÄɲ䷤Ƥ¤¤¿¤À¤¯¤Î¤Ï¤â¤Á¤í¤ó¤Ç¤¹¤¬¡¢¥×¥í¥°¥é¥à¤ËÃð¼á¤òÉÕ
+¤±¤ÆÆɤߤ䤹¤¯¤·¤¿¤ê¡¢¥É¥­¥å¥á¥ó¥È¤òÊä­¤¹¤ë¤Ê¤É¡¢¤½¤¦¤¤¤¦¥Ð¥¤¥Ê¥ê¡¼¤ä¼Â¹Ô·ë²Ì¤Ë
+È¿±Ç¤µ¤ì¤Ê¤¤¤è¤¦¤Ê²þÊѤâÂç´¿·Þ¤Ç¤¹¡£¤½¤¦¤¤¤¦ÇÉÀ¸Êª¤¬¤Ç¤­¤¿¤é¡¢Ï¢Íí¤·¤Æ¤â¤é¤¨¤ë¤È
+¤¦¤ì¤·¤¤¤Ç¤¹¡ÊµÁ̳¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡Ë¡£
+
+  ²¿¤«µ¿ÌäÅÀ¤¬¤¢¤Ã¤¿¤ê¡¢ÇÉÀ¸Êª¤òºîÀ®¤¹¤ë¾å¤Ç¾ðÊó¤¬ÉÔ­¤·¤Æ¤¤¤ë¤È´¶¤¸¤¿¤é¡¢Ãøºî¼Ô
+¤ËÏ¢Íí¤ò¤È¤Ã¤Æ¼ÁÌ䤹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤¿¤À¡¢Ãøºî¼Ô¤ÎÅÔ¹ç¤Ç¤¹¤°¤Ë¤ÏÊÖ»ö¤¬¤Ç¤­¤Ê¤¤
+¤«¤â¤·¤ì¤Þ¤»¤ó¡£¤½¤ì¤Ï¤´ÍƼϤ¯¤À¤µ¤¤¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤½¤Î¤â¤Î¤ÎÉÔÈ÷¤Ê¤É¤ò»ØŦ¤¹¤ë
+¾ì¹ç¤Ï¡¢Ãøºî¼Ô¤«Àî¹çƲ¤Ë¤´Ï¢Íí¤¯¤À¤µ¤¤¡£
+
+  ¤â¤·¤«¤¹¤ë¤È¡¢¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ëµ»½Ñ¤Ë¤Ä¤¤¤Æ¡¢
+Ãøºî¼Ô¤Îµö²Ä¤Î̵¤¤¼Ô¤¬Æõö¤ò¼èÆÀ¤¹¤ë¤³¤È¤ò¶Ø¤¸¤Æ¤¤¤ë¤³¤È¤¬¡¢ÆüËܤÎÆõöË¡¤ËÄñ¿¨¤·
+¤Æ¤¤¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡Ê¤´°Õ¸«¤òÂԤäƤ¤¤Þ¤¹¡Ë¡£¤³¤ì¤Ë¤Ä¤¤¤Æ¡¢¥é¥¤¥»¥ó¥¹¤òºÇ½é¤ËÄó
+¾§¤·¤¿Àî¹ç½¨¼Â¤Î¸«²ò¤ò°Ê²¼¤Ë½ñ¤¤¤Æ¤ª¤­¤Þ¤¹¡£
+
+  ÆõöË¡¤¬À©Äꤵ¤ì¤¿Çطʤˤϡ¢È¯ÌÀ¼Ô¤¬¼«Ê¬¤ÎȯÌÀ¤Ë¤è¤ëÍø±×¤ò¼é¤ë¤¿¤á¤ËȯÌÀ¤Î¾ÜºÙ
+¤ò¸øɽ¤·¤Ê¤¤¤³¤È¤¬²Ê³Øµ»½Ñ¤Î¿ÊÊâ¤òÃ٤餻¤ë¤«¤é¡¢¸øɽ¤·¤Æ¤â¤é¤¦Âå¤ï¤ê¤Ë°ìÄê´ü´Ö¤Î
+ÆÈÀêÍøÍѤòˡŪ¤ËÊݸ¤ë¡¢¤È¤¤¤¦Àº¿À¤¬¤¢¤ê¤Þ¤¹¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤Ç¤Ï¡¢È¯ÌÀ¤Î¾ÜºÙ¤ò
+°Õ¿ÞŪ¤Ë±£¤¹¤Ä¤â¤ê¤Ï¤Ê¤¯¡¢¤·¤¿¤¬¤Ã¤ÆÆõö¤ò¼è¤ë¤³¤È¤ò¶Ø»ß¤·¤Æ¤âÆõöË¡¤ÎÀº¿À¤Ë¤ÏÈ¿
+¤·¤Æ¤¤¤Ê¤¤¤È¹Í¤¨¤Æ¤¤¤Þ¤¹¡£¤à¤·¤í¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤ÎÀº¿À¤òµâ¤Þ¤Ê¤¤¼Ô¤¬Æõö¤ò¼èÆÀ¤·
+¥ª¥ê¥¸¥Ê¥ë¤Î¥½¥Õ¥È¥¦¥§¥¢¤äÇÉÀ¸Êª¤ËÂФ·¤ÆÆõöÎÁ¤òÀÁµá¤¹¤ë¤«¤â¤·¤ì¤Ê¤¤É԰¤ÎÊý¤¬¡¢
+²Ê³Øµ»½Ñ¤Î¿ÊÊâ¤òÃ٤餻¤ë¤È¹Í¤¨¤Þ¤¹¡£¤·¤¿¤¬¤Ã¤Æ¡¢¤½¤ÎÉ԰¤ò»öÁ°¤Ëʧ¿¡¤·¤¿¤³¤Î¥é¥¤
+¥»¥ó¥¹¤ÏÆõöË¡¤ËŬ¤Ã¤¿¤â¤Î¤À¤È¹Í¤¨¤Æ¤¤¤Þ¤¹¡£
+
+  ¤â¤Á¤í¤ó¡¢°ìÈְ¿´¤Ê¤Î¤Ï¡¢¥ª¥ê¥¸¥Ê¥ë¤Î¥½¥Õ¥È¥¦¥§¥¢¤ÇȯÌÀ¤Èǧ¤á¤é¤ì¤ë¤¹¤Ù¤Æ¤Î¤â
+¤Î¤Ë¤Ä¤¤¤ÆÃøºî¼Ô¤¬Æõö¤ò¼èÆÀ¤·¤Æ¡¢Â¾¼Ô¤ÎÆõö¼èÆÀ¤ò»öÁ°¤Ë˸¤²¤ì¤Ð¤¤¤¤¤Î¤Ç¤¹¤¬¡¢¤½
+¤ì¤ÏÃøºî¼Ô¤Ë¤ÏÉéô¤Ë¤Ê¤ë¾ì¹ç¤¬¤¢¤ê¤Þ¤¹¡£¤½¤ÎÉéô¤È¥½¥Õ¥È¥¦¥§¥¢¤ò¸ø³«¤¹¤ë¤«¤É¤¦¤«
+¤òÅ·Çé¤Ë¤«¤±¤Ê¤±¤ì¤Ð¤¤¤±¤Ê¤¤¤È¤·¤¿¤é¡¢¸ø³«¤ò¤¢¤­¤é¤á¤Æ¤·¤Þ¤¦¾ì¹ç¤â¤¢¤ë¤«¤â¤·¤ì¤Þ
+¤»¤ó¡£¤½¤ì¤ÏÆõöË¡¤ÎÀº¿À¤Î´üÂÔ¤¹¤ë¤â¤Î¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¤·¡¢²æ¡¹¤ÎÌÜŪ¡Ê¡Ö£±¡¥ÌÜŪ¡×
+¤ò»²¾È¡Ë¤Ë¤â±è¤¤¤Þ¤»¤ó¡£
+
+  ¤Þ¤¿¡¢È¯ÌÀ¤Î¾ÜºÙ¤¬ÆõöË¡¤Î·Á¼°¤Ë¤è¤Ã¤Æµ­½Ò¤µ¤ì¤Æ¤¤¤Ê¤¤¤¿¤á¤ËÌÀ¤é¤«¤Ç¤Ê¤¤¾ì¹ç¡¢
+Ãøºî¼Ô°Ê³°¤Î¤â¤Î¤¬µö²Ä¤Ê¤¯¤½¤ì¤ò²òÀϤ·¤ÆÌÀ¤é¤«¤Ë¤¹¤ë¤³¤È¤Ï¡¢¤³¤Î¥é¥¤¥»¥ó¥¹¤Çǧ¤á
+¤é¤ì¤Æ¤¤¤Æ¤¤¤Þ¤¹¡£¤½¤ì¤ò̵½þ¤Ç¸ø³«¤·¤Æ¤â¤¤¤¤¤Ç¤¹¤·¡¢Í­½þ¤ÇÈÎÇ䤹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹
+¡£
+
+  ¤Ê¤ª¡¢¤³¤ì¤Ç¥é¥¤¥»¥ó¥¹¤µ¤ì¤¿¥½¥Õ¥È¥¦¥§¥¢Ãæ¤Î¤¹¤Ù¤Æ¤Îµ»½Ñ¤ËÂФ·¤Æ¡¢ÍøÍѤ˺ݤ·¤Æ
+ÆõöÎÁ¤ò»Ùʧ¤¦¿´ÇÛ¤¬Á´¤¯Ìµ¤¤¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡£¸ø³«¤Î»þÅÀ¤ÇÍ­¸ú¤ÊÆõö¤Ë¤è¤ëµ»½Ñ
+¤¬¥½¥Õ¥È¥¦¥§¥¢Æâ¤Ç»È¤ï¤ì¤Æ¤¤¤ì¤Ð¡¢¤½¤ì¤Ë¤Ä¤¤¤Æ¤ÏÆõöÊÝ»ý¼Ô¤«¤é¤ÎÆõöÎÁÍ׵᤬¤¢¤ê
+¤¨¤Þ¤¹¡£¤³¤Î¥é¥¤¥»¥ó¥¹¤¬ÆõöÎÁ¤Î¿´ÇÛ̵¤·¤ÈÊݾڤ·¤Æ¤¤¤ë¤Î¤Ï¡¢¤³¤Î¥½¥Õ¥È¥¦¥§¥¢Æâ¤Ç
+¿·¤¿¤ËȯÌÀ¤Èǧ¤á¤é¤ì¤ëµ»½Ñ¤ËÂФ·¤Æ¤Î¤ß¤Ç¤¹¡£
+
+  ¤³¤Î¥é¥¤¥»¥ó¥¹¤ò¼«Ê¬¤Î¥½¥Õ¥È¥¦¥§¥¢¤ËŬÍѤ·¤¿¤¤¤È»×¤¦Êý¤¬¤ª¤é¤ì¤Þ¤·¤¿¤é¡¢»öÁ°¡¦
+»ö¸å¤Ëµö²Ä¤òµá¤á¤ë¤³¤È¤Ê¤¯»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤«¤Þ¤¤¤Þ¤»¤ó¡£¤â¤·ÉÔÅԹ礬¤¢¤ì¤Ð¡¢¥é¥¤
+¥»¥ó¥¹Ê¸¤ò²þÊѤ·¤Æ»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤â¤¤¤¤¤Ç¤¹¡£²þÊѤκݤˤϡ¢º®Íð¤òËɤ°¤¿¤á¤Ë¥é¥¤
+¥»¥ó¥¹Ì¾¤òÊѹ¹¤¹¤ë¤Î¤ò˺¤ì¤Ê¤¤¤è¤¦¤Ë¤·¤Æ¤¯¤À¤µ¤¤¡£
+
+£´¡¥¥ê¥ó¥¯
+
+  Àî¹ç½¨¼ÂURL     http://k.osask.jp/
+       e-mail     kawai@osask.jp
diff --git a/firm/06/os/LICENSE b/firm/06/os/LICENSE
new file mode 100644 (file)
index 0000000..6128b3b
--- /dev/null
@@ -0,0 +1,6 @@
+¤³¤Î¥½¥Õ¥È¥¦¥¨¥¢¤Ïºä°æ¹°Î¼¤Ë¤è¤Ã¤ÆºîÀ®¤µ¤ì¤¿¤â¤Î¤Ç¤¢¤ê¡¤KL-01¤ÇÇÛÉÛ¤·¤Þ¤¹¡¥
+KL-01¤Ë¤Ä¤¤¤Æ¤ÏźÉդΠKL-01 ¤«¡¤¤â¤·¤¯¤Ï°Ê²¼¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+http://wiki.osask.jp/?KL-01
+
+°Ê¾å
diff --git a/firm/06/os/Makefile b/firm/06/os/Makefile
new file mode 100644 (file)
index 0000000..8d7316d
--- /dev/null
@@ -0,0 +1,68 @@
+PREFIX  = /usr/local
+ARCH    = h8300-elf
+BINDIR  = $(PREFIX)/bin
+ADDNAME = $(ARCH)-
+
+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
+
+OBJS  = startup.o main.o interrupt.o
+OBJS += lib.o serial.o timer.o
+OBJS += led.o leddrv.o
+OBJS += re.o rotenc.o
+OBJS += sw.o
+OBJS += lcd.o
+
+# sources of kozos
+OBJS += kozos.o syscall.o memory.o consdrv.o timerdrv.o command.o clock.o
+
+TARGET = kozos
+
+CFLAGS = -Wall -mh -nostdinc -nostdlib -fno-builtin
+#CFLAGS += -mint32 # int¤ò32¥Ó¥Ã¥È¤Ë¤¹¤ë¤È³Ý»»¡¿³ä»»¤¬¤Ç¤­¤Ê¤¯¤Ê¤ë
+CFLAGS += -I.
+#CFLAGS += -g
+CFLAGS += -Os
+CFLAGS += -DKOZOS
+
+LFLAGS = -static -T ld.scr -L.
+
+.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/06/os/clock.c b/firm/06/os/clock.c
new file mode 100644 (file)
index 0000000..c4b923a
--- /dev/null
@@ -0,0 +1,69 @@
+#include "defines.h"
+#include "kozos.h"
+#include "consdrv.h"
+#include "timerdrv.h"
+#include "leddrv.h"
+#include "lib.h"
+#include "sw.h"
+#include "lcd.h"
+
+/* ¥¿¥¤¥Þ¤Î¥«¥¦¥ó¥È³«»Ï¤ò¥¿¥¤¥Þ¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+static void send_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);
+}
+
+static void send_led_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);
+}
+
+static void send_led_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);
+}
+
+int clock_main(int argc, char *argv[])
+{
+  uint8 val = 0;
+
+  sw_init();
+  lcd_init();
+  lcd_clear();
+  lcd_draw_string(5, 5, "KOZOS EXPBRD #00", 0);
+
+  while (1) {
+    val = (val + 1) % 101;
+    lcd_draw_progressbar(5, 20, 121 - 5, 25, 0, 100, val, 0);
+
+    send_start(100);
+    kz_recv(MSGBOX_ID_TIMEXPIRE, NULL, NULL);
+    if (sw_read(Sw1)) {
+      send_led_write(0, 1);
+    } else {
+      send_led_toggle(0);
+    }
+
+    send_start(100);
+    kz_recv(MSGBOX_ID_TIMEXPIRE, NULL, NULL);
+    if (sw_read(Sw2)) {
+      send_led_write(1, 1);
+    } else {
+      send_led_toggle(1);
+    }
+  }
+
+  return 0;
+}
diff --git a/firm/06/os/command.c b/firm/06/os/command.c
new file mode 100644 (file)
index 0000000..13d8296
--- /dev/null
@@ -0,0 +1,91 @@
+#include "defines.h"
+#include "kozos.h"
+#include "consdrv.h"
+#include "timerdrv.h"
+#include "leddrv.h"
+#include "lib.h"
+
+/* ¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Î»ÈÍѳ«»Ï¤ò¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+static void send_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);
+}
+
+/* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎϤò¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+static void send_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);
+}
+
+/* ¥¿¥¤¥Þ¤Î¥«¥¦¥ó¥È³«»Ï¤ò¥¿¥¤¥Þ¡¦¥É¥é¥¤¥Ð¤Ë°ÍÍꤹ¤ë */
+static void send_start(int msec)
+{
+  struct timerreq *req;
+  req = kz_kmalloc(sizeof(*req));
+  req->id = MSGBOX_ID_CONSINPUT;
+  req->msec = msec;
+  kz_send(MSGBOX_ID_TIMDRIVE, TIMERDRV_CMD_START, (char *)req);
+}
+
+static void send_led_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);
+}
+
+int command_main(int argc, char *argv[])
+{
+  char *p;
+  int size;
+
+  send_use(SERIAL_DEFAULT_DEVICE);
+
+  while (1) {
+    send_write("command> "); /* ¥×¥í¥ó¥×¥Èɽ¼¨ */
+
+    /* ¥³¥ó¥½¡¼¥ë¤«¤é¤Î¼õ¿®Ê¸»úÎó¤ò¼õ¤±¼è¤ë */
+    kz_recv(MSGBOX_ID_CONSINPUT, &size, &p);
+    if (p == NULL) {
+      send_write("expired.\n");
+      continue;
+    }
+    p[size] = '\0';
+
+    if (!strncmp(p, "echo", 4)) { /* echo¥³¥Þ¥ó¥É */
+      send_write(p + 4); /* echo¤Ë³¤¯Ê¸»úÎó¤ò½ÐÎϤ¹¤ë */
+      send_write("\n");
+    } else if (!strncmp(p, "timer", 4)) { /* timer¥³¥Þ¥ó¥É */
+      send_write("timer start.\n");
+      send_start(1000);
+    } else if (!strncmp(p, "led1", 4)) {
+      send_led_toggle(0);
+    } else if (!strncmp(p, "led2", 4)) {
+      send_led_toggle(1);
+    } else if (!strncmp(p, "ledg", 4)) {
+      send_led_toggle(2);
+    } else if (!strncmp(p, "ledr", 4)) {
+      send_led_toggle(3);
+    } else {
+      send_write("unknown.\n");
+    }
+
+    kz_kmfree(p);
+  }
+
+  return 0;
+}
diff --git a/firm/06/os/consdrv.c b/firm/06/os/consdrv.c
new file mode 100644 (file)
index 0000000..3b02db7
--- /dev/null
@@ -0,0 +1,187 @@
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "interrupt.h"
+#include "serial.h"
+#include "lib.h"
+#include "consdrv.h"
+
+#define CONS_BUFFER_SIZE 24
+
+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];
+
+/*
+ * °Ê²¼¤Î£²¤Ä¤Î´Ø¿ô(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 consdrv_main(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/06/os/consdrv.h b/firm/06/os/consdrv.h
new file mode 100644 (file)
index 0000000..0439eef
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _CONSDRV_H_INCLUDED_
+#define _CONSDRV_H_INCLUDED_
+
+#define CONSDRV_DEVICE_NUM 1
+#define CONSDRV_CMD_USE   'u' /* ¥³¥ó¥½¡¼¥ë¡¦¥É¥é¥¤¥Ð¤Î»ÈÍѳ«»Ï */
+#define CONSDRV_CMD_WRITE 'w' /* ¥³¥ó¥½¡¼¥ë¤Ø¤Îʸ»úÎó½ÐÎÏ */
+
+#endif
diff --git a/firm/06/os/defines.h b/firm/06/os/defines.h
new file mode 100644 (file)
index 0000000..d13f64b
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _DEFINES_H_INCLUDED_
+#define _DEFINES_H_INCLUDED_
+
+#define NULL ((void *)0)
+#define SERIAL_DEFAULT_DEVICE 1
+#define TIMER_DEFAULT_DEVICE  1
+
+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_NUM
+} kz_msgbox_id_t;
+
+#endif
diff --git a/firm/06/os/interrupt.c b/firm/06/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/06/os/interrupt.h b/firm/06/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/06/os/intr.h b/firm/06/os/intr.h
new file mode 100644 (file)
index 0000000..d31c9a0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _INTR_H_INCLUDED_
+#define _INTR_H_INCLUDED_
+
+/* ¥½¥Õ¥È¥¦¥¨¥¢¡¦³ä¹þ¤ß¥Ù¥¯¥¿¤ÎÄêµÁ */
+
+#define SOFTVEC_TYPE_NUM     4
+
+#define SOFTVEC_TYPE_SOFTERR 0
+#define SOFTVEC_TYPE_SYSCALL 1
+#define SOFTVEC_TYPE_SERINTR 2
+#define SOFTVEC_TYPE_TIMINTR 3
+
+#endif
diff --git a/firm/06/os/kozos.c b/firm/06/os/kozos.c
new file mode 100644 (file)
index 0000000..8a25eba
--- /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 8
+#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/06/os/kozos.h b/firm/06/os/kozos.h
new file mode 100644 (file)
index 0000000..768ee54
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _KOZOS_H_INCLUDED_
+#define _KOZOS_H_INCLUDED_
+
+#include "defines.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[]);
+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);
+
+/* ¥·¥¹¥Æ¥à¡¦¥¿¥¹¥¯ */
+int consdrv_main(int argc, char *argv[]);
+int timerdrv_main(int argc, char *argv[]);
+int leddrv_main(int argc, char *argv[]);
+
+/* ¥æ¡¼¥¶¡¦¥¿¥¹¥¯ */
+int command_main(int argc, char *argv[]);
+int clock_main(int argc, char *argv[]);
+int rotenc_main(int argc, char *argv[]);
+
+#endif
diff --git a/firm/06/os/lcd.c b/firm/06/os/lcd.c
new file mode 100644 (file)
index 0000000..0392bc5
--- /dev/null
@@ -0,0 +1,398 @@
+#include "lcd.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 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 lcd_init(void)
+{
+  *H8_3069F_P4DDR = BIT_LCD_RES;
+
+  /*
+   * 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 lcd_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 lcd_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 lcd_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) {
+        lcd_set_pixel(y, x, 0);
+      } else {
+        lcd_set_pixel(y, x, 1);
+      }
+    } else {
+      if (reverse) {
+        lcd_set_pixel(x, y, 0);
+      } else {
+        lcd_set_pixel(x, y, 1);
+      }
+    }
+    error = error - deltay;
+    if (error < 0) {
+      y = y + ystep;
+      error = error + deltax;
+    }
+  }
+}
+
+void lcd_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 reverse)
+{
+  int x, y;
+  for (x = x1; x <= x2; x++) {
+    if (reverse) {
+      lcd_set_pixel(x, y1, 0);
+      lcd_set_pixel(x, y2, 0);
+    } else {
+      lcd_set_pixel(x, y1, 1);
+      lcd_set_pixel(x, y2, 1);
+    }
+  }
+  for (y = y1; y <= y2; y++) {
+    if (reverse) {
+      lcd_set_pixel(x1, y, 0);
+      lcd_set_pixel(x2, y, 0);
+    } else {
+      lcd_set_pixel(x1, y, 1);
+      lcd_set_pixel(x2, y, 1);
+    }
+  }
+}
+
+void lcd_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) {
+        lcd_set_pixel(x, y, 0);
+      } else {
+        lcd_set_pixel(x, y, 1);
+      }
+    }
+  }
+}
+
+void lcd_draw_string(uint8 x, uint8 y, char *str, uint8 reverse)
+{
+  char *p = str;
+  int cnt = 0;
+  while (*p) {
+    lcd_draw_char(x + (FONT_X * cnt), y, *p, reverse);
+    p++;
+    cnt++;
+  }
+}
+
+void lcd_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) {
+            lcd_set_pixel(x + i, y + j, 0);
+          } else {
+            lcd_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            lcd_set_pixel(x + i, y + j, 1);
+          } else {
+            lcd_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) {
+            lcd_set_pixel(x + i, y + j, 0);
+          } else {
+            lcd_set_pixel(x + i, y + j, 1);
+          }
+        } else {
+          if (reverse) {
+            lcd_set_pixel(x + i, y + j, 1);
+          } else {
+            lcd_set_pixel(x + i, y + j, 0);
+          }
+        }
+      }
+    }
+  }
+}
+
+void lcd_draw_checkbox(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint8 state, uint8 reverse)
+{
+  lcd_draw_box(x1, y1, x2, y2, reverse);
+  if (state) {
+    lcd_draw_line(x1, y1, x2, y2, reverse);
+    lcd_draw_line(x1, y2, x2, y1, reverse);
+  }
+}
+
+void lcd_draw_progressbar(
+    uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse)
+{
+  lcd_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;
+  lcd_fill_box(x1 + 1, y1 + 1, x1 + pix - 1, y2 - 1, reverse);
+  lcd_fill_box(x1 + pix, y1 + 1, x2 - 1, y2 - 1, !reverse);
+}
+
diff --git a/firm/06/os/lcd.h b/firm/06/os/lcd.h
new file mode 100644 (file)
index 0000000..4092c20
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _LCD_H_INCLUDED_
+#define _LCD_H_INCLUDED_
+
+#include "defines.h"
+
+void lcd_init(void);
+void lcd_clear(void);
+void lcd_set_pixel(int x, int y, int reverse);
+void lcd_draw_line(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_draw_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_fill_box(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 reverse);
+void lcd_draw_string(uint8 x, uint8 y, char *str, uint8 reverse);
+void lcd_draw_char(uint8 x, uint8 y, char c, uint8 reverse);
+void lcd_draw_checkbox(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    uint8 state, uint8 reverse);
+void lcd_draw_progressbar(uint16 x1, uint16 y1, uint16 x2, uint16 y2,
+    int min, int max, int value, uint8 reverse);
+
+#endif
+
diff --git a/firm/06/os/ld.scr b/firm/06/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/06/os/led.c b/firm/06/os/led.c
new file mode 100644 (file)
index 0000000..f918d3a
--- /dev/null
@@ -0,0 +1,99 @@
+#include "led.h"
+#include "defines.h"
+
+#define H8_3069F_PADDR  ((volatile uint8 *)0xFEE009)
+#define H8_3069F_PADR   ((volatile uint8 *)0xFFFFD9)
+
+#define MASK_LEDG   (1 << 2)
+#define MASK_LEDR   (1 << 3)
+#define MASK_LED1   (1 << 6)
+#define MASK_LED2   (1 << 7)
+
+int led_init(void)
+{
+  volatile uint8 mask = MASK_LED1 | MASK_LED2 | MASK_LEDG | MASK_LEDR;
+
+  /*
+   * ¥Ý¡¼¥È¥Ç¥£¥ì¥¯¥·¥ç¥ó¤òÀßÄꤹ¤ëÁ°¤Ë¥Ç¡¼¥¿¥ì¥¸¥¹¥¿¤ò½é´ü²½¤¹¤ë¡£
+   * ÉéÏÀÍý¤Ê¤Î¤Ç¡¢½é´üÃͤΥ¼¥í¤À¤È½ÐÎϤˤ·¤¿»þÅÀ¤ÇÅÀÅô¾õÂ֤Ȥʤ롣
+   */
+  *H8_3069F_PADR |= mask;
+
+  /*
+   * ¥Ý¡¼¥ÈA¤Î¥Ó¥Ã¥È2,3,6,7¤Ï½ÐÎϥݡ¼¥È¤È¤·¤ÆÀßÄꤹ¤ë¡£
+   *
+   * ¥Ç¡¼¥¿¥Ç¥£¥ì¥¯¥·¥ç¥ó¥ì¥¸¥¹¥¿¤ÏWrite Only¤Ê¤Î¤Ç¡¢
+   * Â¾¤Î¥Ó¥Ã¥È¤ÎÀßÄ꤬ɬÍפˤʤä¿»þÅÀ¤Ç¡¢
+   * ¥Ý¡¼¥ÈÆþ½ÐÎÏÀßÄê¤ò¤Þ¤È¤á¤Æ´ÉÍý¤¹¤ë¤è¤¦¤Ê
+   * ²¿¤é¤«¤ÎÂкö¤¬É¬ÍפȤʤë¤À¤í¤¦¡£
+   */
+  *H8_3069F_PADDR = 0xCC;
+
+  return 0;
+}
+
+int led_write(led_target_t target, led_state_t state)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = MASK_LED1;
+      break;
+    case Led2:
+      mask = MASK_LED2;
+      break;
+    case LedG:
+      mask = MASK_LEDG;
+      break;
+    case LedR:
+      mask = MASK_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  switch (state) {
+    case LedOn:
+      *H8_3069F_PADR &= ~mask;
+      break;
+    case LedOff:
+      *H8_3069F_PADR |= mask;
+      break;
+    default:
+      return -1;
+  }
+
+  return 0;
+}
+
+int led_toggle(led_target_t target)
+{
+  volatile uint8 mask = 0x00;
+
+  switch (target) {
+    case Led1:
+      mask = MASK_LED1;
+      break;
+    case Led2:
+      mask = MASK_LED2;
+      break;
+    case LedG:
+      mask = MASK_LEDG;
+      break;
+    case LedR:
+      mask = MASK_LEDR;
+      break;
+    default:
+      return -1;
+  }
+
+  if (*H8_3069F_PADR & mask) {
+    *H8_3069F_PADR &= ~mask;
+  } else {
+    *H8_3069F_PADR |= mask;
+  }
+
+  return 0;
+}
+
diff --git a/firm/06/os/led.h b/firm/06/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/06/os/leddrv.c b/firm/06/os/leddrv.c
new file mode 100644 (file)
index 0000000..0ff8505
--- /dev/null
@@ -0,0 +1,40 @@
+#include "leddrv.h"
+#include "led.h"
+#include "kozos.h"
+
+/* \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 leddrv_main(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/06/os/leddrv.h b/firm/06/os/leddrv.h
new file mode 100644 (file)
index 0000000..84f41ba
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _LEDDRV_H_INCLUDED_
+#define _LEDDRV_H_INCLUDED_
+
+#define LEDDRV_CMD_LED_ON       'o' /* LED¤ÎÅÀÅô */
+#define LEDDRV_CMD_LED_OFF      'x' /* LED¤Î¾ÃÅô */
+#define LEDDRV_CMD_LED_TOGGLE   't' /* LED¤Î¥È¥°¥ë */
+
+#endif
diff --git a/firm/06/os/lib.c b/firm/06/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/06/os/lib.h b/firm/06/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/06/os/main.c b/firm/06/os/main.c
new file mode 100644 (file)
index 0000000..1293a94
--- /dev/null
@@ -0,0 +1,36 @@
+#include "defines.h"
+#include "kozos.h"
+#include "interrupt.h"
+#include "lib.h"
+
+/* ¥·¥¹¥Æ¥à¡¦¥¿¥¹¥¯¤È¥æ¡¼¥¶¡¦¥¿¥¹¥¯¤Îµ¯Æ° */
+static int start_threads(int argc, char *argv[])
+{
+  kz_run(consdrv_main,  "consdrv",  1, 0x200, 0, NULL);
+  kz_run(command_main,  "command",  8, 0x200, 0, NULL);
+  kz_run(timerdrv_main, "timerdrv", 2, 0x100, 0, NULL);
+  kz_run(leddrv_main,   "leddrv",   7, 0x100, 0, NULL);
+  kz_run(clock_main,    "clock",    9, 0x100, 0, NULL);
+  kz_run(rotenc_main,   "rotenc",  10, 0x100, 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/06/os/memory.c b/firm/06/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/06/os/memory.h b/firm/06/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/06/os/re.c b/firm/06/os/re.c
new file mode 100644 (file)
index 0000000..af73317
--- /dev/null
@@ -0,0 +1,23 @@
+#include "re.h"
+
+#define H8_3069F_TMDR       ((volatile uint8 *)0xFFFF62)
+#define H8_3069F_TSTR       ((volatile uint8 *)0xFFFF60)
+#define H8_3069F_16TCNT2H   ((volatile uint8 *)0xFFFF7A)
+#define H8_3069F_16TCNT2L   ((volatile uint8 *)0xFFFF7B)
+
+#define TMDR_BIT_MDF    (1 << 6)
+#define TSTR_BIT_STR2   (1 << 2)
+
+int re_init(void)
+{
+  *H8_3069F_TMDR = TMDR_BIT_MDF;
+  *H8_3069F_TSTR = TSTR_BIT_STR2;
+
+  return 0;
+}
+
+uint16 re_read(void)
+{
+  return ((*H8_3069F_16TCNT2H) << 8) | (*H8_3069F_16TCNT2L << 0);
+}
+
diff --git a/firm/06/os/re.h b/firm/06/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/06/os/rotenc.c b/firm/06/os/rotenc.c
new file mode 100644 (file)
index 0000000..b17a195
--- /dev/null
@@ -0,0 +1,67 @@
+#include "defines.h"
+#include "kozos.h"
+#include "lib.h"
+#include "consdrv.h"
+#include "rotenc.h"
+#include "re.h"
+#include "leddrv.h"
+
+/* \e$B%3%s%=!<%k$X$NJ8;zNs=PNO$r%3%s%=!<%k!&%I%i%$%P$K0MMj$9$k\e(B */
+static void send_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);
+}
+
+static void send_led_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);
+}
+
+static void send_led_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);
+}
+
+int rotenc_main(int argc, char *argv[])
+{
+  re_init();
+
+  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) {
+          send_write("<-\n");
+          send_led_toggle(2);
+          send_led_write(3, 0);
+        }
+      } else {
+        if (dir < 32) {
+          send_write("->\n");
+          send_led_write(2, 0);
+          send_led_toggle(3);
+        }
+      }
+      prev = curr;
+    }
+  }
+
+  return 0;
+}
diff --git a/firm/06/os/rotenc.h b/firm/06/os/rotenc.h
new file mode 100644 (file)
index 0000000..1bb9b68
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _REDRV_H_INCLUDED_
+#define _REDRV_H_INCLUDED_
+
+#define REDRV_CMD_ACTION_WAIT   'w' /* ÆþÎϤòÂԤĠ*/
+
+#endif
diff --git a/firm/06/os/serial.c b/firm/06/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/06/os/serial.h b/firm/06/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/06/os/startup.s b/firm/06/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/06/os/sw.c b/firm/06/os/sw.c
new file mode 100644 (file)
index 0000000..391b26d
--- /dev/null
@@ -0,0 +1,31 @@
+#include "sw.h"
+
+#define H8_3069F_P7DR   ((volatile uint8 *)0xFFFFD6)
+#define H8_3069F_PADR   ((volatile uint8 *)0xFFFFD9)
+
+#define SW_BIT_P7_SW1   (1 << 0)
+#define SW_BIT_P7_SW2   (1 << 1)
+#define SW_BIT_PA_SWRE  (1 << 4)
+
+int sw_init(void)
+{
+  return 0;
+}
+
+uint8 sw_read(sw_target_t target)
+{
+  uint8 c = 0;
+  switch (target) {
+    case Sw1:
+      c = (*H8_3069F_P7DR & SW_BIT_P7_SW1) ? 0 : 1;
+      break;
+    case Sw2:
+      c = (*H8_3069F_P7DR & SW_BIT_P7_SW2) ? 0 : 1;
+      break;
+    case SwRe:
+      c = (*H8_3069F_PADR & SW_BIT_PA_SWRE) ? 0 : 1;
+      break;
+  }
+  return c;
+}
+
diff --git a/firm/06/os/sw.h b/firm/06/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/06/os/syscall.c b/firm/06/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/06/os/syscall.h b/firm/06/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/06/os/timer.c b/firm/06/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/06/os/timer.h b/firm/06/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/06/os/timerdrv.c b/firm/06/os/timerdrv.c
new file mode 100644 (file)
index 0000000..0cf787b
--- /dev/null
@@ -0,0 +1,124 @@
+#include "defines.h"
+#include "kozos.h"
+#include "intr.h"
+#include "interrupt.h"
+#include "timer.h"
+#include "lib.h"
+#include "timerdrv.h"
+
+struct timerbuf {
+  struct timerbuf *next;
+  kz_msgbox_id_t id; /* ¥¿¥¤¥ÞËþλ»þ¤Î¥á¥Ã¥»¡¼¥¸Á÷¿®Àè */
+  int msec;
+};
+
+static struct timerreg {
+  struct timerbuf *timers; /* ¥¿¥¤¥Þ¡¦¥Ð¥Ã¥Õ¥¡¤Î¥ê¥ó¥¯¥ê¥¹¥È */
+  int index; /* ÍøÍѤ¹¤ë¥¿¥¤¥Þ¤ÎÈÖ¹æ */
+} timerreg;
+
+/*
+ * °Ê²¼¤Ï³ä¹þ¤ß¥Ï¥ó¥É¥é¤Ç¤¢¤ê¡¤ÈóƱ´ü¤Ç¸Æ¤Ð¤ì¤ë¤Î¤Ç¡¤¥é¥¤¥Ö¥é¥ê´Ø¿ô¤Ê¤É¤ò
+ * ¸Æ¤Ó½Ð¤¹¾ì¹ç¤Ë¤ÏÃí°Õ¤¬É¬Íס¥
+ * ´ðËܤȤ·¤Æ¡¤°Ê²¼¤Î¤¤¤º¤ì¤«¤ËÅö¤Æ¤Ï¤Þ¤ë´Ø¿ô¤·¤«¸Æ¤Ó½Ð¤·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * ¡¦ºÆÆþ²Äǽ¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤Ï̵¤¤´Ø¿ô¤Ç¤¢¤ë¡¥
+ * ¡¦¥¹¥ì¥Ã¥É¤«¤é¸Æ¤Ð¤ì¤ë¤³¤È¤¬¤¢¤ë¤¬¡¤³ä¹þ¤ß¶Ø»ß¤Ç¸Æ¤Ó½Ð¤·¤Æ¤¤¤ë¡¥
+ * ¤Þ¤¿Èó¥³¥ó¥Æ¥­¥¹¥È¾õÂ֤ǸƤФì¤ë¤¿¤á¡¤¥·¥¹¥Æ¥à¡¦¥³¡¼¥ë¤ÏÍøÍѤ·¤Æ¤Ï¤¤¤±¤Ê¤¤¡¥
+ * (¥µ¡¼¥Ó¥¹¡¦¥³¡¼¥ë¤òÍøÍѤ¹¤ë¤³¤È)
+ */
+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 timerdrv_main(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/06/os/timerdrv.h b/firm/06/os/timerdrv.h
new file mode 100644 (file)
index 0000000..8ca0040
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef _TIMERDRV_H_INCLUDED_
+#define _TIMERDRV_H_INCLUDED_
+
+#define TIMERDRV_DEVICE_NUM 1
+#define TIMERDRV_CMD_EXPIRE 'e' /* ¥¿¥¤¥ÞËþλ */
+#define TIMERDRV_CMD_START  's' /* ¥¿¥¤¥Þ¤Î¥¹¥¿¡¼¥È */
+
+struct timerreq {
+  kz_msgbox_id_t id; /* ¥¿¥¤¥ÞËþλ»þ¤Î¥á¥Ã¥»¡¼¥¸Á÷¿®Àè */
+  int msec;
+};
+
+#endif