From c3e216f09bd31bbe23f6e2b5da90f501a4df3b0b Mon Sep 17 00:00:00 2001 From: Shinichiro Nakamura Date: Tue, 29 May 2012 19:06:45 +0900 Subject: [PATCH] Copied from 05. --- firm/06/bootload/KL-01 | 117 +++++++++ firm/06/bootload/LICENSE | 6 + firm/06/bootload/Makefile | 72 ++++++ firm/06/bootload/defines.h | 11 + firm/06/bootload/dram.c | 202 +++++++++++++++ firm/06/bootload/dram.h | 12 + firm/06/bootload/elf.c | 94 +++++++ firm/06/bootload/elf.h | 6 + firm/06/bootload/interrupt.c | 30 +++ firm/06/bootload/interrupt.h | 26 ++ firm/06/bootload/intr.S | 107 ++++++++ firm/06/bootload/intr.h | 13 + firm/06/bootload/lcd.c | 398 +++++++++++++++++++++++++++++ firm/06/bootload/lcd.h | 23 ++ firm/06/bootload/ld.scr | 75 ++++++ firm/06/bootload/led.c | 99 ++++++++ firm/06/bootload/led.h | 21 ++ firm/06/bootload/lib.c | 135 ++++++++++ firm/06/bootload/lib.h | 18 ++ firm/06/bootload/main.c | 157 ++++++++++++ firm/06/bootload/re.c | 23 ++ firm/06/bootload/re.h | 10 + firm/06/bootload/serial.c | 112 +++++++++ firm/06/bootload/serial.h | 10 + firm/06/bootload/startup.s | 10 + firm/06/bootload/sw.c | 31 +++ firm/06/bootload/sw.h | 16 ++ firm/06/bootload/vector.c | 25 ++ firm/06/bootload/xmodem.c | 94 +++++++ firm/06/bootload/xmodem.h | 6 + firm/06/os/KL-01 | 117 +++++++++ firm/06/os/LICENSE | 6 + firm/06/os/Makefile | 68 +++++ firm/06/os/clock.c | 69 ++++++ firm/06/os/command.c | 91 +++++++ firm/06/os/consdrv.c | 187 ++++++++++++++ firm/06/os/consdrv.h | 8 + firm/06/os/defines.h | 25 ++ firm/06/os/interrupt.c | 30 +++ firm/06/os/interrupt.h | 26 ++ firm/06/os/intr.h | 13 + firm/06/os/kozos.c | 578 +++++++++++++++++++++++++++++++++++++++++++ firm/06/os/kozos.h | 46 ++++ firm/06/os/lcd.c | 398 +++++++++++++++++++++++++++++ firm/06/os/lcd.h | 23 ++ firm/06/os/ld.scr | 70 ++++++ firm/06/os/led.c | 99 ++++++++ firm/06/os/led.h | 21 ++ firm/06/os/leddrv.c | 40 +++ firm/06/os/leddrv.h | 8 + firm/06/os/lib.c | 135 ++++++++++ firm/06/os/lib.h | 18 ++ firm/06/os/main.c | 36 +++ firm/06/os/memory.c | 117 +++++++++ firm/06/os/memory.h | 8 + firm/06/os/re.c | 23 ++ firm/06/os/re.h | 10 + firm/06/os/rotenc.c | 67 +++++ firm/06/os/rotenc.h | 6 + firm/06/os/serial.c | 154 ++++++++++++ firm/06/os/serial.h | 16 ++ firm/06/os/startup.s | 23 ++ firm/06/os/sw.c | 31 +++ firm/06/os/sw.h | 16 ++ firm/06/os/syscall.c | 143 +++++++++++ firm/06/os/syscall.h | 83 +++++++ firm/06/os/timer.c | 136 ++++++++++ firm/06/os/timer.h | 13 + firm/06/os/timerdrv.c | 124 ++++++++++ firm/06/os/timerdrv.h | 13 + 70 files changed, 5054 insertions(+) create mode 100644 firm/06/bootload/KL-01 create mode 100644 firm/06/bootload/LICENSE create mode 100644 firm/06/bootload/Makefile create mode 100644 firm/06/bootload/defines.h create mode 100644 firm/06/bootload/dram.c create mode 100644 firm/06/bootload/dram.h create mode 100644 firm/06/bootload/elf.c create mode 100644 firm/06/bootload/elf.h create mode 100644 firm/06/bootload/interrupt.c create mode 100644 firm/06/bootload/interrupt.h create mode 100644 firm/06/bootload/intr.S create mode 100644 firm/06/bootload/intr.h create mode 100644 firm/06/bootload/lcd.c create mode 100644 firm/06/bootload/lcd.h create mode 100644 firm/06/bootload/ld.scr create mode 100644 firm/06/bootload/led.c create mode 100644 firm/06/bootload/led.h create mode 100644 firm/06/bootload/lib.c create mode 100644 firm/06/bootload/lib.h create mode 100644 firm/06/bootload/main.c create mode 100644 firm/06/bootload/re.c create mode 100644 firm/06/bootload/re.h create mode 100644 firm/06/bootload/serial.c create mode 100644 firm/06/bootload/serial.h create mode 100644 firm/06/bootload/startup.s create mode 100644 firm/06/bootload/sw.c create mode 100644 firm/06/bootload/sw.h create mode 100644 firm/06/bootload/vector.c create mode 100644 firm/06/bootload/xmodem.c create mode 100644 firm/06/bootload/xmodem.h create mode 100644 firm/06/os/KL-01 create mode 100644 firm/06/os/LICENSE create mode 100644 firm/06/os/Makefile create mode 100644 firm/06/os/clock.c create mode 100644 firm/06/os/command.c create mode 100644 firm/06/os/consdrv.c create mode 100644 firm/06/os/consdrv.h create mode 100644 firm/06/os/defines.h create mode 100644 firm/06/os/interrupt.c create mode 100644 firm/06/os/interrupt.h create mode 100644 firm/06/os/intr.h create mode 100644 firm/06/os/kozos.c create mode 100644 firm/06/os/kozos.h create mode 100644 firm/06/os/lcd.c create mode 100644 firm/06/os/lcd.h create mode 100644 firm/06/os/ld.scr create mode 100644 firm/06/os/led.c create mode 100644 firm/06/os/led.h create mode 100644 firm/06/os/leddrv.c create mode 100644 firm/06/os/leddrv.h create mode 100644 firm/06/os/lib.c create mode 100644 firm/06/os/lib.h create mode 100644 firm/06/os/main.c create mode 100644 firm/06/os/memory.c create mode 100644 firm/06/os/memory.h create mode 100644 firm/06/os/re.c create mode 100644 firm/06/os/re.h create mode 100644 firm/06/os/rotenc.c create mode 100644 firm/06/os/rotenc.h create mode 100644 firm/06/os/serial.c create mode 100644 firm/06/os/serial.h create mode 100644 firm/06/os/startup.s create mode 100644 firm/06/os/sw.c create mode 100644 firm/06/os/sw.h create mode 100644 firm/06/os/syscall.c create mode 100644 firm/06/os/syscall.h create mode 100644 firm/06/os/timer.c create mode 100644 firm/06/os/timer.h create mode 100644 firm/06/os/timerdrv.c create mode 100644 firm/06/os/timerdrv.h diff --git a/firm/06/bootload/KL-01 b/firm/06/bootload/KL-01 new file mode 100644 index 0000000..335ecb7 --- /dev/null +++ b/firm/06/bootload/KL-01 @@ -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 index 0000000..6128b3b --- /dev/null +++ b/firm/06/bootload/LICENSE @@ -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 index 0000000..a9a50eb --- /dev/null +++ b/firm/06/bootload/Makefile @@ -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 index 0000000..e7dcac8 --- /dev/null +++ b/firm/06/bootload/defines.h @@ -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 index 0000000..d3e5662 --- /dev/null +++ b/firm/06/bootload/dram.c @@ -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 index 0000000..b5d2d90 --- /dev/null +++ b/firm/06/bootload/dram.h @@ -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 index 0000000..965d0a5 --- /dev/null +++ b/firm/06/bootload/elf.c @@ -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 index 0000000..c6ed725 --- /dev/null +++ b/firm/06/bootload/elf.h @@ -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 index 0000000..0a02225 --- /dev/null +++ b/firm/06/bootload/interrupt.c @@ -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 index 0000000..ce8df6e --- /dev/null +++ b/firm/06/bootload/interrupt.h @@ -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 index 0000000..c8324eb --- /dev/null +++ b/firm/06/bootload/intr.S @@ -0,0 +1,107 @@ +#include "intr.h" + .h8300h + .section .text + + .global _intr_softerr +# .type _intr_softerr,@function +_intr_softerr: + mov.l er6,@-er7 + mov.l er5,@-er7 + mov.l er4,@-er7 + mov.l er3,@-er7 + mov.l er2,@-er7 + mov.l er1,@-er7 + mov.l er0,@-er7 + mov.l er7,er1 + mov.l #_intrstack,sp + mov.l er1,@-er7 + mov.w #SOFTVEC_TYPE_SOFTERR,r0 + jsr @_interrupt + mov.l @er7+,er1 + mov.l er1,er7 + mov.l @er7+,er0 + mov.l @er7+,er1 + mov.l @er7+,er2 + mov.l @er7+,er3 + mov.l @er7+,er4 + mov.l @er7+,er5 + mov.l @er7+,er6 + rte + + .global _intr_syscall +# .type _intr_syscall,@function +_intr_syscall: + mov.l er6,@-er7 + mov.l er5,@-er7 + mov.l er4,@-er7 + mov.l er3,@-er7 + mov.l er2,@-er7 + mov.l er1,@-er7 + mov.l er0,@-er7 + mov.l er7,er1 + mov.l #_intrstack,sp + mov.l er1,@-er7 + mov.w #SOFTVEC_TYPE_SYSCALL,r0 + jsr @_interrupt + mov.l @er7+,er1 + mov.l er1,er7 + mov.l @er7+,er0 + mov.l @er7+,er1 + mov.l @er7+,er2 + mov.l @er7+,er3 + mov.l @er7+,er4 + mov.l @er7+,er5 + mov.l @er7+,er6 + rte + + .global _intr_serintr +# .type _intr_serintr,@function +_intr_serintr: + mov.l er6,@-er7 + mov.l er5,@-er7 + mov.l er4,@-er7 + mov.l er3,@-er7 + mov.l er2,@-er7 + mov.l er1,@-er7 + mov.l er0,@-er7 + mov.l er7,er1 + mov.l #_intrstack,sp + mov.l er1,@-er7 + mov.w #SOFTVEC_TYPE_SERINTR,r0 + jsr @_interrupt + mov.l @er7+,er1 + mov.l er1,er7 + mov.l @er7+,er0 + mov.l @er7+,er1 + mov.l @er7+,er2 + mov.l @er7+,er3 + mov.l @er7+,er4 + mov.l @er7+,er5 + mov.l @er7+,er6 + rte + + .global _intr_timintr +# .type _intr_timintr,@function +_intr_timintr: + mov.l er6,@-er7 + mov.l er5,@-er7 + mov.l er4,@-er7 + mov.l er3,@-er7 + mov.l er2,@-er7 + mov.l er1,@-er7 + mov.l er0,@-er7 + mov.l er7,er1 + mov.l #_intrstack,sp + mov.l er1,@-er7 + mov.w #SOFTVEC_TYPE_TIMINTR,r0 + jsr @_interrupt + mov.l @er7+,er1 + mov.l er1,er7 + mov.l @er7+,er0 + mov.l @er7+,er1 + mov.l @er7+,er2 + mov.l @er7+,er3 + mov.l @er7+,er4 + mov.l @er7+,er5 + mov.l @er7+,er6 + rte diff --git a/firm/06/bootload/intr.h b/firm/06/bootload/intr.h new file mode 100644 index 0000000..d31c9a0 --- /dev/null +++ b/firm/06/bootload/intr.h @@ -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 index 0000000..0392bc5 --- /dev/null +++ b/firm/06/bootload/lcd.c @@ -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 index 0000000..4092c20 --- /dev/null +++ b/firm/06/bootload/lcd.h @@ -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 index 0000000..4ce149c --- /dev/null +++ b/firm/06/bootload/ld.scr @@ -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 index 0000000..f918d3a --- /dev/null +++ b/firm/06/bootload/led.c @@ -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 index 0000000..cd12388 --- /dev/null +++ b/firm/06/bootload/led.h @@ -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 index 0000000..04a6afb --- /dev/null +++ b/firm/06/bootload/lib.c @@ -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 index 0000000..54009be --- /dev/null +++ b/firm/06/bootload/lib.h @@ -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 index 0000000..3fbbbe1 --- /dev/null +++ b/firm/06/bootload/main.c @@ -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 index 0000000..af73317 --- /dev/null +++ b/firm/06/bootload/re.c @@ -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 index 0000000..de5e3bf --- /dev/null +++ b/firm/06/bootload/re.h @@ -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 index 0000000..1f30bbf --- /dev/null +++ b/firm/06/bootload/serial.c @@ -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 index 0000000..27a5c20 --- /dev/null +++ b/firm/06/bootload/serial.h @@ -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 index 0000000..8ba4038 --- /dev/null +++ b/firm/06/bootload/startup.s @@ -0,0 +1,10 @@ + .h8300h + .section .text + .global _start +# .type _start,@function +_start: + mov.l #_bootstack,sp + jsr @_main + +1: + bra 1b diff --git a/firm/06/bootload/sw.c b/firm/06/bootload/sw.c new file mode 100644 index 0000000..391b26d --- /dev/null +++ b/firm/06/bootload/sw.c @@ -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 index 0000000..65e1133 --- /dev/null +++ b/firm/06/bootload/sw.h @@ -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 index 0000000..3ddd93b --- /dev/null +++ b/firm/06/bootload/vector.c @@ -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 index 0000000..dfde193 --- /dev/null +++ b/firm/06/bootload/xmodem.c @@ -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 index 0000000..c090f17 --- /dev/null +++ b/firm/06/bootload/xmodem.h @@ -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 index 0000000..335ecb7 --- /dev/null +++ b/firm/06/os/KL-01 @@ -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 index 0000000..6128b3b --- /dev/null +++ b/firm/06/os/LICENSE @@ -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 index 0000000..8d7316d --- /dev/null +++ b/firm/06/os/Makefile @@ -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 index 0000000..c4b923a --- /dev/null +++ b/firm/06/os/clock.c @@ -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 index 0000000..13d8296 --- /dev/null +++ b/firm/06/os/command.c @@ -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 index 0000000..3b02db7 --- /dev/null +++ b/firm/06/os/consdrv.c @@ -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 index 0000000..0439eef --- /dev/null +++ b/firm/06/os/consdrv.h @@ -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 index 0000000..d13f64b --- /dev/null +++ b/firm/06/os/defines.h @@ -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 index 0000000..0a02225 --- /dev/null +++ b/firm/06/os/interrupt.c @@ -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 index 0000000..ce8df6e --- /dev/null +++ b/firm/06/os/interrupt.h @@ -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 index 0000000..d31c9a0 --- /dev/null +++ b/firm/06/os/intr.h @@ -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 index 0000000..8a25eba --- /dev/null +++ b/firm/06/os/kozos.c @@ -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(¤t->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(¤t->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 index 0000000..768ee54 --- /dev/null +++ b/firm/06/os/kozos.h @@ -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 index 0000000..0392bc5 --- /dev/null +++ b/firm/06/os/lcd.c @@ -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 index 0000000..4092c20 --- /dev/null +++ b/firm/06/os/lcd.h @@ -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 index 0000000..f1a2f15 --- /dev/null +++ b/firm/06/os/ld.scr @@ -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 index 0000000..f918d3a --- /dev/null +++ b/firm/06/os/led.c @@ -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 index 0000000..cd12388 --- /dev/null +++ b/firm/06/os/led.h @@ -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 index 0000000..0ff8505 --- /dev/null +++ b/firm/06/os/leddrv.c @@ -0,0 +1,40 @@ +#include "leddrv.h" +#include "led.h" +#include "kozos.h" + +/* $B%9%l%C%I$+$i$NMW5a$r=hM}$9$k(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 index 0000000..84f41ba --- /dev/null +++ b/firm/06/os/leddrv.h @@ -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 index 0000000..04a6afb --- /dev/null +++ b/firm/06/os/lib.c @@ -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 index 0000000..54009be --- /dev/null +++ b/firm/06/os/lib.h @@ -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 index 0000000..1293a94 --- /dev/null +++ b/firm/06/os/main.c @@ -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 index 0000000..75925d0 --- /dev/null +++ b/firm/06/os/memory.c @@ -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 index 0000000..260b191 --- /dev/null +++ b/firm/06/os/memory.h @@ -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 index 0000000..af73317 --- /dev/null +++ b/firm/06/os/re.c @@ -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 index 0000000..de5e3bf --- /dev/null +++ b/firm/06/os/re.h @@ -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 index 0000000..b17a195 --- /dev/null +++ b/firm/06/os/rotenc.c @@ -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" + +/* $B%3%s%=!<%k$X$NJ8;zNs=PNO$r%3%s%=!<%k!&%I%i%$%P$K0MMj$9$k(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 index 0000000..1bb9b68 --- /dev/null +++ b/firm/06/os/rotenc.h @@ -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 index 0000000..8ff4ea4 --- /dev/null +++ b/firm/06/os/serial.c @@ -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 index 0000000..bebf693 --- /dev/null +++ b/firm/06/os/serial.h @@ -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 index 0000000..e6b0d36 --- /dev/null +++ b/firm/06/os/startup.s @@ -0,0 +1,23 @@ + .h8300h + .section .text + .global _start +# .type _start,@function +_start: + mov.l #_bootstack,sp + jsr @_main + +1: + bra 1b + + .global _dispatch +# .type _dispatch,@function +_dispatch: + mov.l @er0,er7 + mov.l @er7+,er0 + mov.l @er7+,er1 + mov.l @er7+,er2 + mov.l @er7+,er3 + mov.l @er7+,er4 + mov.l @er7+,er5 + mov.l @er7+,er6 + rte diff --git a/firm/06/os/sw.c b/firm/06/os/sw.c new file mode 100644 index 0000000..391b26d --- /dev/null +++ b/firm/06/os/sw.c @@ -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 index 0000000..65e1133 --- /dev/null +++ b/firm/06/os/sw.h @@ -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 index 0000000..744d715 --- /dev/null +++ b/firm/06/os/syscall.c @@ -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, ¶m); + 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, ¶m); + return param.un.wait.ret; +} + +int kz_sleep(void) +{ + kz_syscall_param_t param; + kz_syscall(KZ_SYSCALL_TYPE_SLEEP, ¶m); + 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, ¶m); + return param.un.wakeup.ret; +} + +kz_thread_id_t kz_getid(void) +{ + kz_syscall_param_t param; + kz_syscall(KZ_SYSCALL_TYPE_GETID, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + 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, ¶m); + return param.un.send.ret; +} diff --git a/firm/06/os/syscall.h b/firm/06/os/syscall.h new file mode 100644 index 0000000..65e0061 --- /dev/null +++ b/firm/06/os/syscall.h @@ -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 index 0000000..9af5ba0 --- /dev/null +++ b/firm/06/os/timer.c @@ -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 index 0000000..3ce7039 --- /dev/null +++ b/firm/06/os/timer.h @@ -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 index 0000000..0cf787b --- /dev/null +++ b/firm/06/os/timerdrv.c @@ -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 index 0000000..8ca0040 --- /dev/null +++ b/firm/06/os/timerdrv.h @@ -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 -- 2.11.0