{"id":74,"date":"2008-09-25T01:53:19","date_gmt":"2008-09-25T08:53:19","guid":{"rendered":"http:\/\/imagecraft.wordpress.com\/?p=74"},"modified":"2008-09-25T01:53:19","modified_gmt":"2008-09-25T08:53:19","slug":"emos-whitepaper","status":"publish","type":"post","link":"https:\/\/imagecraft.com\/?p=74","title":{"rendered":"eMOS Whitepaper"},"content":{"rendered":"<h1>eMOS &#8211; an embedded message passing real time OS<\/h1>\n<p>eMOS is a real time OS for embedded systems with a preemptive message passing kernel at its core. The message passing API provides a uniform model for supporting additional software stacks such as UART driver, File System, USB stack, TCP\/IP and CAN library etc.<\/p>\n<p><!--more--><\/p>\n<h2>Design Principles<\/h2>\n<p class=\"MsoBodyText\">eMOS is designed for embedded microcontrollers. It can be used on low end 8 bits AVR microcontrollers with 8K of flash and 2K of RAM to 32 bits ARM devices with lots of memory. The microkernel API takes just a few K bytes and can be used by itself in minimal systems to provide basic multiasking services.<\/p>\n<p class=\"MsoBodyText\">In designing the eMOS tasking model, we feel that a preemptive priority based round robin scheduler is the simplest model for users, allowing the natural \u201cfunctions as tasks\u201d style of writing programs. It places no restriction on how users may structure their code and users do not need to work around the tasking model. To minimize resource consumption, a separate kernel stack is used by the kernel calls, so that tasks would not duplicate the resource needed for by kernel calls. For the advance users, scheduling APIs provide the control needed to further minimize task scheduling and resource consumption.<\/p>\n<p class=\"MsoBodyText\">For process synchronization and interprocess communication, we adopt the message passing semantics made popular by OS such as QNX. A set of 3 primitives provides a robust and fast solution to both synchronization and interprocess communication requirements. Priority inversion is handled automatically as well. For simpler needs, eMOS also provides semaphores.<\/p>\n<p class=\"MsoBodyText\">As many embedded systems are used in low power situations, eMOS includes timer API and provides hooks to the idle task so that you may place the system in low power mode to conserve power, to be awaken by interrupts or timer events.<\/p>\n<p class=\"MsoBodyText\">The general philosophy is to provide flexibility rather than optimizing the design for a particular niche (e.g. memory constraint devices). Thus eMOS uses dynamic memory allocation (via a best-fit always-merge allocator to lessen memory fragmentation) and places no arbitrary limits on the number of tasks or task priorities and allow dynamic task creation and deletion. This approach allows eMOS to scale up and down except to the most memory constrainted situations.<\/p>\n<p class=\"MsoBodyText\">In theory, scheduling algorithm is f(n) where n is the number of tasks in the READY state and task allocation is affected by the memory allocator. However in practice, these should not be worse than other schemes in any meaningful way as the number of READY tasks are few and allocation is fast.<\/p>\n<pre>\/* eMOS\n\u00a0* Copyright (C) 2008 ImageCraft Creations Inc. All Right Reserved.\n\u00a0* info@imagecraft.com http:\/\/www.imagecraft.com\n\u00a0*\/\n\n\/* fucntion that returns a status:\n\u00a0* status &gt;= 0, function succeeded\n\u00a0* 0 &gt; status,\u00a0 function failed\n\u00a0*\/\n\n\/* uKERNEL AND SCHEDULER API\n\u00a0*\/\n\/* initialize eMOS, must be call first *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  int\u00a0 eMOS_SysInit(void);\n\/* start eMOS scheduler *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 int\u00a0 eMOS_SysStart(void);\n\/* arrange \"func\" to be called when the system is idle *\/\u00a0\u00a0\u00a0  int\u00a0 eMOS_SysIdleHook(void (*func)(void));\n\/* return non-zero if there are runnable tasks *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  int\u00a0 eMOS_isSysBusy(void);\n\/* return non-zero if all other tasks are waiting *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int\u00a0 eMOS_isSysWait(void);\n\n\/* create a task and return the process ID *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  int\u00a0 eMOS_TaskCreate(void (*func)(void), unsigned stacksize, unsigned prio, unsigned hw_stacksize);\n\/* give up processing time *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  void eMOS_TaskYield(void);\n\/* hibernate *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 void eMOS_TaskHibernate(void);\n\/* wake a task from hibernation, can be called from ISR *\/\u00a0\u00a0\u00a0 int\u00a0 eMOS_TaskWakeup(void);\n\/* kill a task *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  int eMOS_TaskKill(int pid);\n\n\/* temporarily disable the scheduler, any syscall will\n\u00a0\u00a0 also re-enable it *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 void eMOS_SchedOff(void);\n\/* re-enable the scheduler *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  void eMOS_SchedOn(void);\n\n\/* MESSAGE PASSING API\n\u00a0* if the buffer lengths do not match between the send\/receive or send\/reply calls,\n\u00a0* then the shorter len is used\n\u00a0*\/\n\/* send a message and wait until a reply *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 int eMOS_MsgSend(void *sendbuf, int sendlen, void *reqbuf, int reqlen);\n\/* (wait and) receive a message *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 int eMOS_MsgReceive(void *recbuf, int reclen);\n\/* reply to a request *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int eMOS_MsgReply(void *reqbuf, int reqlen);\n\n\/* SEMAPHORE API\n\u00a0*\/\n\/* create a semaphore *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int eMOS_SemCreate(void);\n\/* lock a semaphore, wait if not available *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  int eMOS_SemLock(int semid);\n\/* unlock a semaphore *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int eMOS_SemUnlock(int semid);\n\n\/* Timer, RTC, etc.\n\u00a0*\/\n\/* sleep for X seconds *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  void eMOS_Sleep(int secs);\n\/* sleep for X milliseconds *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 void eMOS_SleepMs(int msecs);\n\/* set the RTC clock *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 void eMOS_ClkPut(unsigned long time);\n\/* get the RTC clock *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 unsigned long eMOS_ClkGet(void);\n\/* arrange \"func\" to be called for the system tick ISR *\/\u00a0\u00a0\u00a0  void eMOS_SystemTickISRHook(void (*func)(void));\n\/* set the current time *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 void eMOS_TimePut(unsigned long time);\n\/* get the current time *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 unsigned long eMOS_TimeGet(void);\n\n\/* MEMORY MANAGEMENT API\n\u00a0* Default allocator is best-fit always-merge\n\u00a0*\/\n\/* set the system free space range *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  void eMOS_FreeSpace(unsigned begin, unsigned end);\n\/* allocate memory and zero out the content *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 void *eMOS_MemAlloc(unsigned size);\n\/* free memory *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  void eMOS_MemFree(void * ptr);\n\n\/* Ring Buffer UART\n\u00a0*\/\n\/* initialize the COM port subsystem *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 void eMOS_ComInit(void);\n\/* open a COM port and set the ring buffer size *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 int\u00a0 eMOS_ComOpen(int portn, int n);\n\/* close a COM port *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 int\u00a0 eMOS_ComClose(void);\n\/* ??? *\/ eMOS_ComTerm();\n\/* read a character and wait if none is available *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int\u00a0 eMOS_ComRead(int com);\n\/* write a character *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 int\u00a0 eMOS_ComWrite(int c);\n\/* ISR for putting a character into the output buffer *\/\u00a0\u00a0\u00a0   void eMOS_ComISRPut(void);\n\/* ISR for getting a character into the input buffer *\/\u00a0\u00a0\u00a0 \u00a0\u00a0 void eMOS_ComISRGet(void);\n\/* read a string and wait if no input is available *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0  char *eMOS_ComGets(int com, char *buf, int size);\n\/* write a string *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0   int\u00a0 eMOS_ComPuts(char *buf);\n\/* return non-zero if input is available *\/\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0 int\u00a0 eMOS_ComReady(int com);<\/pre>\n<p class=\"MsoBodyText\"><!--[if !supportEmptyParas]--> <!--[endif]--><\/p>\n","protected":false},"excerpt":{"rendered":"<p>eMOS &#8211; an embedded message passing real time OS eMOS is a real time OS for embedded systems with a preemptive message passing kernel at its core. The message passing API provides a uniform model for supporting additional software stacks such as UART driver, File System, USB stack, TCP\/IP and CAN library etc.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"footnotes":""},"categories":[8],"tags":[70,145],"class_list":["post-74","post","type-post","status-publish","format-standard","hentry","category-new-product","tag-emos","tag-rtos"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/imagecraft.com\/index.php?rest_route=\/wp\/v2\/posts\/74","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/imagecraft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/imagecraft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/imagecraft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/imagecraft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=74"}],"version-history":[{"count":0,"href":"https:\/\/imagecraft.com\/index.php?rest_route=\/wp\/v2\/posts\/74\/revisions"}],"wp:attachment":[{"href":"https:\/\/imagecraft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=74"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/imagecraft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=74"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/imagecraft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=74"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}